Project

General

Profile

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
?>
(6-6/7)