00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00036
00041
00042
00047
00048
00053
00054
00059
00060
00064
00065
00066
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00099 public function Connect($host,$port=0,$tval=30) {
00100
00101 $this->error = null;
00102
00103
00104 if($this->connected()) {
00105
00106
00107
00108
00109 $this->error = array("error" => "Already connected to a server");
00110 return false;
00111 }
00112
00113 if(empty($port)) {
00114 $port = $this->SMTP_PORT;
00115 }
00116
00117
00118 $this->smtp_conn = fsockopen($host,
00119 $port,
00120 $errno,
00121 $errstr,
00122 $tval);
00123
00124 if(empty($this->smtp_conn)) {
00125 $this->error = array("error" => "Failed to connect to server",
00126 "errno" => $errno,
00127 "errstr" => $errstr);
00128 if($this->do_debug >= 1) {
00129 echo "SMTP -> ERROR: " . $this->error["error"] .
00130 ": $errstr ($errno)" . $this->CRLF;
00131 }
00132 return false;
00133 }
00134
00135
00136
00137
00138
00139 if(substr(PHP_OS, 0, 3) != "WIN")
00140 socket_set_timeout($this->smtp_conn, $tval, 0);
00141
00142
00143 $announce = $this->get_lines();
00144
00145
00146
00147
00148
00149 if($this->do_debug >= 2) {
00150 echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
00151 }
00152
00153 return true;
00154 }
00155
00165 public function StartTLS() {
00166 $this->error = null; # to avoid confusion
00167
00168 if(!$this->connected()) {
00169 $this->error = array("error" => "Called StartTLS() without being connected");
00170 return false;
00171 }
00172
00173 fputs($this->smtp_conn,"STARTTLS" . $extra . $this->CRLF);
00174
00175 $rply = $this->get_lines();
00176 $code = substr($rply,0,3);
00177
00178 if($this->do_debug >= 2) {
00179 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00180 }
00181
00182 if($code != 220) {
00183 $this->error =
00184 array("error" => "STARTTLS not accepted from server",
00185 "smtp_code" => $code,
00186 "smtp_msg" => substr($rply,4));
00187 if($this->do_debug >= 1) {
00188 echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF;
00189 }
00190 return false;
00191 }
00192
00193
00194 if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
00195 return false;
00196 }
00197
00198 return true;
00199 }
00200
00207 public function Authenticate($username, $password) {
00208
00209 fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
00210
00211 $rply = $this->get_lines();
00212 $code = substr($rply,0,3);
00213
00214 if($code != 334) {
00215 $this->error =
00216 array("error" => "AUTH not accepted from server",
00217 "smtp_code" => $code,
00218 "smtp_msg" => substr($rply,4));
00219 if($this->do_debug >= 1) {
00220 echo "SMTP -> ERROR: " . $this->error["error"] .
00221 ": " . $rply . $this->CRLF;
00222 }
00223 return false;
00224 }
00225
00226
00227 fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
00228
00229 $rply = $this->get_lines();
00230 $code = substr($rply,0,3);
00231
00232 if($code != 334) {
00233 $this->error =
00234 array("error" => "Username not accepted from server",
00235 "smtp_code" => $code,
00236 "smtp_msg" => substr($rply,4));
00237 if($this->do_debug >= 1) {
00238 echo "SMTP -> ERROR: " . $this->error["error"] .
00239 ": " . $rply . $this->CRLF;
00240 }
00241 return false;
00242 }
00243
00244
00245 fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
00246
00247 $rply = $this->get_lines();
00248 $code = substr($rply,0,3);
00249
00250 if($code != 235) {
00251 $this->error =
00252 array("error" => "Password not accepted from server",
00253 "smtp_code" => $code,
00254 "smtp_msg" => substr($rply,4));
00255 if($this->do_debug >= 1) {
00256 echo "SMTP -> ERROR: " . $this->error["error"] .
00257 ": " . $rply . $this->CRLF;
00258 }
00259 return false;
00260 }
00261
00262 return true;
00263 }
00264
00270 public function Connected() {
00271 if(!empty($this->smtp_conn)) {
00272 $sock_status = socket_get_status($this->smtp_conn);
00273 if($sock_status["eof"]) {
00274
00275
00276 if($this->do_debug >= 1) {
00277 echo "SMTP -> NOTICE:" . $this->CRLF .
00278 "EOF caught while checking if connected";
00279 }
00280 $this->Close();
00281 return false;
00282 }
00283 return true;
00284 }
00285 return false;
00286 }
00287
00295 public function Close() {
00296 $this->error = null;
00297 $this->helo_rply = null;
00298 if(!empty($this->smtp_conn)) {
00299
00300 fclose($this->smtp_conn);
00301 $this->smtp_conn = 0;
00302 }
00303 }
00304
00305
00306
00307
00308
00328 public function Data($msg_data) {
00329 $this->error = null;
00330
00331 if(!$this->connected()) {
00332 $this->error = array(
00333 "error" => "Called Data() without being connected");
00334 return false;
00335 }
00336
00337 fputs($this->smtp_conn,"DATA" . $this->CRLF);
00338
00339 $rply = $this->get_lines();
00340 $code = substr($rply,0,3);
00341
00342 if($this->do_debug >= 2) {
00343 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00344 }
00345
00346 if($code != 354) {
00347 $this->error =
00348 array("error" => "DATA command not accepted from server",
00349 "smtp_code" => $code,
00350 "smtp_msg" => substr($rply,4));
00351 if($this->do_debug >= 1) {
00352 echo "SMTP -> ERROR: " . $this->error["error"] .
00353 ": " . $rply . $this->CRLF;
00354 }
00355 return false;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 $msg_data = str_replace("\r\n","\n",$msg_data);
00371 $msg_data = str_replace("\r","\n",$msg_data);
00372 $lines = explode("\n",$msg_data);
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 $field = substr($lines[0],0,strpos($lines[0],":"));
00383 $in_headers = false;
00384 if(!empty($field) && !strstr($field," ")) {
00385 $in_headers = true;
00386 }
00387
00388 $max_line_length = 998;
00389
00390 while(list(,$line) = @each($lines)) {
00391 $lines_out = null;
00392 if($line == "" && $in_headers) {
00393 $in_headers = false;
00394 }
00395
00396 while(strlen($line) > $max_line_length) {
00397 $pos = strrpos(substr($line,0,$max_line_length)," ");
00398
00399
00400 if(!$pos) {
00401 $pos = $max_line_length - 1;
00402 $lines_out[] = substr($line,0,$pos);
00403 $line = substr($line,$pos);
00404 } else {
00405 $lines_out[] = substr($line,0,$pos);
00406 $line = substr($line,$pos + 1);
00407 }
00408
00409
00410
00411
00412
00413 if($in_headers) {
00414 $line = "\t" . $line;
00415 }
00416 }
00417 $lines_out[] = $line;
00418
00419
00420 while(list(,$line_out) = @each($lines_out)) {
00421 if(strlen($line_out) > 0)
00422 {
00423 if(substr($line_out, 0, 1) == ".") {
00424 $line_out = "." . $line_out;
00425 }
00426 }
00427 fputs($this->smtp_conn,$line_out . $this->CRLF);
00428 }
00429 }
00430
00431
00432
00433 fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
00434
00435 $rply = $this->get_lines();
00436 $code = substr($rply,0,3);
00437
00438 if($this->do_debug >= 2) {
00439 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00440 }
00441
00442 if($code != 250) {
00443 $this->error =
00444 array("error" => "DATA not accepted from server",
00445 "smtp_code" => $code,
00446 "smtp_msg" => substr($rply,4));
00447 if($this->do_debug >= 1) {
00448 echo "SMTP -> ERROR: " . $this->error["error"] .
00449 ": " . $rply . $this->CRLF;
00450 }
00451 return false;
00452 }
00453 return true;
00454 }
00455
00472 public function Expand($name) {
00473 $this->error = null;
00474
00475 if(!$this->connected()) {
00476 $this->error = array(
00477 "error" => "Called Expand() without being connected");
00478 return false;
00479 }
00480
00481 fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
00482
00483 $rply = $this->get_lines();
00484 $code = substr($rply,0,3);
00485
00486 if($this->do_debug >= 2) {
00487 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00488 }
00489
00490 if($code != 250) {
00491 $this->error =
00492 array("error" => "EXPN not accepted from server",
00493 "smtp_code" => $code,
00494 "smtp_msg" => substr($rply,4));
00495 if($this->do_debug >= 1) {
00496 echo "SMTP -> ERROR: " . $this->error["error"] .
00497 ": " . $rply . $this->CRLF;
00498 }
00499 return false;
00500 }
00501
00502
00503 $entries = explode($this->CRLF,$rply);
00504 while(list(,$l) = @each($entries)) {
00505 $list[] = substr($l,4);
00506 }
00507
00508 return $list;
00509 }
00510
00523 public function Hello($host="") {
00524 $this->error = null;
00525
00526 if(!$this->connected()) {
00527 $this->error = array(
00528 "error" => "Called Hello() without being connected");
00529 return false;
00530 }
00531
00532
00533
00534 if(empty($host)) {
00535
00536
00537 $host = "localhost";
00538 }
00539
00540
00541 if(!$this->SendHello("EHLO", $host))
00542 {
00543 if(!$this->SendHello("HELO", $host))
00544 return false;
00545 }
00546
00547 return true;
00548 }
00549
00555 private function SendHello($hello, $host) {
00556 fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
00557
00558 $rply = $this->get_lines();
00559 $code = substr($rply,0,3);
00560
00561 if($this->do_debug >= 2) {
00562 echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
00563 }
00564
00565 if($code != 250) {
00566 $this->error =
00567 array("error" => $hello . " not accepted from server",
00568 "smtp_code" => $code,
00569 "smtp_msg" => substr($rply,4));
00570 if($this->do_debug >= 1) {
00571 echo "SMTP -> ERROR: " . $this->error["error"] .
00572 ": " . $rply . $this->CRLF;
00573 }
00574 return false;
00575 }
00576
00577 $this->helo_rply = $rply;
00578
00579 return true;
00580 }
00581
00597 public function Help($keyword="") {
00598 $this->error = null;
00599
00600 if(!$this->connected()) {
00601 $this->error = array(
00602 "error" => "Called Help() without being connected");
00603 return false;
00604 }
00605
00606 $extra = "";
00607 if(!empty($keyword)) {
00608 $extra = " " . $keyword;
00609 }
00610
00611 fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
00612
00613 $rply = $this->get_lines();
00614 $code = substr($rply,0,3);
00615
00616 if($this->do_debug >= 2) {
00617 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00618 }
00619
00620 if($code != 211 && $code != 214) {
00621 $this->error =
00622 array("error" => "HELP not accepted from server",
00623 "smtp_code" => $code,
00624 "smtp_msg" => substr($rply,4));
00625 if($this->do_debug >= 1) {
00626 echo "SMTP -> ERROR: " . $this->error["error"] .
00627 ": " . $rply . $this->CRLF;
00628 }
00629 return false;
00630 }
00631
00632 return $rply;
00633 }
00634
00649 public function Mail($from) {
00650 $this->error = null;
00651
00652 if(!$this->connected()) {
00653 $this->error = array(
00654 "error" => "Called Mail() without being connected");
00655 return false;
00656 }
00657
00658 $useVerp = ($this->do_verp ? "XVERP" : "");
00659 fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
00660
00661 $rply = $this->get_lines();
00662 $code = substr($rply,0,3);
00663
00664 if($this->do_debug >= 2) {
00665 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00666 }
00667
00668 if($code != 250) {
00669 $this->error =
00670 array("error" => "MAIL not accepted from server",
00671 "smtp_code" => $code,
00672 "smtp_msg" => substr($rply,4));
00673 if($this->do_debug >= 1) {
00674 echo "SMTP -> ERROR: " . $this->error["error"] .
00675 ": " . $rply . $this->CRLF;
00676 }
00677 return false;
00678 }
00679 return true;
00680 }
00681
00692 public function Noop() {
00693 $this->error = null;
00694
00695 if(!$this->connected()) {
00696 $this->error = array(
00697 "error" => "Called Noop() without being connected");
00698 return false;
00699 }
00700
00701 fputs($this->smtp_conn,"NOOP" . $this->CRLF);
00702
00703 $rply = $this->get_lines();
00704 $code = substr($rply,0,3);
00705
00706 if($this->do_debug >= 2) {
00707 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00708 }
00709
00710 if($code != 250) {
00711 $this->error =
00712 array("error" => "NOOP not accepted from server",
00713 "smtp_code" => $code,
00714 "smtp_msg" => substr($rply,4));
00715 if($this->do_debug >= 1) {
00716 echo "SMTP -> ERROR: " . $this->error["error"] .
00717 ": " . $rply . $this->CRLF;
00718 }
00719 return false;
00720 }
00721 return true;
00722 }
00723
00735 public function Quit($close_on_error=true) {
00736 $this->error = null;
00737
00738 if(!$this->connected()) {
00739 $this->error = array(
00740 "error" => "Called Quit() without being connected");
00741 return false;
00742 }
00743
00744
00745 fputs($this->smtp_conn,"quit" . $this->CRLF);
00746
00747
00748 $byemsg = $this->get_lines();
00749
00750 if($this->do_debug >= 2) {
00751 echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
00752 }
00753
00754 $rval = true;
00755 $e = null;
00756
00757 $code = substr($byemsg,0,3);
00758 if($code != 221) {
00759
00760 $e = array("error" => "SMTP server rejected quit command",
00761 "smtp_code" => $code,
00762 "smtp_rply" => substr($byemsg,4));
00763 $rval = false;
00764 if($this->do_debug >= 1) {
00765 echo "SMTP -> ERROR: " . $e["error"] . ": " .
00766 $byemsg . $this->CRLF;
00767 }
00768 }
00769
00770 if(empty($e) || $close_on_error) {
00771 $this->Close();
00772 }
00773
00774 return $rval;
00775 }
00776
00789 public function Recipient($to) {
00790 $this->error = null;
00791
00792 if(!$this->connected()) {
00793 $this->error = array(
00794 "error" => "Called Recipient() without being connected");
00795 return false;
00796 }
00797
00798 fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
00799
00800 $rply = $this->get_lines();
00801 $code = substr($rply,0,3);
00802
00803 if($this->do_debug >= 2) {
00804 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00805 }
00806
00807 if($code != 250 && $code != 251) {
00808 $this->error =
00809 array("error" => "RCPT not accepted from server",
00810 "smtp_code" => $code,
00811 "smtp_msg" => substr($rply,4));
00812 if($this->do_debug >= 1) {
00813 echo "SMTP -> ERROR: " . $this->error["error"] .
00814 ": " . $rply . $this->CRLF;
00815 }
00816 return false;
00817 }
00818 return true;
00819 }
00820
00833 public function Reset() {
00834 $this->error = null;
00835
00836 if(!$this->connected()) {
00837 $this->error = array(
00838 "error" => "Called Reset() without being connected");
00839 return false;
00840 }
00841
00842 fputs($this->smtp_conn,"RSET" . $this->CRLF);
00843
00844 $rply = $this->get_lines();
00845 $code = substr($rply,0,3);
00846
00847 if($this->do_debug >= 2) {
00848 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00849 }
00850
00851 if($code != 250) {
00852 $this->error =
00853 array("error" => "RSET failed",
00854 "smtp_code" => $code,
00855 "smtp_msg" => substr($rply,4));
00856 if($this->do_debug >= 1) {
00857 echo "SMTP -> ERROR: " . $this->error["error"] .
00858 ": " . $rply . $this->CRLF;
00859 }
00860 return false;
00861 }
00862
00863 return true;
00864 }
00865
00882 public function Send($from) {
00883 $this->error = null;
00884
00885 if(!$this->connected()) {
00886 $this->error = array(
00887 "error" => "Called Send() without being connected");
00888 return false;
00889 }
00890
00891 fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
00892
00893 $rply = $this->get_lines();
00894 $code = substr($rply,0,3);
00895
00896 if($this->do_debug >= 2) {
00897 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00898 }
00899
00900 if($code != 250) {
00901 $this->error =
00902 array("error" => "SEND not accepted from server",
00903 "smtp_code" => $code,
00904 "smtp_msg" => substr($rply,4));
00905 if($this->do_debug >= 1) {
00906 echo "SMTP -> ERROR: " . $this->error["error"] .
00907 ": " . $rply . $this->CRLF;
00908 }
00909 return false;
00910 }
00911 return true;
00912 }
00913
00930 public function SendAndMail($from) {
00931 $this->error = null;
00932
00933 if(!$this->connected()) {
00934 $this->error = array(
00935 "error" => "Called SendAndMail() without being connected");
00936 return false;
00937 }
00938
00939 fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
00940
00941 $rply = $this->get_lines();
00942 $code = substr($rply,0,3);
00943
00944 if($this->do_debug >= 2) {
00945 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00946 }
00947
00948 if($code != 250) {
00949 $this->error =
00950 array("error" => "SAML not accepted from server",
00951 "smtp_code" => $code,
00952 "smtp_msg" => substr($rply,4));
00953 if($this->do_debug >= 1) {
00954 echo "SMTP -> ERROR: " . $this->error["error"] .
00955 ": " . $rply . $this->CRLF;
00956 }
00957 return false;
00958 }
00959 return true;
00960 }
00961
00978 public function SendOrMail($from) {
00979 $this->error = null;
00980
00981 if(!$this->connected()) {
00982 $this->error = array(
00983 "error" => "Called SendOrMail() without being connected");
00984 return false;
00985 }
00986
00987 fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
00988
00989 $rply = $this->get_lines();
00990 $code = substr($rply,0,3);
00991
00992 if($this->do_debug >= 2) {
00993 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
00994 }
00995
00996 if($code != 250) {
00997 $this->error =
00998 array("error" => "SOML not accepted from server",
00999 "smtp_code" => $code,
01000 "smtp_msg" => substr($rply,4));
01001 if($this->do_debug >= 1) {
01002 echo "SMTP -> ERROR: " . $this->error["error"] .
01003 ": " . $rply . $this->CRLF;
01004 }
01005 return false;
01006 }
01007 return true;
01008 }
01009
01023 public function Turn() {
01024 $this->error = array("error" => "This method, TURN, of the SMTP ".
01025 "is not implemented");
01026 if($this->do_debug >= 1) {
01027 echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
01028 }
01029 return false;
01030 }
01031
01045 public function Verify($name) {
01046 $this->error = null;
01047
01048 if(!$this->connected()) {
01049 $this->error = array(
01050 "error" => "Called Verify() without being connected");
01051 return false;
01052 }
01053
01054 fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
01055
01056 $rply = $this->get_lines();
01057 $code = substr($rply,0,3);
01058
01059 if($this->do_debug >= 2) {
01060 echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
01061 }
01062
01063 if($code != 250 && $code != 251) {
01064 $this->error =
01065 array("error" => "VRFY failed on name '$name'",
01066 "smtp_code" => $code,
01067 "smtp_msg" => substr($rply,4));
01068 if($this->do_debug >= 1) {
01069 echo "SMTP -> ERROR: " . $this->error["error"] .
01070 ": " . $rply . $this->CRLF;
01071 }
01072 return false;
01073 }
01074 return $rply;
01075 }
01076
01077
01078
01079
01080
01090 private function get_lines() {
01091 $data = "";
01092 while($str = @fgets($this->smtp_conn,515)) {
01093 if($this->do_debug >= 4) {
01094 echo "SMTP -> get_lines(): \$data was \"$data\"" .
01095 $this->CRLF;
01096 echo "SMTP -> get_lines(): \$str is \"$str\"" .
01097 $this->CRLF;
01098 }
01099 $data .= $str;
01100 if($this->do_debug >= 4) {
01101 echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
01102 }
01103
01104
01105 if(substr($str,3,1) == " ") { break; }
01106 }
01107 return $data;
01108 }
01109
01110 }
01111
01112
01113 ?>