remove old readme
[atutor.git] / docs / include / classes / phpmailer / class.smtp.php
1 <?php\r
2 ////////////////////////////////////////////////////\r
3 // SMTP - PHP SMTP class\r
4 //\r
5 // Version 1.02\r
6 //\r
7 // Define an SMTP class that can be used to connect\r
8 // and communicate with any SMTP server. It implements\r
9 // all the SMTP functions defined in RFC821 except TURN.\r
10 //\r
11 // Author: Chris Ryan\r
12 //\r
13 // License: LGPL, see LICENSE\r
14 ////////////////////////////////////////////////////\r
15 \r
16 /**\r
17  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP\r
18  * commands except TURN which will always return a not implemented\r
19  * error. SMTP also provides some utility methods for sending mail\r
20  * to an SMTP server.\r
21  * @package PHPMailer\r
22  * @author Chris Ryan\r
23  */\r
24 class SMTP\r
25 {\r
26     /**\r
27      *  SMTP server port\r
28      *  @var int\r
29      */\r
30     var $SMTP_PORT = 25;\r
31     \r
32     /**\r
33      *  SMTP reply line ending\r
34      *  @var string\r
35      */\r
36     var $CRLF = "\r\n";\r
37     \r
38     /**\r
39      *  Sets whether debugging is turned on\r
40      *  @var bool\r
41      */\r
42     var $do_debug;       # the level of debug to perform\r
43 \r
44     /**#@+\r
45      * @access private\r
46      */\r
47     var $smtp_conn;      # the socket to the server\r
48     var $error;          # error if any on the last call\r
49     var $helo_rply;      # the reply the server sent to us for HELO\r
50     /**#@-*/\r
51 \r
52     /**\r
53      * Initialize the class so that the data is in a known state.\r
54      * @access public\r
55      * @return void\r
56      */\r
57     function SMTP() {\r
58         $this->smtp_conn = 0;\r
59         $this->error = null;\r
60         $this->helo_rply = null;\r
61 \r
62         $this->do_debug = 0;\r
63     }\r
64 \r
65     /*************************************************************\r
66      *                    CONNECTION FUNCTIONS                  *\r
67      ***********************************************************/\r
68 \r
69     /**\r
70      * Connect to the server specified on the port specified.\r
71      * If the port is not specified use the default SMTP_PORT.\r
72      * If tval is specified then a connection will try and be\r
73      * established with the server for that number of seconds.\r
74      * If tval is not specified the default is 30 seconds to\r
75      * try on the connection.\r
76      *\r
77      * SMTP CODE SUCCESS: 220\r
78      * SMTP CODE FAILURE: 421\r
79      * @access public\r
80      * @return bool\r
81      */\r
82     function Connect($host,$port=0,$tval=30) {\r
83         # set the error val to null so there is no confusion\r
84         $this->error = null;\r
85 \r
86         # make sure we are __not__ connected\r
87         if($this->connected()) {\r
88             # ok we are connected! what should we do?\r
89             # for now we will just give an error saying we\r
90             # are already connected\r
91             $this->error =\r
92                 array("error" => "Already connected to a server");\r
93             return false;\r
94         }\r
95 \r
96         if(empty($port)) {\r
97             $port = $this->SMTP_PORT;\r
98         }\r
99 \r
100         #connect to the smtp server\r
101         $this->smtp_conn = @fsockopen($host,    # the host of the server\r
102                                      $port,    # the port to use\r
103                                      $errno,   # error number if any\r
104                                      $errstr,  # error message if any\r
105                                      $tval);   # give up after ? secs\r
106         # verify we connected properly\r
107         if(empty($this->smtp_conn)) {\r
108             $this->error = array("error" => "Failed to connect to server",\r
109                                  "errno" => $errno,\r
110                                  "errstr" => $errstr);\r
111             if($this->do_debug >= 1) {\r
112                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
113                          ": $errstr ($errno)" . $this->CRLF;\r
114             }\r
115             return false;\r
116         }\r
117 \r
118         # sometimes the SMTP server takes a little longer to respond\r
119         # so we will give it a longer timeout for the first read\r
120         // Windows still does not have support for this timeout function\r
121         if(substr(PHP_OS, 0, 3) != "WIN")\r
122            socket_set_timeout($this->smtp_conn, $tval, 0);\r
123 \r
124         # get any announcement stuff\r
125         $announce = $this->get_lines();\r
126 \r
127         # set the timeout  of any socket functions at 1/10 of a second\r
128         //if(function_exists("socket_set_timeout"))\r
129         //   socket_set_timeout($this->smtp_conn, 0, 100000);\r
130 \r
131         if($this->do_debug >= 2) {\r
132             echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;\r
133         }\r
134 \r
135         return true;\r
136     }\r
137 \r
138     /**\r
139      * Performs SMTP authentication.  Must be run after running the\r
140      * Hello() method.  Returns true if successfully authenticated.\r
141      * @access public\r
142      * @return bool\r
143      */\r
144     function Authenticate($username, $password) {\r
145         // Start authentication\r
146         fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);\r
147 \r
148         $rply = $this->get_lines();\r
149         $code = substr($rply,0,3);\r
150 \r
151         if($code != 334) {\r
152             $this->error =\r
153                 array("error" => "AUTH not accepted from server",\r
154                       "smtp_code" => $code,\r
155                       "smtp_msg" => substr($rply,4));\r
156             if($this->do_debug >= 1) {\r
157                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
158                          ": " . $rply . $this->CRLF;\r
159             }\r
160             return false;\r
161         }\r
162 \r
163         // Send encoded username\r
164         fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);\r
165 \r
166         $rply = $this->get_lines();\r
167         $code = substr($rply,0,3);\r
168 \r
169         if($code != 334) {\r
170             $this->error =\r
171                 array("error" => "Username not accepted from server",\r
172                       "smtp_code" => $code,\r
173                       "smtp_msg" => substr($rply,4));\r
174             if($this->do_debug >= 1) {\r
175                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
176                          ": " . $rply . $this->CRLF;\r
177             }\r
178             return false;\r
179         }\r
180 \r
181         // Send encoded password\r
182         fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);\r
183 \r
184         $rply = $this->get_lines();\r
185         $code = substr($rply,0,3);\r
186 \r
187         if($code != 235) {\r
188             $this->error =\r
189                 array("error" => "Password not accepted from server",\r
190                       "smtp_code" => $code,\r
191                       "smtp_msg" => substr($rply,4));\r
192             if($this->do_debug >= 1) {\r
193                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
194                          ": " . $rply . $this->CRLF;\r
195             }\r
196             return false;\r
197         }\r
198 \r
199         return true;\r
200     }\r
201 \r
202     /**\r
203      * Returns true if connected to a server otherwise false\r
204      * @access private\r
205      * @return bool\r
206      */\r
207     function Connected() {\r
208         if(!empty($this->smtp_conn)) {\r
209             $sock_status = socket_get_status($this->smtp_conn);\r
210             if($sock_status["eof"]) {\r
211                 # hmm this is an odd situation... the socket is\r
212                 # valid but we aren't connected anymore\r
213                 if($this->do_debug >= 1) {\r
214                     echo "SMTP -> NOTICE:" . $this->CRLF .\r
215                          "EOF caught while checking if connected";\r
216                 }\r
217                 $this->Close();\r
218                 return false;\r
219             }\r
220             return true; # everything looks good\r
221         }\r
222         return false;\r
223     }\r
224 \r
225     /**\r
226      * Closes the socket and cleans up the state of the class.\r
227      * It is not considered good to use this function without\r
228      * first trying to use QUIT.\r
229      * @access public\r
230      * @return void\r
231      */\r
232     function Close() {\r
233         $this->error = null; # so there is no confusion\r
234         $this->helo_rply = null;\r
235         if(!empty($this->smtp_conn)) {\r
236             # close the connection and cleanup\r
237             fclose($this->smtp_conn);\r
238             $this->smtp_conn = 0;\r
239         }\r
240     }\r
241 \r
242 \r
243     /***************************************************************\r
244      *                        SMTP COMMANDS                       *\r
245      *************************************************************/\r
246 \r
247     /**\r
248      * Issues a data command and sends the msg_data to the server\r
249      * finializing the mail transaction. $msg_data is the message\r
250      * that is to be send with the headers. Each header needs to be\r
251      * on a single line followed by a <CRLF> with the message headers\r
252      * and the message body being seperated by and additional <CRLF>.\r
253      *\r
254      * Implements rfc 821: DATA <CRLF>\r
255      *\r
256      * SMTP CODE INTERMEDIATE: 354\r
257      *     [data]\r
258      *     <CRLF>.<CRLF>\r
259      *     SMTP CODE SUCCESS: 250\r
260      *     SMTP CODE FAILURE: 552,554,451,452\r
261      * SMTP CODE FAILURE: 451,554\r
262      * SMTP CODE ERROR  : 500,501,503,421\r
263      * @access public\r
264      * @return bool\r
265      */\r
266     function Data($msg_data) {\r
267         $this->error = null; # so no confusion is caused\r
268 \r
269         if(!$this->connected()) {\r
270             $this->error = array(\r
271                     "error" => "Called Data() without being connected");\r
272             return false;\r
273         }\r
274 \r
275         fputs($this->smtp_conn,"DATA" . $this->CRLF);\r
276 \r
277         $rply = $this->get_lines();\r
278         $code = substr($rply,0,3);\r
279 \r
280         if($this->do_debug >= 2) {\r
281             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
282         }\r
283 \r
284         if($code != 354) {\r
285             $this->error =\r
286                 array("error" => "DATA command not accepted from server",\r
287                       "smtp_code" => $code,\r
288                       "smtp_msg" => substr($rply,4));\r
289             if($this->do_debug >= 1) {\r
290                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
291                          ": " . $rply . $this->CRLF;\r
292             }\r
293             return false;\r
294         }\r
295 \r
296         # the server is ready to accept data!\r
297         # according to rfc 821 we should not send more than 1000\r
298         # including the CRLF\r
299         # characters on a single line so we will break the data up\r
300         # into lines by \r and/or \n then if needed we will break\r
301         # each of those into smaller lines to fit within the limit.\r
302         # in addition we will be looking for lines that start with\r
303         # a period '.' and append and additional period '.' to that\r
304         # line. NOTE: this does not count towards are limit.\r
305 \r
306         # normalize the line breaks so we know the explode works\r
307         $msg_data = str_replace("\r\n","\n",$msg_data);\r
308         $msg_data = str_replace("\r","\n",$msg_data);\r
309         $lines = explode("\n",$msg_data);\r
310 \r
311         # we need to find a good way to determine is headers are\r
312         # in the msg_data or if it is a straight msg body\r
313         # currently I'm assuming rfc 822 definitions of msg headers\r
314         # and if the first field of the first line (':' sperated)\r
315         # does not contain a space then it _should_ be a header\r
316         # and we can process all lines before a blank "" line as\r
317         # headers.\r
318         $field = substr($lines[0],0,strpos($lines[0],":"));\r
319         $in_headers = false;\r
320         if(!empty($field) && !strstr($field," ")) {\r
321             $in_headers = true;\r
322         }\r
323 \r
324         $max_line_length = 998; # used below; set here for ease in change\r
325 \r
326         while(list(,$line) = @each($lines)) {\r
327             $lines_out = null;\r
328             if($line == "" && $in_headers) {\r
329                 $in_headers = false;\r
330             }\r
331             # ok we need to break this line up into several\r
332             # smaller lines\r
333             while(strlen($line) > $max_line_length) {\r
334                 $pos = strrpos(substr($line,0,$max_line_length)," ");\r
335 \r
336                 # Patch to fix DOS attack\r
337                 if(!$pos) {\r
338                     $pos = $max_line_length - 1;\r
339                 }\r
340 \r
341                 $lines_out[] = substr($line,0,$pos);\r
342                 $line = substr($line,$pos + 1);\r
343                 # if we are processing headers we need to\r
344                 # add a LWSP-char to the front of the new line\r
345                 # rfc 822 on long msg headers\r
346                 if($in_headers) {\r
347                     $line = "\t" . $line;\r
348                 }\r
349             }\r
350             $lines_out[] = $line;\r
351 \r
352             # now send the lines to the server\r
353             while(list(,$line_out) = @each($lines_out)) {\r
354                 if(strlen($line_out) > 0)\r
355                 {\r
356                     if(substr($line_out, 0, 1) == ".") {\r
357                         $line_out = "." . $line_out;\r
358                     }\r
359                 }\r
360                 fputs($this->smtp_conn,$line_out . $this->CRLF);\r
361             }\r
362         }\r
363 \r
364         # ok all the message data has been sent so lets get this\r
365         # over with aleady\r
366         fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);\r
367 \r
368         $rply = $this->get_lines();\r
369         $code = substr($rply,0,3);\r
370 \r
371         if($this->do_debug >= 2) {\r
372             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
373         }\r
374 \r
375         if($code != 250) {\r
376             $this->error =\r
377                 array("error" => "DATA not accepted from server",\r
378                       "smtp_code" => $code,\r
379                       "smtp_msg" => substr($rply,4));\r
380             if($this->do_debug >= 1) {\r
381                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
382                          ": " . $rply . $this->CRLF;\r
383             }\r
384             return false;\r
385         }\r
386         return true;\r
387     }\r
388 \r
389     /**\r
390      * Expand takes the name and asks the server to list all the\r
391      * people who are members of the _list_. Expand will return\r
392      * back and array of the result or false if an error occurs.\r
393      * Each value in the array returned has the format of:\r
394      *     [ <full-name> <sp> ] <path>\r
395      * The definition of <path> is defined in rfc 821\r
396      *\r
397      * Implements rfc 821: EXPN <SP> <string> <CRLF>\r
398      *\r
399      * SMTP CODE SUCCESS: 250\r
400      * SMTP CODE FAILURE: 550\r
401      * SMTP CODE ERROR  : 500,501,502,504,421\r
402      * @access public\r
403      * @return string array\r
404      */\r
405     function Expand($name) {\r
406         $this->error = null; # so no confusion is caused\r
407 \r
408         if(!$this->connected()) {\r
409             $this->error = array(\r
410                     "error" => "Called Expand() without being connected");\r
411             return false;\r
412         }\r
413 \r
414         fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);\r
415 \r
416         $rply = $this->get_lines();\r
417         $code = substr($rply,0,3);\r
418 \r
419         if($this->do_debug >= 2) {\r
420             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
421         }\r
422 \r
423         if($code != 250) {\r
424             $this->error =\r
425                 array("error" => "EXPN not accepted from server",\r
426                       "smtp_code" => $code,\r
427                       "smtp_msg" => substr($rply,4));\r
428             if($this->do_debug >= 1) {\r
429                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
430                          ": " . $rply . $this->CRLF;\r
431             }\r
432             return false;\r
433         }\r
434 \r
435         # parse the reply and place in our array to return to user\r
436         $entries = explode($this->CRLF,$rply);\r
437         while(list(,$l) = @each($entries)) {\r
438             $list[] = substr($l,4);\r
439         }\r
440 \r
441         return $list;\r
442     }\r
443 \r
444     /**\r
445      * Sends the HELO command to the smtp server.\r
446      * This makes sure that we and the server are in\r
447      * the same known state.\r
448      *\r
449      * Implements from rfc 821: HELO <SP> <domain> <CRLF>\r
450      *\r
451      * SMTP CODE SUCCESS: 250\r
452      * SMTP CODE ERROR  : 500, 501, 504, 421\r
453      * @access public\r
454      * @return bool\r
455      */\r
456     function Hello($host="") {\r
457         $this->error = null; # so no confusion is caused\r
458 \r
459         if(!$this->connected()) {\r
460             $this->error = array(\r
461                     "error" => "Called Hello() without being connected");\r
462             return false;\r
463         }\r
464 \r
465         # if a hostname for the HELO wasn't specified determine\r
466         # a suitable one to send\r
467         if(empty($host)) {\r
468             # we need to determine some sort of appopiate default\r
469             # to send to the server\r
470             $host = "localhost";\r
471         }\r
472 \r
473         // Send extended hello first (RFC 2821)\r
474         if(!$this->SendHello("EHLO", $host))\r
475         {\r
476             if(!$this->SendHello("HELO", $host))\r
477                 return false;\r
478         }\r
479 \r
480         return true;\r
481     }\r
482 \r
483     /**\r
484      * Sends a HELO/EHLO command.\r
485      * @access private\r
486      * @return bool\r
487      */\r
488     function SendHello($hello, $host) {\r
489         fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);\r
490 \r
491         $rply = $this->get_lines();\r
492         $code = substr($rply,0,3);\r
493 \r
494         if($this->do_debug >= 2) {\r
495             echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;\r
496         }\r
497 \r
498         if($code != 250) {\r
499             $this->error =\r
500                 array("error" => $hello . " not accepted from server",\r
501                       "smtp_code" => $code,\r
502                       "smtp_msg" => substr($rply,4));\r
503             if($this->do_debug >= 1) {\r
504                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
505                          ": " . $rply . $this->CRLF;\r
506             }\r
507             return false;\r
508         }\r
509 \r
510         $this->helo_rply = $rply;\r
511         \r
512         return true;\r
513     }\r
514 \r
515     /**\r
516      * Gets help information on the keyword specified. If the keyword\r
517      * is not specified then returns generic help, ussually contianing\r
518      * A list of keywords that help is available on. This function\r
519      * returns the results back to the user. It is up to the user to\r
520      * handle the returned data. If an error occurs then false is\r
521      * returned with $this->error set appropiately.\r
522      *\r
523      * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>\r
524      *\r
525      * SMTP CODE SUCCESS: 211,214\r
526      * SMTP CODE ERROR  : 500,501,502,504,421\r
527      * @access public\r
528      * @return string\r
529      */\r
530     function Help($keyword="") {\r
531         $this->error = null; # to avoid confusion\r
532 \r
533         if(!$this->connected()) {\r
534             $this->error = array(\r
535                     "error" => "Called Help() without being connected");\r
536             return false;\r
537         }\r
538 \r
539         $extra = "";\r
540         if(!empty($keyword)) {\r
541             $extra = " " . $keyword;\r
542         }\r
543 \r
544         fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);\r
545 \r
546         $rply = $this->get_lines();\r
547         $code = substr($rply,0,3);\r
548 \r
549         if($this->do_debug >= 2) {\r
550             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
551         }\r
552 \r
553         if($code != 211 && $code != 214) {\r
554             $this->error =\r
555                 array("error" => "HELP not accepted from server",\r
556                       "smtp_code" => $code,\r
557                       "smtp_msg" => substr($rply,4));\r
558             if($this->do_debug >= 1) {\r
559                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
560                          ": " . $rply . $this->CRLF;\r
561             }\r
562             return false;\r
563         }\r
564 \r
565         return $rply;\r
566     }\r
567 \r
568     /**\r
569      * Starts a mail transaction from the email address specified in\r
570      * $from. Returns true if successful or false otherwise. If True\r
571      * the mail transaction is started and then one or more Recipient\r
572      * commands may be called followed by a Data command.\r
573      *\r
574      * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>\r
575      *\r
576      * SMTP CODE SUCCESS: 250\r
577      * SMTP CODE SUCCESS: 552,451,452\r
578      * SMTP CODE SUCCESS: 500,501,421\r
579      * @access public\r
580      * @return bool\r
581      */\r
582     function Mail($from) {\r
583         $this->error = null; # so no confusion is caused\r
584 \r
585         if(!$this->connected()) {\r
586             $this->error = array(\r
587                     "error" => "Called Mail() without being connected");\r
588             return false;\r
589         }\r
590 \r
591         fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);\r
592 \r
593         $rply = $this->get_lines();\r
594         $code = substr($rply,0,3);\r
595 \r
596         if($this->do_debug >= 2) {\r
597             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
598         }\r
599 \r
600         if($code != 250) {\r
601             $this->error =\r
602                 array("error" => "MAIL not accepted from server",\r
603                       "smtp_code" => $code,\r
604                       "smtp_msg" => substr($rply,4));\r
605             if($this->do_debug >= 1) {\r
606                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
607                          ": " . $rply . $this->CRLF;\r
608             }\r
609             return false;\r
610         }\r
611         return true;\r
612     }\r
613 \r
614     /**\r
615      * Sends the command NOOP to the SMTP server.\r
616      *\r
617      * Implements from rfc 821: NOOP <CRLF>\r
618      *\r
619      * SMTP CODE SUCCESS: 250\r
620      * SMTP CODE ERROR  : 500, 421\r
621      * @access public\r
622      * @return bool\r
623      */\r
624     function Noop() {\r
625         $this->error = null; # so no confusion is caused\r
626 \r
627         if(!$this->connected()) {\r
628             $this->error = array(\r
629                     "error" => "Called Noop() without being connected");\r
630             return false;\r
631         }\r
632 \r
633         fputs($this->smtp_conn,"NOOP" . $this->CRLF);\r
634 \r
635         $rply = $this->get_lines();\r
636         $code = substr($rply,0,3);\r
637 \r
638         if($this->do_debug >= 2) {\r
639             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
640         }\r
641 \r
642         if($code != 250) {\r
643             $this->error =\r
644                 array("error" => "NOOP not accepted from server",\r
645                       "smtp_code" => $code,\r
646                       "smtp_msg" => substr($rply,4));\r
647             if($this->do_debug >= 1) {\r
648                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
649                          ": " . $rply . $this->CRLF;\r
650             }\r
651             return false;\r
652         }\r
653         return true;\r
654     }\r
655 \r
656     /**\r
657      * Sends the quit command to the server and then closes the socket\r
658      * if there is no error or the $close_on_error argument is true.\r
659      *\r
660      * Implements from rfc 821: QUIT <CRLF>\r
661      *\r
662      * SMTP CODE SUCCESS: 221\r
663      * SMTP CODE ERROR  : 500\r
664      * @access public\r
665      * @return bool\r
666      */\r
667     function Quit($close_on_error=true) {\r
668         $this->error = null; # so there is no confusion\r
669 \r
670         if(!$this->connected()) {\r
671             $this->error = array(\r
672                     "error" => "Called Quit() without being connected");\r
673             return false;\r
674         }\r
675 \r
676         # send the quit command to the server\r
677         fputs($this->smtp_conn,"quit" . $this->CRLF);\r
678 \r
679         # get any good-bye messages\r
680         $byemsg = $this->get_lines();\r
681 \r
682         if($this->do_debug >= 2) {\r
683             echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;\r
684         }\r
685 \r
686         $rval = true;\r
687         $e = null;\r
688 \r
689         $code = substr($byemsg,0,3);\r
690         if($code != 221) {\r
691             # use e as a tmp var cause Close will overwrite $this->error\r
692             $e = array("error" => "SMTP server rejected quit command",\r
693                        "smtp_code" => $code,\r
694                        "smtp_rply" => substr($byemsg,4));\r
695             $rval = false;\r
696             if($this->do_debug >= 1) {\r
697                 echo "SMTP -> ERROR: " . $e["error"] . ": " .\r
698                          $byemsg . $this->CRLF;\r
699             }\r
700         }\r
701 \r
702         if(empty($e) || $close_on_error) {\r
703             $this->Close();\r
704         }\r
705 \r
706         return $rval;\r
707     }\r
708 \r
709     /**\r
710      * Sends the command RCPT to the SMTP server with the TO: argument of $to.\r
711      * Returns true if the recipient was accepted false if it was rejected.\r
712      *\r
713      * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>\r
714      *\r
715      * SMTP CODE SUCCESS: 250,251\r
716      * SMTP CODE FAILURE: 550,551,552,553,450,451,452\r
717      * SMTP CODE ERROR  : 500,501,503,421\r
718      * @access public\r
719      * @return bool\r
720      */\r
721     function Recipient($to) {\r
722         $this->error = null; # so no confusion is caused\r
723 \r
724         if(!$this->connected()) {\r
725             $this->error = array(\r
726                     "error" => "Called Recipient() without being connected");\r
727             return false;\r
728         }\r
729 \r
730         fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);\r
731 \r
732         $rply = $this->get_lines();\r
733         $code = substr($rply,0,3);\r
734 \r
735         if($this->do_debug >= 2) {\r
736             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
737         }\r
738 \r
739         if($code != 250 && $code != 251) {\r
740             $this->error =\r
741                 array("error" => "RCPT not accepted from server",\r
742                       "smtp_code" => $code,\r
743                       "smtp_msg" => substr($rply,4));\r
744             if($this->do_debug >= 1) {\r
745                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
746                          ": " . $rply . $this->CRLF;\r
747             }\r
748             return false;\r
749         }\r
750         return true;\r
751     }\r
752 \r
753     /**\r
754      * Sends the RSET command to abort and transaction that is\r
755      * currently in progress. Returns true if successful false\r
756      * otherwise.\r
757      *\r
758      * Implements rfc 821: RSET <CRLF>\r
759      *\r
760      * SMTP CODE SUCCESS: 250\r
761      * SMTP CODE ERROR  : 500,501,504,421\r
762      * @access public\r
763      * @return bool\r
764      */\r
765     function Reset() {\r
766         $this->error = null; # so no confusion is caused\r
767 \r
768         if(!$this->connected()) {\r
769             $this->error = array(\r
770                     "error" => "Called Reset() without being connected");\r
771             return false;\r
772         }\r
773 \r
774         fputs($this->smtp_conn,"RSET" . $this->CRLF);\r
775 \r
776         $rply = $this->get_lines();\r
777         $code = substr($rply,0,3);\r
778 \r
779         if($this->do_debug >= 2) {\r
780             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
781         }\r
782 \r
783         if($code != 250) {\r
784             $this->error =\r
785                 array("error" => "RSET failed",\r
786                       "smtp_code" => $code,\r
787                       "smtp_msg" => substr($rply,4));\r
788             if($this->do_debug >= 1) {\r
789                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
790                          ": " . $rply . $this->CRLF;\r
791             }\r
792             return false;\r
793         }\r
794 \r
795         return true;\r
796     }\r
797 \r
798     /**\r
799      * Starts a mail transaction from the email address specified in\r
800      * $from. Returns true if successful or false otherwise. If True\r
801      * the mail transaction is started and then one or more Recipient\r
802      * commands may be called followed by a Data command. This command\r
803      * will send the message to the users terminal if they are logged\r
804      * in.\r
805      *\r
806      * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>\r
807      *\r
808      * SMTP CODE SUCCESS: 250\r
809      * SMTP CODE SUCCESS: 552,451,452\r
810      * SMTP CODE SUCCESS: 500,501,502,421\r
811      * @access public\r
812      * @return bool\r
813      */\r
814     function Send($from) {\r
815         $this->error = null; # so no confusion is caused\r
816 \r
817         if(!$this->connected()) {\r
818             $this->error = array(\r
819                     "error" => "Called Send() without being connected");\r
820             return false;\r
821         }\r
822 \r
823         fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);\r
824 \r
825         $rply = $this->get_lines();\r
826         $code = substr($rply,0,3);\r
827 \r
828         if($this->do_debug >= 2) {\r
829             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
830         }\r
831 \r
832         if($code != 250) {\r
833             $this->error =\r
834                 array("error" => "SEND not accepted from server",\r
835                       "smtp_code" => $code,\r
836                       "smtp_msg" => substr($rply,4));\r
837             if($this->do_debug >= 1) {\r
838                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
839                          ": " . $rply . $this->CRLF;\r
840             }\r
841             return false;\r
842         }\r
843         return true;\r
844     }\r
845 \r
846     /**\r
847      * Starts a mail transaction from the email address specified in\r
848      * $from. Returns true if successful or false otherwise. If True\r
849      * the mail transaction is started and then one or more Recipient\r
850      * commands may be called followed by a Data command. This command\r
851      * will send the message to the users terminal if they are logged\r
852      * in and send them an email.\r
853      *\r
854      * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>\r
855      *\r
856      * SMTP CODE SUCCESS: 250\r
857      * SMTP CODE SUCCESS: 552,451,452\r
858      * SMTP CODE SUCCESS: 500,501,502,421\r
859      * @access public\r
860      * @return bool\r
861      */\r
862     function SendAndMail($from) {\r
863         $this->error = null; # so no confusion is caused\r
864 \r
865         if(!$this->connected()) {\r
866             $this->error = array(\r
867                 "error" => "Called SendAndMail() without being connected");\r
868             return false;\r
869         }\r
870 \r
871         fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);\r
872 \r
873         $rply = $this->get_lines();\r
874         $code = substr($rply,0,3);\r
875 \r
876         if($this->do_debug >= 2) {\r
877             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
878         }\r
879 \r
880         if($code != 250) {\r
881             $this->error =\r
882                 array("error" => "SAML not accepted from server",\r
883                       "smtp_code" => $code,\r
884                       "smtp_msg" => substr($rply,4));\r
885             if($this->do_debug >= 1) {\r
886                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
887                          ": " . $rply . $this->CRLF;\r
888             }\r
889             return false;\r
890         }\r
891         return true;\r
892     }\r
893 \r
894     /**\r
895      * Starts a mail transaction from the email address specified in\r
896      * $from. Returns true if successful or false otherwise. If True\r
897      * the mail transaction is started and then one or more Recipient\r
898      * commands may be called followed by a Data command. This command\r
899      * will send the message to the users terminal if they are logged\r
900      * in or mail it to them if they are not.\r
901      *\r
902      * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>\r
903      *\r
904      * SMTP CODE SUCCESS: 250\r
905      * SMTP CODE SUCCESS: 552,451,452\r
906      * SMTP CODE SUCCESS: 500,501,502,421\r
907      * @access public\r
908      * @return bool\r
909      */\r
910     function SendOrMail($from) {\r
911         $this->error = null; # so no confusion is caused\r
912 \r
913         if(!$this->connected()) {\r
914             $this->error = array(\r
915                 "error" => "Called SendOrMail() without being connected");\r
916             return false;\r
917         }\r
918 \r
919         fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);\r
920 \r
921         $rply = $this->get_lines();\r
922         $code = substr($rply,0,3);\r
923 \r
924         if($this->do_debug >= 2) {\r
925             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
926         }\r
927 \r
928         if($code != 250) {\r
929             $this->error =\r
930                 array("error" => "SOML not accepted from server",\r
931                       "smtp_code" => $code,\r
932                       "smtp_msg" => substr($rply,4));\r
933             if($this->do_debug >= 1) {\r
934                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
935                          ": " . $rply . $this->CRLF;\r
936             }\r
937             return false;\r
938         }\r
939         return true;\r
940     }\r
941 \r
942     /**\r
943      * This is an optional command for SMTP that this class does not\r
944      * support. This method is here to make the RFC821 Definition\r
945      * complete for this class and __may__ be implimented in the future\r
946      *\r
947      * Implements from rfc 821: TURN <CRLF>\r
948      *\r
949      * SMTP CODE SUCCESS: 250\r
950      * SMTP CODE FAILURE: 502\r
951      * SMTP CODE ERROR  : 500, 503\r
952      * @access public\r
953      * @return bool\r
954      */\r
955     function Turn() {\r
956         $this->error = array("error" => "This method, TURN, of the SMTP ".\r
957                                         "is not implemented");\r
958         if($this->do_debug >= 1) {\r
959             echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;\r
960         }\r
961         return false;\r
962     }\r
963 \r
964     /**\r
965      * Verifies that the name is recognized by the server.\r
966      * Returns false if the name could not be verified otherwise\r
967      * the response from the server is returned.\r
968      *\r
969      * Implements rfc 821: VRFY <SP> <string> <CRLF>\r
970      *\r
971      * SMTP CODE SUCCESS: 250,251\r
972      * SMTP CODE FAILURE: 550,551,553\r
973      * SMTP CODE ERROR  : 500,501,502,421\r
974      * @access public\r
975      * @return int\r
976      */\r
977     function Verify($name) {\r
978         $this->error = null; # so no confusion is caused\r
979 \r
980         if(!$this->connected()) {\r
981             $this->error = array(\r
982                     "error" => "Called Verify() without being connected");\r
983             return false;\r
984         }\r
985 \r
986         fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);\r
987 \r
988         $rply = $this->get_lines();\r
989         $code = substr($rply,0,3);\r
990 \r
991         if($this->do_debug >= 2) {\r
992             echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;\r
993         }\r
994 \r
995         if($code != 250 && $code != 251) {\r
996             $this->error =\r
997                 array("error" => "VRFY failed on name '$name'",\r
998                       "smtp_code" => $code,\r
999                       "smtp_msg" => substr($rply,4));\r
1000             if($this->do_debug >= 1) {\r
1001                 echo "SMTP -> ERROR: " . $this->error["error"] .\r
1002                          ": " . $rply . $this->CRLF;\r
1003             }\r
1004             return false;\r
1005         }\r
1006         return $rply;\r
1007     }\r
1008 \r
1009     /*******************************************************************\r
1010      *                       INTERNAL FUNCTIONS                       *\r
1011      ******************************************************************/\r
1012 \r
1013     /**\r
1014      * Read in as many lines as possible\r
1015      * either before eof or socket timeout occurs on the operation.\r
1016      * With SMTP we can tell if we have more lines to read if the\r
1017      * 4th character is '-' symbol. If it is a space then we don't\r
1018      * need to read anything else.\r
1019      * @access private\r
1020      * @return string\r
1021      */\r
1022     function get_lines() {\r
1023         $data = "";\r
1024         while($str = fgets($this->smtp_conn,515)) {\r
1025             if($this->do_debug >= 4) {\r
1026                 echo "SMTP -> get_lines(): \$data was \"$data\"" .\r
1027                          $this->CRLF;\r
1028                 echo "SMTP -> get_lines(): \$str is \"$str\"" .\r
1029                          $this->CRLF;\r
1030             }\r
1031             $data .= $str;\r
1032             if($this->do_debug >= 4) {\r
1033                 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;\r
1034             }\r
1035             # if the 4th character is a space then we are done reading\r
1036             # so just break the loop\r
1037             if(substr($str,3,1) == " ") { break; }\r
1038         }\r
1039         return $data;\r
1040     }\r
1041 \r
1042 }\r
1043 \r
1044 \r
1045  ?>\r