PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | site/class/smtp.php +1555 -0 1.6.1 → 1.8.16 View file →
@@ -1,0 +1,1555 @@
1 +<?php
2 +/**
3 + * @package VikBooking
4 + * @subpackage com_vikbooking
5 + * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 + * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 + * @license GNU General Public License version 2 or later; see LICENSE
8 + * @link https://vikwp.com
9 + */
10 +
11 +defined('ABSPATH') or die('No script kiddies please!');
12 +
13 +class smtp_class
14 +{
15 +/*
16 +{metadocument}
17 + <variable>
18 + <name>user</name>
19 + <type>STRING</type>
20 + <value></value>
21 + <documentation>
22 + <purpose>Define the authorized user when sending messages to a SMTP
23 + server.</purpose>
24 + <usage>Set this variable to the user name when the SMTP server
25 + requires authentication.</usage>
26 + </documentation>
27 + </variable>
28 +{/metadocument}
29 +*/
30 + var $user="";
31 +
32 +/*
33 +{metadocument}
34 + <variable>
35 + <name>realm</name>
36 + <type>STRING</type>
37 + <value></value>
38 + <documentation>
39 + <purpose>Define the authentication realm when sending messages to a
40 + SMTP server.</purpose>
41 + <usage>Set this variable when the SMTP server requires
42 + authentication and if more than one authentication realm is
43 + supported.</usage>
44 + </documentation>
45 + </variable>
46 +{/metadocument}
47 +*/
48 + var $realm="";
49 +
50 +/*
51 +{metadocument}
52 + <variable>
53 + <name>password</name>
54 + <type>STRING</type>
55 + <value></value>
56 + <documentation>
57 + <purpose>Define the authorized user password when sending messages
58 + to a SMTP server.</purpose>
59 + <usage>Set this variable to the user password when the SMTP server
60 + requires authentication.</usage>
61 + </documentation>
62 + </variable>
63 +{/metadocument}
64 +*/
65 + var $password="";
66 +
67 +/*
68 +{metadocument}
69 + <variable>
70 + <name>workstation</name>
71 + <type>STRING</type>
72 + <value></value>
73 + <documentation>
74 + <purpose>Define the client workstation name when sending messages
75 + to a SMTP server.</purpose>
76 + <usage>Set this variable to the client workstation when the SMTP
77 + server requires authentication identifiying the origin workstation
78 + name.</usage>
79 + </documentation>
80 + </variable>
81 +{/metadocument}
82 +*/
83 + var $workstation="";
84 +
85 +/*
86 +{metadocument}
87 + <variable>
88 + <name>authentication_mechanism</name>
89 + <type>STRING</type>
90 + <value></value>
91 + <documentation>
92 + <purpose>Force the use of a specific authentication mechanism.</purpose>
93 + <usage>Set it to an empty string to let the class determine the
94 + authentication mechanism to use automatically based on the
95 + supported mechanisms by the server and by the SASL client library
96 + classes.<paragraphbreak />
97 + Set this variable to a specific mechanism name if you want to
98 + override the automatic authentication mechanism selection.</usage>
99 + </documentation>
100 + </variable>
101 +{/metadocument}
102 +*/
103 + var $authentication_mechanism="";
104 +
105 +/*
106 +{metadocument}
107 + <variable>
108 + <name>host_name</name>
109 + <type>STRING</type>
110 + <value></value>
111 + <documentation>
112 + <purpose>Define the SMTP server host name.</purpose>
113 + <usage>Set to the host name of the SMTP server to which you want to
114 + relay the messages.</usage>
115 + </documentation>
116 + </variable>
117 +{/metadocument}
118 +*/
119 + var $host_name="";
120 +
121 +/*
122 +{metadocument}
123 + <variable>
124 + <name>host_post</name>
125 + <type>INTEGER</type>
126 + <value>25</value>
127 + <documentation>
128 + <purpose>Define the SMTP server host port.</purpose>
129 + <usage>Set to the TCP port of the SMTP server host to connect.</usage>
130 + </documentation>
131 + </variable>
132 +{/metadocument}
133 +*/
134 + var $host_port=25;
135 +
136 +/*
137 +{metadocument}
138 + <variable>
139 + <name>ssl</name>
140 + <type>BOOLEAN</type>
141 + <value>0</value>
142 + <documentation>
143 + <purpose>Define whether the connection to the SMTP server should be
144 + established securely using SSL protocol.</purpose>
145 + <usage>Set to <booleanvalue>1</booleanvalue> if the SMTP server
146 + requires secure connections using SSL protocol.</usage>
147 + </documentation>
148 + </variable>
149 +{/metadocument}
150 +*/
151 + var $ssl=0;
152 +
153 +/*
154 +{metadocument}
155 + <variable>
156 + <name>start_tls</name>
157 + <type>BOOLEAN</type>
158 + <value>0</value>
159 + <documentation>
160 + <purpose>Define whether the connection to the SMTP server should use
161 + encryption after the connection is established using TLS
162 + protocol.</purpose>
163 + <usage>Set to <booleanvalue>1</booleanvalue> if the SMTP server
164 + requires that authentication be done securely starting the TLS
165 + protocol after the connection is established.</usage>
166 + </documentation>
167 + </variable>
168 +{/metadocument}
169 +*/
170 + var $start_tls = 0;
171 +
172 +/*
173 +{metadocument}
174 + <variable>
175 + <name>localhost</name>
176 + <type>STRING</type>
177 + <value></value>
178 + <documentation>
179 + <purpose>Name of the local host computer</purpose>
180 + <usage>Set to the name of the computer connecting to the SMTP
181 + server from the local network.</usage>
182 + </documentation>
183 + </variable>
184 +{/metadocument}
185 +*/
186 + var $localhost="";
187 +
188 +/*
189 +{metadocument}
190 + <variable>
191 + <name>timeout</name>
192 + <type>INTEGER</type>
193 + <value>0</value>
194 + <documentation>
195 + <purpose>Specify the connection timeout period in seconds.</purpose>
196 + <usage>Leave it set to <integervalue>0</integervalue> if you want
197 + the connection attempts to wait forever. Change this value if for
198 + some reason the timeout period seems insufficient or otherwise it
199 + seems too long.</usage>
200 + </documentation>
201 + </variable>
202 +{/metadocument}
203 +*/
204 + var $timeout=0;
205 +
206 +/*
207 +{metadocument}
208 + <variable>
209 + <name>data_timeout</name>
210 + <type>INTEGER</type>
211 + <value>0</value>
212 + <documentation>
213 + <purpose>Specify the timeout period in seconds to wait for data from
214 + the server.</purpose>
215 + <usage>Leave it set to <integervalue>0</integervalue> if you want
216 + to use the same value defined in the
217 + <variablelink>timeout</variablelink> variable. Change this value
218 + if for some reason the default data timeout period seems
219 + insufficient or otherwise it seems too long.</usage>
220 + </documentation>
221 + </variable>
222 +{/metadocument}
223 +*/
224 + var $data_timeout=0;
225 +
226 +/*
227 +{metadocument}
228 + <variable>
229 + <name>direct_delivery</name>
230 + <type>BOOLEAN</type>
231 + <value>0</value>
232 + <documentation>
233 + <purpose>Boolean flag that indicates whether the message should be
234 + sent in direct delivery mode, i.e. the message is sent to the SMTP
235 + server associated to the domain of the recipient instead of
236 + relaying to the server specified by the
237 + <variablelink>host_name</variablelink> variable.</purpose>
238 + <usage>Set this to <tt><booleanvalue>1</booleanvalue></tt> if you
239 + want to send urgent messages directly to the recipient domain SMTP
240 + server.</usage>
241 + </documentation>
242 + </variable>
243 +{/metadocument}
244 +*/
245 + var $direct_delivery=0;
246 +
247 +/*
248 +{metadocument}
249 + <variable>
250 + <name>error</name>
251 + <type>STRING</type>
252 + <value></value>
253 + <documentation>
254 + <purpose>Message that describes the error when a call to a class
255 + function fails.</purpose>
256 + <usage>Check this variable when an error occurs to understand what
257 + happened.</usage>
258 + </documentation>
259 + </variable>
260 +{/metadocument}
261 +*/
262 + var $error="";
263 +
264 +/*
265 +{metadocument}
266 + <variable>
267 + <name>debug</name>
268 + <type>BOOLEAN</type>
269 + <value>0</value>
270 + <documentation>
271 + <purpose>Specify whether it is necessary to output SMTP connection
272 + debug information.</purpose>
273 + <usage>Set this variable to
274 + <tt><booleanvalue>1</booleanvalue></tt> if you need to see
275 + the progress of the SMTP connection and protocol dialog when you
276 + need to understand the reason for delivery problems.</usage>
277 + </documentation>
278 + </variable>
279 +{/metadocument}
280 +*/
281 + var $debug=0;
282 +
283 +/*
284 +{metadocument}
285 + <variable>
286 + <name>html_debug</name>
287 + <type>BOOLEAN</type>
288 + <value>0</value>
289 + <documentation>
290 + <purpose>Specify whether the debug information should be outputted in
291 + HTML format.</purpose>
292 + <usage>Set this variable to
293 + <tt><booleanvalue>1</booleanvalue></tt> if you need to see
294 + the debug output in a Web page.</usage>
295 + </documentation>
296 + </variable>
297 +{/metadocument}
298 +*/
299 + var $html_debug=0;
300 +
301 +/*
302 +{metadocument}
303 + <variable>
304 + <name>esmtp</name>
305 + <type>BOOLEAN</type>
306 + <value>1</value>
307 + <documentation>
308 + <purpose>Specify whether the class should attempt to use ESMTP
309 + extensions supported by the server.</purpose>
310 + <usage>Set this variable to
311 + <tt><booleanvalue>0</booleanvalue></tt> if for some reason you
312 + want to avoid benefitting from ESMTP extensions.</usage>
313 + </documentation>
314 + </variable>
315 +{/metadocument}
316 +*/
317 + var $esmtp=1;
318 +
319 +/*
320 +{metadocument}
321 + <variable>
322 + <name>esmtp_extensions</name>
323 + <type>HASH</type>
324 + <value></value>
325 + <documentation>
326 + <purpose>Associative array with the list of ESMTP extensions
327 + supported by the SMTP server.</purpose>
328 + <usage>Check this variable after connecting to the SMTP server to
329 + determine which ESMTP extensions are supported.</usage>
330 + </documentation>
331 + </variable>
332 +{/metadocument}
333 +*/
334 + var $esmtp_extensions=array();
335 +
336 +/*
337 +{metadocument}
338 + <variable>
339 + <name>exclude_address</name>
340 + <type>STRING</type>
341 + <value></value>
342 + <documentation>
343 + <purpose>Specify an address that should be considered invalid
344 + when resolving host name addresses.</purpose>
345 + <usage>In some networks any domain name that does not exist is
346 + resolved as a sub-domain of the default local domain. If the DNS is
347 + configured in such way that it always resolves any sub-domain of
348 + the default local domain to a given address, it is hard to
349 + determine whether a given domain does not exist.<paragraphbreak />
350 + If your network is configured this way, you may set this variable
351 + to the address that all sub-domains of the default local domain
352 + resolves, so the class can assume that such address is invalid.</usage>
353 + </documentation>
354 + </variable>
355 +{/metadocument}
356 +*/
357 + var $exclude_address="";
358 +
359 +/*
360 +{metadocument}
361 + <variable>
362 + <name>getmxrr</name>
363 + <type>STRING</type>
364 + <value>getmxrr</value>
365 + <documentation>
366 + <purpose>Specify the name of the function that is called to determine
367 + the SMTP server address of a given domain.</purpose>
368 + <usage>Change this to a working replacement of the PHP
369 + <tt>getmxrr()</tt> function if this is not working in your system
370 + and you want to send messages in direct delivery mode.</usage>
371 + </documentation>
372 + </variable>
373 +{/metadocument}
374 +*/
375 + var $getmxrr="GetMXRR";
376 +
377 +/*
378 +{metadocument}
379 + <variable>
380 + <name>pop3_auth_host</name>
381 + <type>STRING</type>
382 + <value></value>
383 + <documentation>
384 + <purpose>Specify the server address for POP3 based authentication.</purpose>
385 + <usage>Set this variable to the address of the POP3 server if the
386 + SMTP server requires POP3 based authentication.</usage>
387 + </documentation>
388 + </variable>
389 +{/metadocument}
390 +*/
391 + var $pop3_auth_host="";
392 +
393 +/*
394 +{metadocument}
395 + <variable>
396 + <name>pop3_auth_port</name>
397 + <type>INTEGER</type>
398 + <value>110</value>
399 + <documentation>
400 + <purpose>Specify the server port for POP3 based authentication.</purpose>
401 + <usage>Set this variable to the port of the POP3 server if the
402 + SMTP server requires POP3 based authentication.</usage>
403 + </documentation>
404 + </variable>
405 +{/metadocument}
406 +*/
407 + var $pop3_auth_port=110;
408 +
409 + /* private variables - DO NOT ACCESS */
410 +
411 + var $state="Disconnected";
412 + var $connection=0;
413 + var $pending_recipients=0;
414 + var $next_token="";
415 + var $direct_sender="";
416 + var $connected_domain="";
417 + var $result_code;
418 + var $disconnected_error=0;
419 + var $esmtp_host="";
420 + var $maximum_piped_recipients=100;
421 +
422 + /* Private methods - DO NOT CALL */
423 +
424 + Function Tokenize($string,$separator="")
425 + {
426 + if(!strcmp($separator,""))
427 + {
428 + $separator=$string;
429 + $string=$this->next_token;
430 + }
431 + for($character=0;$character<strlen($separator);$character++)
432 + {
433 + if(GetType($position=strpos($string,$separator[$character]))=="integer")
434 + $found=(IsSet($found) ? min($found,$position) : $position);
435 + }
436 + if(IsSet($found))
437 + {
438 + $this->next_token=substr($string,$found+1);
439 + return(substr($string,0,$found));
440 + }
441 + else
442 + {
443 + $this->next_token="";
444 + return($string);
445 + }
446 + }
447 +
448 + Function OutputDebug($message)
449 + {
450 + $message.="\n";
451 + if($this->html_debug)
452 + $message=str_replace("\n","<br />\n",HtmlEntities($message));
453 + echo $message;
454 + flush();
455 + }
456 +
457 + Function SetDataAccessError($error)
458 + {
459 + $this->error=$error;
460 + if(function_exists("socket_get_status"))
461 + {
462 + $status=socket_get_status($this->connection);
463 + if($status["timed_out"])
464 + $this->error.=": data access time out";
465 + elseif($status["eof"])
466 + {
467 + $this->error.=": the server disconnected";
468 + $this->disconnected_error=1;
469 + }
470 + }
471 + }
472 +
473 + Function GetLine()
474 + {
475 + for($line="";;)
476 + {
477 + if(feof($this->connection))
478 + {
479 + $this->error="reached the end of data while reading from the SMTP server conection";
480 + return("");
481 + }
482 + if(GetType($data=@fgets($this->connection,100))!="string"
483 + || strlen($data)==0)
484 + {
485 + $this->SetDataAccessError("it was not possible to read line from the SMTP server");
486 + return("");
487 + }
488 + $line.=$data;
489 + $length=strlen($line);
490 + if($length>=2
491 + && substr($line,$length-2,2)=="\r\n")
492 + {
493 + $line=substr($line,0,$length-2);
494 + if($this->debug)
495 + $this->OutputDebug("S $line");
496 + return($line);
497 + }
498 + }
499 + }
500 +
501 + Function PutLine($line)
502 + {
503 + if($this->debug)
504 + $this->OutputDebug("C $line");
505 + if(!@fputs($this->connection,"$line\r\n"))
506 + {
507 + $this->SetDataAccessError("it was not possible to send a line to the SMTP server");
508 + return(0);
509 + }
510 + return(1);
511 + }
512 +
513 + Function PutData(&$data)
514 + {
515 + if(strlen($data))
516 + {
517 + if($this->debug)
518 + $this->OutputDebug("C $data");
519 + if(!@fputs($this->connection,$data))
520 + {
521 + $this->SetDataAccessError("it was not possible to send data to the SMTP server");
522 + return(0);
523 + }
524 + }
525 + return(1);
526 + }
527 +
528 + Function VerifyResultLines($code,&$responses)
529 + {
530 + $responses=array();
531 + Unset($this->result_code);
532 + while(strlen($line=$this->GetLine($this->connection)))
533 + {
534 + if(IsSet($this->result_code))
535 + {
536 + if(strcmp($this->Tokenize($line," -"),$this->result_code))
537 + {
538 + $this->error=$line;
539 + return(0);
540 + }
541 + }
542 + else
543 + {
544 + $this->result_code=$this->Tokenize($line," -");
545 + if(GetType($code)=="array")
546 + {
547 + for($codes=0;$codes<count($code) && strcmp($this->result_code,$code[$codes]);$codes++);
548 + if($codes>=count($code))
549 + {
550 + $this->error=$line;
551 + return(0);
552 + }
553 + }
554 + else
555 + {
556 + if(strcmp($this->result_code,$code))
557 + {
558 + $this->error=$line;
559 + return(0);
560 + }
561 + }
562 + }
563 + $responses[]=$this->Tokenize("");
564 + if(!strcmp($this->result_code,$this->Tokenize($line," ")))
565 + return(1);
566 + }
567 + return(-1);
568 + }
569 +
570 + Function FlushRecipients()
571 + {
572 + if($this->pending_sender)
573 + {
574 + if($this->VerifyResultLines("250",$responses)<=0)
575 + return(0);
576 + $this->pending_sender=0;
577 + }
578 + for(;$this->pending_recipients;$this->pending_recipients--)
579 + {
580 + if($this->VerifyResultLines(array("250","251"),$responses)<=0)
581 + return(0);
582 + }
583 + return(1);
584 + }
585 +
586 + Function ConnectToHost($domain, $port, $resolve_message)
587 + {
588 + if($this->ssl)
589 + {
590 + $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
591 + $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
592 + if($php_version<4003000)
593 + return("establishing SSL connections requires at least PHP version 4.3.0");
594 + if(!function_exists("extension_loaded")
595 + || !extension_loaded("openssl"))
596 + return("establishing SSL connections requires the OpenSSL extension enabled");
597 + }
598 + if(function_exists('preg_match') ? preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $domain) : ereg('^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$',$domain))
599 + $ip=$domain;
600 + else
601 + {
602 + if($this->debug)
603 + $this->OutputDebug($resolve_message);
604 + if(!strcmp($ip=@gethostbyname($domain),$domain))
605 + return("could not resolve host \"".$domain."\"");
606 + }
607 + if(strlen($this->exclude_address)
608 + && !strcmp(@gethostbyname($this->exclude_address),$ip))
609 + return("domain \"".$domain."\" resolved to an address excluded to be valid");
610 + if($this->debug)
611 + $this->OutputDebug("Connecting to host address \"".$ip."\" port ".$port."...");
612 + if(($this->connection=($this->timeout ? @fsockopen(($this->ssl ? "ssl://" : "").$ip,$port,$errno,$error,$this->timeout) : @fsockopen(($this->ssl ? "ssl://" : "").$ip,$port))))
613 + return("");
614 + $error=($this->timeout ? strval($error) : "??");
615 + switch($error)
616 + {
617 + case "-3":
618 + return("-3 socket could not be created");
619 + case "-4":
620 + return("-4 dns lookup on hostname \"".$domain."\" failed");
621 + case "-5":
622 + return("-5 connection refused or timed out");
623 + case "-6":
624 + return("-6 fdopen() call failed");
625 + case "-7":
626 + return("-7 setvbuf() call failed");
627 + }
628 + return("could not connect to the host \"".$domain."\": ".$error);
629 + }
630 +
631 + Function SASLAuthenticate($mechanisms, $credentials, &$authenticated, &$mechanism)
632 + {
633 + $authenticated=0;
634 + if(!function_exists("class_exists")
635 + || !class_exists("sasl_client_class"))
636 + {
637 + $this->error="it is not possible to authenticate using the specified mechanism because the SASL library class is not loaded";
638 + return(0);
639 + }
640 + $sasl=new sasl_client_class;
641 + $sasl->SetCredential("user",$credentials["user"]);
642 + $sasl->SetCredential("password",$credentials["password"]);
643 + if(IsSet($credentials["realm"]))
644 + $sasl->SetCredential("realm",$credentials["realm"]);
645 + if(IsSet($credentials["workstation"]))
646 + $sasl->SetCredential("workstation",$credentials["workstation"]);
647 + if(IsSet($credentials["mode"]))
648 + $sasl->SetCredential("mode",$credentials["mode"]);
649 + do
650 + {
651 + $status=$sasl->Start($mechanisms,$message,$interactions);
652 + }
653 + while($status==SASL_INTERACT);
654 + switch($status)
655 + {
656 + case SASL_CONTINUE:
657 + break;
658 + case SASL_NOMECH:
659 + if(strlen($this->authentication_mechanism))
660 + {
661 + $this->error="authenticated mechanism ".$this->authentication_mechanism." may not be used: ".$sasl->error;
662 + return(0);
663 + }
664 + break;
665 + default:
666 + $this->error="Could not start the SASL authentication client: ".$sasl->error;
667 + return(0);
668 + }
669 + if(strlen($mechanism=$sasl->mechanism))
670 + {
671 + if($this->PutLine("AUTH ".$sasl->mechanism.(IsSet($message) ? " ".base64_encode($message) : ""))==0)
672 + {
673 + $this->error="Could not send the AUTH command";
674 + return(0);
675 + }
676 + if(!$this->VerifyResultLines(array("235","334"),$responses))
677 + return(0);
678 + switch($this->result_code)
679 + {
680 + case "235":
681 + $response="";
682 + $authenticated=1;
683 + break;
684 + case "334":
685 + $response=base64_decode($responses[0]);
686 + break;
687 + default:
688 + $this->error="Authentication error: ".$responses[0];
689 + return(0);
690 + }
691 + for(;!$authenticated;)
692 + {
693 + do
694 + {
695 + $status=$sasl->Step($response,$message,$interactions);
696 + }
697 + while($status==SASL_INTERACT);
698 + switch($status)
699 + {
700 + case SASL_CONTINUE:
701 + if($this->PutLine(base64_encode($message))==0)
702 + {
703 + $this->error="Could not send the authentication step message";
704 + return(0);
705 + }
706 + if(!$this->VerifyResultLines(array("235","334"),$responses))
707 + return(0);
708 + switch($this->result_code)
709 + {
710 + case "235":
711 + $response="";
712 + $authenticated=1;
713 + break;
714 + case "334":
715 + $response=base64_decode($responses[0]);
716 + break;
717 + default:
718 + $this->error="Authentication error: ".$responses[0];
719 + return(0);
720 + }
721 + break;
722 + default:
723 + $this->error="Could not process the SASL authentication step: ".$sasl->error;
724 + return(0);
725 + }
726 + }
727 + }
728 + return(1);
729 + }
730 +
731 + Function StartSMTP($localhost)
732 + {
733 + $success = 1;
734 + $this->esmtp_extensions = array();
735 + $fallback=1;
736 + if($this->esmtp
737 + || strlen($this->user))
738 + {
739 + if($this->PutLine('EHLO '.$localhost))
740 + {
741 + if(($success_code=$this->VerifyResultLines('250',$responses))>0)
742 + {
743 + $this->esmtp_host=$this->Tokenize($responses[0]," ");
744 + for($response=1;$response<count($responses);$response++)
745 + {
746 + $extension=strtoupper($this->Tokenize($responses[$response]," "));
747 + $this->esmtp_extensions[$extension]=$this->Tokenize("");
748 + }
749 + $success=1;
750 + $fallback=0;
751 + }
752 + else
753 + {
754 + if($success_code==0)
755 + {
756 + $code=$this->Tokenize($this->error," -");
757 + switch($code)
758 + {
759 + case "421":
760 + $fallback=0;
761 + break;
762 + }
763 + }
764 + }
765 + }
766 + else
767 + $fallback=0;
768 + }
769 + if($fallback)
770 + {
771 + if($this->PutLine("HELO $localhost")
772 + && $this->VerifyResultLines("250",$responses)>0)
773 + $success=1;
774 + }
775 + return($success);
776 + }
777 +
778 + /* Public methods */
779 +
780 +/*
781 +{metadocument}
782 + <function>
783 + <name>Connect</name>
784 + <type>BOOLEAN</type>
785 + <documentation>
786 + <purpose>Connect to an SMTP server.</purpose>
787 + <usage>Call this function as first step to send e-mail messages.</usage>
788 + <returnvalue>The function returns
789 + <tt><booleanvalue>1</booleanvalue></tt> if the connection is
790 + successfully established.</returnvalue>
791 + </documentation>
792 + <argument>
793 + <name>domain</name>
794 + <type>STRING</type>
795 + <defaultvalue></defaultvalue>
796 + <documentation>
797 + <purpose>Specify the domain of the recipient when using the direct
798 + delivery mode.</purpose>
799 + </documentation>
800 + </argument>
801 + <do>
802 +{/metadocument}
803 +*/
804 + Function Connect($domain="")
805 + {
806 + if(strcmp($this->state,"Disconnected"))
807 + {
808 + $this->error="connection is already established";
809 + return(0);
810 + }
811 + $this->disconnected_error=0;
812 + $this->error=$error="";
813 + $this->esmtp_host="";
814 + $this->esmtp_extensions=array();
815 + $hosts=array();
816 + if($this->direct_delivery)
817 + {
818 + if(strlen($domain)==0)
819 + return(1);
820 + $hosts=$weights=$mxhosts=array();
821 + $getmxrr=$this->getmxrr;
822 + if(function_exists($getmxrr)
823 + && $getmxrr($domain,$hosts,$weights))
824 + {
825 + for($host=0;$host<count($hosts);$host++)
826 + $mxhosts[$weights[$host]]=$hosts[$host];
827 + KSort($mxhosts);
828 + for(Reset($mxhosts),$host=0;$host<count($mxhosts);Next($mxhosts),$host++)
829 + $hosts[$host]=$mxhosts[Key($mxhosts)];
830 + }
831 + else
832 + {
833 + if(strcmp(@gethostbyname($domain),$domain)!=0)
834 + $hosts[]=$domain;
835 + }
836 + }
837 + else
838 + {
839 + if(strlen($this->host_name))
840 + $hosts[]=$this->host_name;
841 + if(strlen($this->pop3_auth_host))
842 + {
843 + $user=$this->user;
844 + if(strlen($user)==0)
845 + {
846 + $this->error="it was not specified the POP3 authentication user";
847 + return(0);
848 + }
849 + $password=$this->password;
850 + if(strlen($password)==0)
851 + {
852 + $this->error="it was not specified the POP3 authentication password";
853 + return(0);
854 + }
855 + $domain=$this->pop3_auth_host;
856 + $this->error=$this->ConnectToHost($domain, $this->pop3_auth_port, "Resolving POP3 authentication host \"".$domain."\"...");
857 + if(strlen($this->error))
858 + return(0);
859 + if(strlen($response=$this->GetLine())==0)
860 + return(0);
861 + if(strcmp($this->Tokenize($response," "),"+OK"))
862 + {
863 + $this->error="POP3 authentication server greeting was not found";
864 + return(0);
865 + }
866 + if(!$this->PutLine("USER ".$this->user)
867 + || strlen($response=$this->GetLine())==0)
868 + return(0);
869 + if(strcmp($this->Tokenize($response," "),"+OK"))
870 + {
871 + $this->error="POP3 authentication user was not accepted: ".$this->Tokenize("\r\n");
872 + return(0);
873 + }
874 + if(!$this->PutLine("PASS ".$password)
875 + || strlen($response=$this->GetLine())==0)
876 + return(0);
877 + if(strcmp($this->Tokenize($response," "),"+OK"))
878 + {
879 + $this->error="POP3 authentication password was not accepted: ".$this->Tokenize("\r\n");
880 + return(0);
881 + }
882 + fclose($this->connection);
883 + $this->connection=0;
884 + }
885 + }
886 + if(count($hosts)==0)
887 + {
888 + $this->error="could not determine the SMTP to connect";
889 + return(0);
890 + }
891 + for($host=0, $error="not connected";strlen($error) && $host<count($hosts);$host++)
892 + {
893 + $domain=$hosts[$host];
894 + $error=$this->ConnectToHost($domain, $this->host_port, "Resolving SMTP server domain \"$domain\"...");
895 + }
896 + if(strlen($error))
897 + {
898 + $this->error=$error;
899 + return(0);
900 + }
901 + $timeout=($this->data_timeout ? $this->data_timeout : $this->timeout);
902 + if($timeout
903 + && function_exists("socket_set_timeout"))
904 + socket_set_timeout($this->connection,$timeout,0);
905 + if($this->debug)
906 + $this->OutputDebug("Connected to SMTP server \"".$domain."\".");
907 + if(!strcmp($localhost=$this->localhost,"")
908 + && !strcmp($localhost=getenv("SERVER_NAME"),"")
909 + && !strcmp($localhost=getenv("HOST"),""))
910 + $localhost="localhost";
911 + $success=0;
912 + if($this->VerifyResultLines("220",$responses)>0)
913 + {
914 + $success = $this->StartSMTP($localhost);
915 + if($this->start_tls)
916 + {
917 + if(!IsSet($this->esmtp_extensions["STARTTLS"]))
918 + {
919 + $this->error="server does not support starting TLS";
920 + $success=0;
921 + }
922 + elseif(!function_exists('stream_socket_enable_crypto'))
923 + {
924 + $this->error="this PHP installation or version does not support starting TLS";
925 + $success=0;
926 + }
927 + elseif($success = ($this->PutLine('STARTTLS')
928 + && $this->VerifyResultLines('220',$responses)>0))
929 + {
930 + $this->OutputDebug('Starting TLS cryptograpic protocol');
931 + if(!($success = stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT)))
932 + $this->error = 'could not start TLS connection encryption protocol';
933 + else
934 + {
935 + $this->OutputDebug('TLS started');
936 + $success = $this->StartSMTP($localhost);
937 + }
938 + }
939 + }
940 + if($success
941 + && strlen($this->user)
942 + && strlen($this->pop3_auth_host)==0)
943 + {
944 + if(!IsSet($this->esmtp_extensions["AUTH"]))
945 + {
946 + $this->error="server does not require authentication";
947 + if(IsSet($this->esmtp_extensions["STARTTLS"]))
948 + $this->error .= ', it probably requires starting TLS';
949 + $success=0;
950 + }
951 + else
952 + {
953 + if(strlen($this->authentication_mechanism))
954 + $mechanisms=array($this->authentication_mechanism);
955 + else
956 + {
957 + $mechanisms=array();
958 + for($authentication=$this->Tokenize($this->esmtp_extensions["AUTH"]," ");strlen($authentication);$authentication=$this->Tokenize(" "))
959 + $mechanisms[]=$authentication;
960 + }
961 + $credentials=array(
962 + "user"=>$this->user,
963 + "password"=>$this->password
964 + );
965 + if(strlen($this->realm))
966 + $credentials["realm"]=$this->realm;
967 + if(strlen($this->workstation))
968 + $credentials["workstation"]=$this->workstation;
969 + $success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
970 + if(!$success
971 + && !strcmp($mechanism,"PLAIN"))
972 + {
973 + /*
974 + * Author: Russell Robinson, 25 May 2003, http://www.tectite.com/
975 + * Purpose: Try various AUTH PLAIN authentication methods.
976 + */
977 + $mechanisms=array("PLAIN");
978 + $credentials=array(
979 + "user"=>$this->user,
980 + "password"=>$this->password
981 + );
982 + if(strlen($this->realm))
983 + {
984 + /*
985 + * According to: http://www.sendmail.org/~ca/email/authrealms.html#authpwcheck_method
986 + * some sendmails won't accept the realm, so try again without it
987 + */
988 + $success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
989 + }
990 + if(!$success)
991 + {
992 + /*
993 + * It was seen an EXIM configuration like this:
994 + * user^password^unused
995 + */
996 + $credentials["mode"]=SASL_PLAIN_EXIM_DOCUMENTATION_MODE;
997 + $success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
998 + }
999 + if(!$success)
1000 + {
1001 + /*
1002 + * ... though: http://exim.work.de/exim-html-3.20/doc/html/spec_36.html
1003 + * specifies: ^user^password
1004 + */
1005 + $credentials["mode"]=SASL_PLAIN_EXIM_MODE;
1006 + $success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
1007 + }
1008 + }
1009 + if($success
1010 + && strlen($mechanism)==0)
1011 + {
1012 + $this->error="it is not supported any of the authentication mechanisms required by the server";
1013 + $success=0;
1014 + }
1015 + }
1016 + }
1017 + }
1018 + if($success)
1019 + {
1020 + $this->state="Connected";
1021 + $this->connected_domain=$domain;
1022 + }
1023 + else
1024 + {
1025 + fclose($this->connection);
1026 + $this->connection=0;
1027 + }
1028 + return($success);
1029 + }
1030 +/*
1031 +{metadocument}
1032 + </do>
1033 + </function>
1034 +{/metadocument}
1035 +*/
1036 +
1037 +/*
1038 +{metadocument}
1039 + <function>
1040 + <name>MailFrom</name>
1041 + <type>BOOLEAN</type>
1042 + <documentation>
1043 + <purpose>Set the address of the message sender.</purpose>
1044 + <usage>Call this function right after establishing a connection with
1045 + the <functionlink>Connect</functionlink> function.</usage>
1046 + <returnvalue>The function returns
1047 + <tt><booleanvalue>1</booleanvalue></tt> if the sender address is
1048 + successfully set.</returnvalue>
1049 + </documentation>
1050 + <argument>
1051 + <name>sender</name>
1052 + <type>STRING</type>
1053 + <documentation>
1054 + <purpose>E-mail address of the sender.</purpose>
1055 + </documentation>
1056 + </argument>
1057 + <do>
1058 +{/metadocument}
1059 +*/
1060 + Function MailFrom($sender)
1061 + {
1062 + if($this->direct_delivery)
1063 + {
1064 + switch($this->state)
1065 + {
1066 + case "Disconnected":
1067 + $this->direct_sender=$sender;
1068 + return(1);
1069 + case "Connected":
1070 + $sender=$this->direct_sender;
1071 + break;
1072 + default:
1073 + $this->error="direct delivery connection is already established and sender is already set";
1074 + return(0);
1075 + }
1076 + }
1077 + else
1078 + {
1079 + if(strcmp($this->state,"Connected"))
1080 + {
1081 + $this->error="connection is not in the initial state";
1082 + return(0);
1083 + }
1084 + }
1085 + $this->error="";
1086 + if(!$this->PutLine("MAIL FROM:<$sender>"))
1087 + return(0);
1088 + if(!IsSet($this->esmtp_extensions["PIPELINING"])
1089 + && $this->VerifyResultLines("250",$responses)<=0)
1090 + return(0);
1091 + $this->state="SenderSet";
1092 + if(IsSet($this->esmtp_extensions["PIPELINING"]))
1093 + $this->pending_sender=1;
1094 + $this->pending_recipients=0;
1095 + return(1);
1096 + }
1097 +/*
1098 +{metadocument}
1099 + </do>
1100 + </function>
1101 +{/metadocument}
1102 +*/
1103 +
1104 +/*
1105 +{metadocument}
1106 + <function>
1107 + <name>SetRecipient</name>
1108 + <type>BOOLEAN</type>
1109 + <documentation>
1110 + <purpose>Set the address of a message recipient.</purpose>
1111 + <usage>Call this function repeatedly for each recipient right after
1112 + setting the message sender with the
1113 + <functionlink>MailFrom</functionlink> function.</usage>
1114 + <returnvalue>The function returns
1115 + <tt><booleanvalue>1</booleanvalue></tt> if the recipient address is
1116 + successfully set.</returnvalue>
1117 + </documentation>
1118 + <argument>
1119 + <name>recipient</name>
1120 + <type>STRING</type>
1121 + <documentation>
1122 + <purpose>E-mail address of a recipient.</purpose>
1123 + </documentation>
1124 + </argument>
1125 + <do>
1126 +{/metadocument}
1127 +*/
1128 + Function SetRecipient($recipient)
1129 + {
1130 + if($this->direct_delivery)
1131 + {
1132 + if(GetType($at=strrpos($recipient,"@"))!="integer")
1133 + return("it was not specified a valid direct recipient");
1134 + $domain=substr($recipient,$at+1);
1135 + switch($this->state)
1136 + {
1137 + case "Disconnected":
1138 + if(!$this->Connect($domain))
1139 + return(0);
1140 + if(!$this->MailFrom(""))
1141 + {
1142 + $error=$this->error;
1143 + $this->Disconnect();
1144 + $this->error=$error;
1145 + return(0);
1146 + }
1147 + break;
1148 + case "SenderSet":
1149 + case "RecipientSet":
1150 + if(strcmp($this->connected_domain,$domain))
1151 + {
1152 + $this->error="it is not possible to deliver directly to recipients of different domains";
1153 + return(0);
1154 + }
1155 + break;
1156 + default:
1157 + $this->error="connection is already established and the recipient is already set";
1158 + return(0);
1159 + }
1160 + }
1161 + else
1162 + {
1163 + switch($this->state)
1164 + {
1165 + case "SenderSet":
1166 + case "RecipientSet":
1167 + break;
1168 + default:
1169 + $this->error="connection is not in the recipient setting state";
1170 + return(0);
1171 + }
1172 + }
1173 + $this->error="";
1174 + if(!$this->PutLine("RCPT TO:<$recipient>"))
1175 + return(0);
1176 + if(IsSet($this->esmtp_extensions["PIPELINING"]))
1177 + {
1178 + $this->pending_recipients++;
1179 + if($this->pending_recipients>=$this->maximum_piped_recipients)
1180 + {
1181 + if(!$this->FlushRecipients())
1182 + return(0);
1183 + }
1184 + }
1185 + else
1186 + {
1187 + if($this->VerifyResultLines(array("250","251"),$responses)<=0)
1188 + return(0);
1189 + }
1190 + $this->state="RecipientSet";
1191 + return(1);
1192 + }
1193 +/*
1194 +{metadocument}
1195 + </do>
1196 + </function>
1197 +{/metadocument}
1198 +*/
1199 +
1200 +/*
1201 +{metadocument}
1202 + <function>
1203 + <name>StartData</name>
1204 + <type>BOOLEAN</type>
1205 + <documentation>
1206 + <purpose>Tell the SMTP server that the message data will start being
1207 + sent.</purpose>
1208 + <usage>Call this function right after you are done setting all the
1209 + message recipients with the
1210 + <functionlink>SetRecipient</functionlink> function.</usage>
1211 + <returnvalue>The function returns
1212 + <tt><booleanvalue>1</booleanvalue></tt> if the server is ready to
1213 + start receiving the message data.</returnvalue>
1214 + </documentation>
1215 + <do>
1216 +{/metadocument}
1217 +*/
1218 + Function StartData()
1219 + {
1220 + if(strcmp($this->state,"RecipientSet"))
1221 + {
1222 + $this->error="connection is not in the start sending data state";
1223 + return(0);
1224 + }
1225 + $this->error="";
1226 + if(!$this->PutLine("DATA"))
1227 + return(0);
1228 + if($this->pending_recipients)
1229 + {
1230 + if(!$this->FlushRecipients())
1231 + return(0);
1232 + }
1233 + if($this->VerifyResultLines("354",$responses)<=0)
1234 + return(0);
1235 + $this->state="SendingData";
1236 + return(1);
1237 + }
1238 +/*
1239 +{metadocument}
1240 + </do>
1241 + </function>
1242 +{/metadocument}
1243 +*/
1244 +
1245 +/*
1246 +{metadocument}
1247 + <function>
1248 + <name>PrepareData</name>
1249 + <type>STRING</type>
1250 + <documentation>
1251 + <purpose>Prepare message data to normalize line breaks and escaping
1252 + lines that contain single dots.</purpose>
1253 + <usage>Call this function if the message data you want to send may
1254 + contain line breaks that are not the
1255 + <stringvalue>&#13;&#10;</stringvalue> sequence or it may contain
1256 + lines that just have a single dot.</usage>
1257 + <returnvalue>Resulting normalized messages data.</returnvalue>
1258 + </documentation>
1259 + <argument>
1260 + <name>data</name>
1261 + <type>STRING</type>
1262 + <documentation>
1263 + <purpose>Message data to be prepared.</purpose>
1264 + </documentation>
1265 + </argument>
1266 + <do>
1267 +{/metadocument}
1268 +*/
1269 + Function PrepareData($data)
1270 + {
1271 + if(function_exists("preg_replace"))
1272 + return(preg_replace(array("/\n\n|\r\r/","/(^|[^\r])\n/","/\r([^\n]|\$)/D","/(^|\n)\\./"),array("\r\n\r\n","\\1\r\n","\r\n\\1","\\1.."),$data));
1273 + else
1274 + return(ereg_replace("(^|\n)\\.","\\1..",ereg_replace("\r([^\n]|\$)","\r\n\\1",ereg_replace("(^|[^\r])\n","\\1\r\n",ereg_replace("\n\n|\r\r","\r\n\r\n",$data)))));
1275 + }
1276 +/*
1277 +{metadocument}
1278 + </do>
1279 + </function>
1280 +{/metadocument}
1281 +*/
1282 +
1283 +/*
1284 +{metadocument}
1285 + <function>
1286 + <name>SendData</name>
1287 + <type>BOOLEAN</type>
1288 + <documentation>
1289 + <purpose>Send message data.</purpose>
1290 + <usage>Call this function repeatedly for all message data blocks
1291 + to be sent right after start sending message data with the
1292 + <functionlink>StartData</functionlink> function.</usage>
1293 + <returnvalue>The function returns
1294 + <tt><booleanvalue>1</booleanvalue></tt> if the message data was
1295 + sent to the SMTP server successfully.</returnvalue>
1296 + </documentation>
1297 + <argument>
1298 + <name>data</name>
1299 + <type>STRING</type>
1300 + <documentation>
1301 + <purpose>Message data to be sent.</purpose>
1302 + </documentation>
1303 + </argument>
1304 + <do>
1305 +{/metadocument}
1306 +*/
1307 + Function SendData($data)
1308 + {
1309 + if(strcmp($this->state,"SendingData"))
1310 + {
1311 + $this->error="connection is not in the sending data state";
1312 + return(0);
1313 + }
1314 + $this->error="";
1315 + return($this->PutData($data));
1316 + }
1317 +/*
1318 +{metadocument}
1319 + </do>
1320 + </function>
1321 +{/metadocument}
1322 +*/
1323 +
1324 +/*
1325 +{metadocument}
1326 + <function>
1327 + <name>EndSendingData</name>
1328 + <type>BOOLEAN</type>
1329 + <documentation>
1330 + <purpose>Tell the server that all the message data was sent.</purpose>
1331 + <usage>Call this function when you are done with sending the message
1332 + data with the <functionlink>SendData</functionlink> function.</usage>
1333 + <returnvalue>The function returns
1334 + <tt><booleanvalue>1</booleanvalue></tt> if the server accepted the
1335 + message.</returnvalue>
1336 + </documentation>
1337 + <do>
1338 +{/metadocument}
1339 +*/
1340 + Function EndSendingData()
1341 + {
1342 + if(strcmp($this->state,"SendingData"))
1343 + {
1344 + $this->error="connection is not in the sending data state";
1345 + return(0);
1346 + }
1347 + $this->error="";
1348 + if(!$this->PutLine("\r\n.")
1349 + || $this->VerifyResultLines("250",$responses)<=0)
1350 + return(0);
1351 + $this->state="Connected";
1352 + return(1);
1353 + }
1354 +/*
1355 +{metadocument}
1356 + </do>
1357 + </function>
1358 +{/metadocument}
1359 +*/
1360 +
1361 +/*
1362 +{metadocument}
1363 + <function>
1364 + <name>ResetConnection</name>
1365 + <type>BOOLEAN</type>
1366 + <documentation>
1367 + <purpose>Reset an already established SMTP connection to the initial
1368 + state.</purpose>
1369 + <usage>Call this function when there was an error sending a message
1370 + and you need to skip to sending another message without
1371 + disconnecting.</usage>
1372 + <returnvalue>The function returns
1373 + <tt><booleanvalue>1</booleanvalue></tt> if the connection was
1374 + resetted successfully.</returnvalue>
1375 + </documentation>
1376 + <do>
1377 +{/metadocument}
1378 +*/
1379 + Function ResetConnection()
1380 + {
1381 + switch($this->state)
1382 + {
1383 + case "Connected":
1384 + return(1);
1385 + case "SendingData":
1386 + $this->error="can not reset the connection while sending data";
1387 + return(0);
1388 + case "Disconnected":
1389 + $this->error="can not reset the connection before it is established";
1390 + return(0);
1391 + }
1392 + $this->error="";
1393 + if(!$this->PutLine("RSET")
1394 + || $this->VerifyResultLines("250",$responses)<=0)
1395 + return(0);
1396 + $this->state="Connected";
1397 + return(1);
1398 + }
1399 +/*
1400 +{metadocument}
1401 + </do>
1402 + </function>
1403 +{/metadocument}
1404 +*/
1405 +
1406 +/*
1407 +{metadocument}
1408 + <function>
1409 + <name>Disconnect</name>
1410 + <type>BOOLEAN</type>
1411 + <documentation>
1412 + <purpose>Terminate a previously opened connection.</purpose>
1413 + <usage>Call this function after you are done sending your
1414 + messages.</usage>
1415 + <returnvalue>The function returns
1416 + <tt><booleanvalue>1</booleanvalue></tt> if the connection was
1417 + successfully closed.</returnvalue>
1418 + </documentation>
1419 + <argument>
1420 + <name>quit</name>
1421 + <type>BOOLEAN</type>
1422 + <defaultvalue>1</defaultvalue>
1423 + <documentation>
1424 + <purpose>Boolean option that tells whether the class should
1425 + perform the final connection quit handshake, or just close the
1426 + connection without waiting.</purpose>
1427 + </documentation>
1428 + </argument>
1429 + <do>
1430 +{/metadocument}
1431 +*/
1432 + Function Disconnect($quit=1)
1433 + {
1434 + if(!strcmp($this->state,"Disconnected"))
1435 + {
1436 + $this->error="it was not previously established a SMTP connection";
1437 + return(0);
1438 + }
1439 + $this->error="";
1440 + if(!strcmp($this->state,"Connected")
1441 + && $quit
1442 + && (!$this->PutLine("QUIT")
1443 + || ($this->VerifyResultLines("221",$responses)<=0
1444 + && !$this->disconnected_error)))
1445 + return(0);
1446 + if($this->disconnected_error)
1447 + $this->disconnected_error=0;
1448 + else
1449 + fclose($this->connection);
1450 + $this->connection=0;
1451 + $this->state="Disconnected";
1452 + if($this->debug)
1453 + $this->OutputDebug("Disconnected.");
1454 + return(1);
1455 + }
1456 +/*
1457 +{metadocument}
1458 + </do>
1459 + </function>
1460 +{/metadocument}
1461 +*/
1462 +
1463 +/*
1464 +{metadocument}
1465 + <function>
1466 + <name>SendMessage</name>
1467 + <type>BOOLEAN</type>
1468 + <documentation>
1469 + <purpose>Send a message in a single call.</purpose>
1470 + <usage>Call this function if you want to send a single messages to a
1471 + small number of recipients in a single call.</usage>
1472 + <returnvalue>The function returns
1473 + <tt><booleanvalue>1</booleanvalue></tt> if the message was sent
1474 + successfully.</returnvalue>
1475 + </documentation>
1476 + <argument>
1477 + <name>sender</name>
1478 + <type>STRING</type>
1479 + <documentation>
1480 + <purpose>E-mail address of the sender.</purpose>
1481 + </documentation>
1482 + </argument>
1483 + <argument>
1484 + <name>recipients</name>
1485 + <type>STRING</type>
1486 + <documentation>
1487 + <purpose>Array with a list of the e-mail addresses of the
1488 + recipients of the message.</purpose>
1489 + </documentation>
1490 + </argument>
1491 + <argument>
1492 + <name>headers</name>
1493 + <type>ARRAY</type>
1494 + <documentation>
1495 + <purpose>Array with a list of the header lines of the message.</purpose>
1496 + </documentation>
1497 + </argument>
1498 + <argument>
1499 + <name>body</name>
1500 + <type>STRING</type>
1501 + <documentation>
1502 + <purpose>Body data of the message.</purpose>
1503 + </documentation>
1504 + </argument>
1505 + <do>
1506 +{/metadocument}
1507 +*/
1508 + Function SendMessage($sender,$recipients,$headers,$body)
1509 + {
1510 + if(($success=$this->Connect()))
1511 + {
1512 + if(($success=$this->MailFrom($sender)))
1513 + {
1514 + for($recipient=0;$recipient<count($recipients);$recipient++)
1515 + {
1516 + if(!($success=$this->SetRecipient($recipients[$recipient])))
1517 + break;
1518 + }
1519 + if($success
1520 + && ($success=$this->StartData()))
1521 + {
1522 + for($header_data="",$header=0;$header<count($headers);$header++)
1523 + $header_data.=$headers[$header]."\r\n";
1524 + $success=($this->SendData($header_data."\r\n")
1525 + && $this->SendData($this->PrepareData($body))
1526 + && $this->EndSendingData());
1527 + }
1528 + }
1529 + $error=$this->error;
1530 + $disconnect_success=$this->Disconnect($success);
1531 + if($success)
1532 + $success=$disconnect_success;
1533 + else
1534 + $this->error=$error;
1535 + }
1536 + return($success);
1537 + }
1538 +/*
1539 +{metadocument}
1540 + </do>
1541 + </function>
1542 +{/metadocument}
1543 +*/
1544 +
1545 +};
1546 +
1547 +/*
1548 +
1549 +{metadocument}
1550 +</class>
1551 +{/metadocument}
1552 +
1553 +*/
1554 +
1555 +?>