class.smtp.php 27 KB

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