class.smtp.php 25 KB

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