File: 0.00.1a/core/phpmailer/class.smtp.php (View as HTML)

  1: <?php
  2: /*~ class.smtp.php
  3: .---------------------------------------------------------------------------.
  4: |  Software: PHPMailer - PHP email class                                    |
  5: |   Version: 5.2.1                                                          |
  6: |      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
  7: | ------------------------------------------------------------------------- |
  8: |     Admin: Jim Jagielski (project admininistrator)                        |
  9: |   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
 10: |          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
 11: |          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
 12: |   Founder: Brent R. Matzelle (original founder)                           |
 13: | Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved.              |
 14: | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
 15: | Copyright (c) 2001-2003, Brent R. Matzelle                                |
 16: | ------------------------------------------------------------------------- |
 17: |   License: Distributed under the Lesser General Public License (LGPL)     |
 18: |            http://www.gnu.org/copyleft/lesser.html                        |
 19: | This program is distributed in the hope that it will be useful - WITHOUT  |
 20: | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
 21: | FITNESS FOR A PARTICULAR PURPOSE.                                         |
 22: '---------------------------------------------------------------------------'
 23: */
 24: 
 25: /**
 26:  * PHPMailer - PHP SMTP email transport class
 27:  * NOTE: Designed for use with PHP version 5 and up
 28:  * @package PHPMailer
 29:  * @author Andy Prevost
 30:  * @author Marcus Bointon
 31:  * @copyright 2004 - 2008 Andy Prevost
 32:  * @author Jim Jagielski
 33:  * @copyright 2010 - 2012 Jim Jagielski
 34:  * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
 35:  * @version $Id: class.smtp.php 450 2010-06-23 16:46:33Z coolbru $
 36:  */
 37: 
 38: /**
 39:  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
 40:  * commands except TURN which will always return a not implemented
 41:  * error. SMTP also provides some utility methods for sending mail
 42:  * to an SMTP server.
 43:  * original author: Chris Ryan
 44:  */
 45: 
 46: class SMTP {
 47:   /**
 48:    *  SMTP server port
 49:    *  @var int
 50:    */
 51:   public $SMTP_PORT = 25;
 52: 
 53:   /**
 54:    *  SMTP reply line ending
 55:    *  @var string
 56:    */
 57:   public $CRLF = "\r\n";
 58: 
 59:   /**
 60:    *  Sets whether debugging is turned on
 61:    *  @var bool
 62:    */
 63:   public $do_debug;       // the level of debug to perform
 64: 
 65:   /**
 66:    *  Sets VERP use on/off (default is off)
 67:    *  @var bool
 68:    */
 69:   public $do_verp = false;
 70: 
 71:   /**
 72:    * Sets the SMTP PHPMailer Version number
 73:    * @var string
 74:    */
 75:   public $Version         = '5.2.1';
 76: 
 77:   /////////////////////////////////////////////////
 78:   // PROPERTIES, PRIVATE AND PROTECTED
 79:   /////////////////////////////////////////////////
 80: 
 81:   private $smtp_conn; // the socket to the server
 82:   private $error;     // error if any on the last call
 83:   private $helo_rply; // the reply the server sent to us for HELO
 84: 
 85:   /**
 86:    * Initialize the class so that the data is in a known state.
 87:    * @access public
 88:    * @return void
 89:    */
 90:   public function __construct() {
 91:     $this->smtp_conn = 0;
 92:     $this->error = null;
 93:     $this->helo_rply = null;
 94: 
 95:     $this->do_debug = 0;
 96:   }
 97: 
 98:   /////////////////////////////////////////////////
 99:   // CONNECTION FUNCTIONS
100:   /////////////////////////////////////////////////
101: 
102:   /**
103:    * Connect to the server specified on the port specified.
104:    * If the port is not specified use the default SMTP_PORT.
105:    * If tval is specified then a connection will try and be
106:    * established with the server for that number of seconds.
107:    * If tval is not specified the default is 30 seconds to
108:    * try on the connection.
109:    *
110:    * SMTP CODE SUCCESS: 220
111:    * SMTP CODE FAILURE: 421
112:    * @access public
113:    * @return bool
114:    */
115:   public function Connect($host, $port = 0, $tval = 30) {
116:     // set the error val to null so there is no confusion
117:     $this->error = null;
118: 
119:     // make sure we are __not__ connected
120:     if($this->connected()) {
121:       // already connected, generate error
122:       $this->error = array("error" => "Already connected to a server");
123:       return false;
124:     }
125: 
126:     if(empty($port)) {
127:       $port = $this->SMTP_PORT;
128:     }
129: 
130:     // connect to the smtp server
131:     $this->smtp_conn = @fsockopen($host,    // the host of the server
132:                                  $port,    // the port to use
133:                                  $errno,   // error number if any
134:                                  $errstr,  // error message if any
135:                                  $tval);   // give up after ? secs
136:     // verify we connected properly
137:     if(empty($this->smtp_conn)) {
138:       $this->error = array("error" => "Failed to connect to server",
139:                            "errno" => $errno,
140:                            "errstr" => $errstr);
141:       if($this->do_debug >= 1) {
142:         echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
143:       }
144:       return false;
145:     }
146: 
147:     // SMTP server can take longer to respond, give longer timeout for first read
148:     // Windows does not have support for this timeout function
149:     if(substr(PHP_OS, 0, 3) != "WIN")
150:      socket_set_timeout($this->smtp_conn, $tval, 0);
151: 
152:     // get any announcement
153:     $announce = $this->get_lines();
154: 
155:     if($this->do_debug >= 2) {
156:       echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
157:     }
158: 
159:     return true;
160:   }
161: 
162:   /**
163:    * Initiate a TLS communication with the server.
164:    *
165:    * SMTP CODE 220 Ready to start TLS
166:    * SMTP CODE 501 Syntax error (no parameters allowed)
167:    * SMTP CODE 454 TLS not available due to temporary reason
168:    * @access public
169:    * @return bool success
170:    */
171:   public function StartTLS() {
172:     $this->error = null; # to avoid confusion
173: 
174:     if(!$this->connected()) {
175:       $this->error = array("error" => "Called StartTLS() without being connected");
176:       return false;
177:     }
178: 
179:     fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
180: 
181:     $rply = $this->get_lines();
182:     $code = substr($rply,0,3);
183: 
184:     if($this->do_debug >= 2) {
185:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
186:     }
187: 
188:     if($code != 220) {
189:       $this->error =
190:          array("error"     => "STARTTLS not accepted from server",
191:                "smtp_code" => $code,
192:                "smtp_msg"  => substr($rply,4));
193:       if($this->do_debug >= 1) {
194:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
195:       }
196:       return false;
197:     }
198: 
199:     // Begin encrypted connection
200:     if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
201:       return false;
202:     }
203: 
204:     return true;
205:   }
206: 
207:   /**
208:    * Performs SMTP authentication.  Must be run after running the
209:    * Hello() method.  Returns true if successfully authenticated.
210:    * @access public
211:    * @return bool
212:    */
213:   public function Authenticate($username, $password) {
214:     // Start authentication
215:     fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
216: 
217:     $rply = $this->get_lines();
218:     $code = substr($rply,0,3);
219: 
220:     if($code != 334) {
221:       $this->error =
222:         array("error" => "AUTH not accepted from server",
223:               "smtp_code" => $code,
224:               "smtp_msg" => substr($rply,4));
225:       if($this->do_debug >= 1) {
226:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
227:       }
228:       return false;
229:     }
230: 
231:     // Send encoded username
232:     fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
233: 
234:     $rply = $this->get_lines();
235:     $code = substr($rply,0,3);
236: 
237:     if($code != 334) {
238:       $this->error =
239:         array("error" => "Username not accepted from server",
240:               "smtp_code" => $code,
241:               "smtp_msg" => substr($rply,4));
242:       if($this->do_debug >= 1) {
243:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
244:       }
245:       return false;
246:     }
247: 
248:     // Send encoded password
249:     fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
250: 
251:     $rply = $this->get_lines();
252:     $code = substr($rply,0,3);
253: 
254:     if($code != 235) {
255:       $this->error =
256:         array("error" => "Password not accepted from server",
257:               "smtp_code" => $code,
258:               "smtp_msg" => substr($rply,4));
259:       if($this->do_debug >= 1) {
260:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
261:       }
262:       return false;
263:     }
264: 
265:     return true;
266:   }
267: 
268:   /**
269:    * Returns true if connected to a server otherwise false
270:    * @access public
271:    * @return bool
272:    */
273:   public function Connected() {
274:     if(!empty($this->smtp_conn)) {
275:       $sock_status = socket_get_status($this->smtp_conn);
276:       if($sock_status["eof"]) {
277:         // the socket is valid but we are not connected
278:         if($this->do_debug >= 1) {
279:             echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
280:         }
281:         $this->Close();
282:         return false;
283:       }
284:       return true; // everything looks good
285:     }
286:     return false;
287:   }
288: 
289:   /**
290:    * Closes the socket and cleans up the state of the class.
291:    * It is not considered good to use this function without
292:    * first trying to use QUIT.
293:    * @access public
294:    * @return void
295:    */
296:   public function Close() {
297:     $this->error = null; // so there is no confusion
298:     $this->helo_rply = null;
299:     if(!empty($this->smtp_conn)) {
300:       // close the connection and cleanup
301:       fclose($this->smtp_conn);
302:       $this->smtp_conn = 0;
303:     }
304:   }
305: 
306:   /////////////////////////////////////////////////
307:   // SMTP COMMANDS
308:   /////////////////////////////////////////////////
309: 
310:   /**
311:    * Issues a data command and sends the msg_data to the server
312:    * finializing the mail transaction. $msg_data is the message
313:    * that is to be send with the headers. Each header needs to be
314:    * on a single line followed by a <CRLF> with the message headers
315:    * and the message body being seperated by and additional <CRLF>.
316:    *
317:    * Implements rfc 821: DATA <CRLF>
318:    *
319:    * SMTP CODE INTERMEDIATE: 354
320:    *     [data]
321:    *     <CRLF>.<CRLF>
322:    *     SMTP CODE SUCCESS: 250
323:    *     SMTP CODE FAILURE: 552,554,451,452
324:    * SMTP CODE FAILURE: 451,554
325:    * SMTP CODE ERROR  : 500,501,503,421
326:    * @access public
327:    * @return bool
328:    */
329:   public function Data($msg_data) {
330:     $this->error = null; // so no confusion is caused
331: 
332:     if(!$this->connected()) {
333:       $this->error = array(
334:               "error" => "Called Data() without being connected");
335:       return false;
336:     }
337: 
338:     fputs($this->smtp_conn,"DATA" . $this->CRLF);
339: 
340:     $rply = $this->get_lines();
341:     $code = substr($rply,0,3);
342: 
343:     if($this->do_debug >= 2) {
344:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
345:     }
346: 
347:     if($code != 354) {
348:       $this->error =
349:         array("error" => "DATA command not accepted from server",
350:               "smtp_code" => $code,
351:               "smtp_msg" => substr($rply,4));
352:       if($this->do_debug >= 1) {
353:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
354:       }
355:       return false;
356:     }
357: 
358:     /* the server is ready to accept data!
359:      * according to rfc 821 we should not send more than 1000
360:      * including the CRLF
361:      * characters on a single line so we will break the data up
362:      * into lines by \r and/or \n then if needed we will break
363:      * each of those into smaller lines to fit within the limit.
364:      * in addition we will be looking for lines that start with
365:      * a period '.' and append and additional period '.' to that
366:      * line. NOTE: this does not count towards limit.
367:      */
368: 
369:     // normalize the line breaks so we know the explode works
370:     $msg_data = str_replace("\r\n","\n",$msg_data);
371:     $msg_data = str_replace("\r","\n",$msg_data);
372:     $lines = explode("\n",$msg_data);
373: 
374:     /* we need to find a good way to determine is headers are
375:      * in the msg_data or if it is a straight msg body
376:      * currently I am assuming rfc 822 definitions of msg headers
377:      * and if the first field of the first line (':' sperated)
378:      * does not contain a space then it _should_ be a header
379:      * and we can process all lines before a blank "" line as
380:      * headers.
381:      */
382: 
383:     $field = substr($lines[0],0,strpos($lines[0],":"));
384:     $in_headers = false;
385:     if(!empty($field) && !strstr($field," ")) {
386:       $in_headers = true;
387:     }
388: 
389:     $max_line_length = 998; // used below; set here for ease in change
390: 
391:     while(list(,$line) = @each($lines)) {
392:       $lines_out = null;
393:       if($line == "" && $in_headers) {
394:         $in_headers = false;
395:       }
396:       // ok we need to break this line up into several smaller lines
397:       while(strlen($line) > $max_line_length) {
398:         $pos = strrpos(substr($line,0,$max_line_length)," ");
399: 
400:         // Patch to fix DOS attack
401:         if(!$pos) {
402:           $pos = $max_line_length - 1;
403:           $lines_out[] = substr($line,0,$pos);
404:           $line = substr($line,$pos);
405:         } else {
406:           $lines_out[] = substr($line,0,$pos);
407:           $line = substr($line,$pos + 1);
408:         }
409: 
410:         /* if processing headers add a LWSP-char to the front of new line
411:          * rfc 822 on long msg headers
412:          */
413:         if($in_headers) {
414:           $line = "\t" . $line;
415:         }
416:       }
417:       $lines_out[] = $line;
418: 
419:       // send the lines to the server
420:       while(list(,$line_out) = @each($lines_out)) {
421:         if(strlen($line_out) > 0)
422:         {
423:           if(substr($line_out, 0, 1) == ".") {
424:             $line_out = "." . $line_out;
425:           }
426:         }
427:         fputs($this->smtp_conn,$line_out . $this->CRLF);
428:       }
429:     }
430: 
431:     // message data has been sent
432:     fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
433: 
434:     $rply = $this->get_lines();
435:     $code = substr($rply,0,3);
436: 
437:     if($this->do_debug >= 2) {
438:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
439:     }
440: 
441:     if($code != 250) {
442:       $this->error =
443:         array("error" => "DATA not accepted from server",
444:               "smtp_code" => $code,
445:               "smtp_msg" => substr($rply,4));
446:       if($this->do_debug >= 1) {
447:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
448:       }
449:       return false;
450:     }
451:     return true;
452:   }
453: 
454:   /**
455:    * Sends the HELO command to the smtp server.
456:    * This makes sure that we and the server are in
457:    * the same known state.
458:    *
459:    * Implements from rfc 821: HELO <SP> <domain> <CRLF>
460:    *
461:    * SMTP CODE SUCCESS: 250
462:    * SMTP CODE ERROR  : 500, 501, 504, 421
463:    * @access public
464:    * @return bool
465:    */
466:   public function Hello($host = '') {
467:     $this->error = null; // so no confusion is caused
468: 
469:     if(!$this->connected()) {
470:       $this->error = array(
471:             "error" => "Called Hello() without being connected");
472:       return false;
473:     }
474: 
475:     // if hostname for HELO was not specified send default
476:     if(empty($host)) {
477:       // determine appropriate default to send to server
478:       $host = "localhost";
479:     }
480: 
481:     // Send extended hello first (RFC 2821)
482:     if(!$this->SendHello("EHLO", $host)) {
483:       if(!$this->SendHello("HELO", $host)) {
484:         return false;
485:       }
486:     }
487: 
488:     return true;
489:   }
490: 
491:   /**
492:    * Sends a HELO/EHLO command.
493:    * @access private
494:    * @return bool
495:    */
496:   private function SendHello($hello, $host) {
497:     fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
498: 
499:     $rply = $this->get_lines();
500:     $code = substr($rply,0,3);
501: 
502:     if($this->do_debug >= 2) {
503:       echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
504:     }
505: 
506:     if($code != 250) {
507:       $this->error =
508:         array("error" => $hello . " not accepted from server",
509:               "smtp_code" => $code,
510:               "smtp_msg" => substr($rply,4));
511:       if($this->do_debug >= 1) {
512:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
513:       }
514:       return false;
515:     }
516: 
517:     $this->helo_rply = $rply;
518: 
519:     return true;
520:   }
521: 
522:   /**
523:    * Starts a mail transaction from the email address specified in
524:    * $from. Returns true if successful or false otherwise. If True
525:    * the mail transaction is started and then one or more Recipient
526:    * commands may be called followed by a Data command.
527:    *
528:    * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
529:    *
530:    * SMTP CODE SUCCESS: 250
531:    * SMTP CODE SUCCESS: 552,451,452
532:    * SMTP CODE SUCCESS: 500,501,421
533:    * @access public
534:    * @return bool
535:    */
536:   public function Mail($from) {
537:     $this->error = null; // so no confusion is caused
538: 
539:     if(!$this->connected()) {
540:       $this->error = array(
541:               "error" => "Called Mail() without being connected");
542:       return false;
543:     }
544: 
545:     $useVerp = ($this->do_verp ? "XVERP" : "");
546:     fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
547: 
548:     $rply = $this->get_lines();
549:     $code = substr($rply,0,3);
550: 
551:     if($this->do_debug >= 2) {
552:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
553:     }
554: 
555:     if($code != 250) {
556:       $this->error =
557:         array("error" => "MAIL not accepted from server",
558:               "smtp_code" => $code,
559:               "smtp_msg" => substr($rply,4));
560:       if($this->do_debug >= 1) {
561:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
562:       }
563:       return false;
564:     }
565:     return true;
566:   }
567: 
568:   /**
569:    * Sends the quit command to the server and then closes the socket
570:    * if there is no error or the $close_on_error argument is true.
571:    *
572:    * Implements from rfc 821: QUIT <CRLF>
573:    *
574:    * SMTP CODE SUCCESS: 221
575:    * SMTP CODE ERROR  : 500
576:    * @access public
577:    * @return bool
578:    */
579:   public function Quit($close_on_error = true) {
580:     $this->error = null; // so there is no confusion
581: 
582:     if(!$this->connected()) {
583:       $this->error = array(
584:               "error" => "Called Quit() without being connected");
585:       return false;
586:     }
587: 
588:     // send the quit command to the server
589:     fputs($this->smtp_conn,"quit" . $this->CRLF);
590: 
591:     // get any good-bye messages
592:     $byemsg = $this->get_lines();
593: 
594:     if($this->do_debug >= 2) {
595:       echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
596:     }
597: 
598:     $rval = true;
599:     $e = null;
600: 
601:     $code = substr($byemsg,0,3);
602:     if($code != 221) {
603:       // use e as a tmp var cause Close will overwrite $this->error
604:       $e = array("error" => "SMTP server rejected quit command",
605:                  "smtp_code" => $code,
606:                  "smtp_rply" => substr($byemsg,4));
607:       $rval = false;
608:       if($this->do_debug >= 1) {
609:         echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
610:       }
611:     }
612: 
613:     if(empty($e) || $close_on_error) {
614:       $this->Close();
615:     }
616: 
617:     return $rval;
618:   }
619: 
620:   /**
621:    * Sends the command RCPT to the SMTP server with the TO: argument of $to.
622:    * Returns true if the recipient was accepted false if it was rejected.
623:    *
624:    * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
625:    *
626:    * SMTP CODE SUCCESS: 250,251
627:    * SMTP CODE FAILURE: 550,551,552,553,450,451,452
628:    * SMTP CODE ERROR  : 500,501,503,421
629:    * @access public
630:    * @return bool
631:    */
632:   public function Recipient($to) {
633:     $this->error = null; // so no confusion is caused
634: 
635:     if(!$this->connected()) {
636:       $this->error = array(
637:               "error" => "Called Recipient() without being connected");
638:       return false;
639:     }
640: 
641:     fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
642: 
643:     $rply = $this->get_lines();
644:     $code = substr($rply,0,3);
645: 
646:     if($this->do_debug >= 2) {
647:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
648:     }
649: 
650:     if($code != 250 && $code != 251) {
651:       $this->error =
652:         array("error" => "RCPT not accepted from server",
653:               "smtp_code" => $code,
654:               "smtp_msg" => substr($rply,4));
655:       if($this->do_debug >= 1) {
656:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
657:       }
658:       return false;
659:     }
660:     return true;
661:   }
662: 
663:   /**
664:    * Sends the RSET command to abort and transaction that is
665:    * currently in progress. Returns true if successful false
666:    * otherwise.
667:    *
668:    * Implements rfc 821: RSET <CRLF>
669:    *
670:    * SMTP CODE SUCCESS: 250
671:    * SMTP CODE ERROR  : 500,501,504,421
672:    * @access public
673:    * @return bool
674:    */
675:   public function Reset() {
676:     $this->error = null; // so no confusion is caused
677: 
678:     if(!$this->connected()) {
679:       $this->error = array(
680:               "error" => "Called Reset() without being connected");
681:       return false;
682:     }
683: 
684:     fputs($this->smtp_conn,"RSET" . $this->CRLF);
685: 
686:     $rply = $this->get_lines();
687:     $code = substr($rply,0,3);
688: 
689:     if($this->do_debug >= 2) {
690:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
691:     }
692: 
693:     if($code != 250) {
694:       $this->error =
695:         array("error" => "RSET failed",
696:               "smtp_code" => $code,
697:               "smtp_msg" => substr($rply,4));
698:       if($this->do_debug >= 1) {
699:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
700:       }
701:       return false;
702:     }
703: 
704:     return true;
705:   }
706: 
707:   /**
708:    * Starts a mail transaction from the email address specified in
709:    * $from. Returns true if successful or false otherwise. If True
710:    * the mail transaction is started and then one or more Recipient
711:    * commands may be called followed by a Data command. This command
712:    * will send the message to the users terminal if they are logged
713:    * in and send them an email.
714:    *
715:    * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
716:    *
717:    * SMTP CODE SUCCESS: 250
718:    * SMTP CODE SUCCESS: 552,451,452
719:    * SMTP CODE SUCCESS: 500,501,502,421
720:    * @access public
721:    * @return bool
722:    */
723:   public function SendAndMail($from) {
724:     $this->error = null; // so no confusion is caused
725: 
726:     if(!$this->connected()) {
727:       $this->error = array(
728:           "error" => "Called SendAndMail() without being connected");
729:       return false;
730:     }
731: 
732:     fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
733: 
734:     $rply = $this->get_lines();
735:     $code = substr($rply,0,3);
736: 
737:     if($this->do_debug >= 2) {
738:       echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
739:     }
740: 
741:     if($code != 250) {
742:       $this->error =
743:         array("error" => "SAML not accepted from server",
744:               "smtp_code" => $code,
745:               "smtp_msg" => substr($rply,4));
746:       if($this->do_debug >= 1) {
747:         echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
748:       }
749:       return false;
750:     }
751:     return true;
752:   }
753: 
754:   /**
755:    * This is an optional command for SMTP that this class does not
756:    * support. This method is here to make the RFC821 Definition
757:    * complete for this class and __may__ be implimented in the future
758:    *
759:    * Implements from rfc 821: TURN <CRLF>
760:    *
761:    * SMTP CODE SUCCESS: 250
762:    * SMTP CODE FAILURE: 502
763:    * SMTP CODE ERROR  : 500, 503
764:    * @access public
765:    * @return bool
766:    */
767:   public function Turn() {
768:     $this->error = array("error" => "This method, TURN, of the SMTP ".
769:                                     "is not implemented");
770:     if($this->do_debug >= 1) {
771:       echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
772:     }
773:     return false;
774:   }
775: 
776:   /**
777:   * Get the current error
778:   * @access public
779:   * @return array
780:   */
781:   public function getError() {
782:     return $this->error;
783:   }
784: 
785:   /////////////////////////////////////////////////
786:   // INTERNAL FUNCTIONS
787:   /////////////////////////////////////////////////
788: 
789:   /**
790:    * Read in as many lines as possible
791:    * either before eof or socket timeout occurs on the operation.
792:    * With SMTP we can tell if we have more lines to read if the
793:    * 4th character is '-' symbol. If it is a space then we don't
794:    * need to read anything else.
795:    * @access private
796:    * @return string
797:    */
798:   private function get_lines() {
799:     $data = "";
800:     while(!feof($this->smtp_conn)) {
801:       $str = @fgets($this->smtp_conn,515);
802:       if($this->do_debug >= 4) {
803:         echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
804:         echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
805:       }
806:       $data .= $str;
807:       if($this->do_debug >= 4) {
808:         echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
809:       }
810:       // if 4th character is a space, we are done reading, break the loop
811:       if(substr($str,3,1) == " ") { break; }
812:     }
813:     return $data;
814:   }
815: 
816: }
817: 
818: ?>
819: