PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/pmfv2-1-0-alpha-1/inc/class.smtp.php

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