PageRenderTime 59ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/e/class/class.smtp.php

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