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