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