* * Description: a VERY simple (and probably not totally RFC 2821 compliant) * smtp client. This was borne out of frustration that PHP's own * mail() routine always invokes a sendmail binary instead of * using SMTP on *NIX machines. It was also my attempt at learning * more about PHP's socket library, and rfc 282[1|2]. * * Resources: * http://phpmailer.sourceforge.net * http://www.phpguru.org/static/smtp.html * http://www.faqs.org/rfcs/rfc2821.html * http://www.faqs.org/rfcs/rfc2822.html */ /* Returns the 3 digit code from an MTA response */ function get_smtp_code( $string ) { return( substr( trim($string) , 0, 3 ) ); } /* A simple function to connect, unencrypted, to an SMTP server of your choice and then * send an email message. One transaction and message per function call, with an arbitary * number of cc's and bcc's, up to your mail server's limits. (Postfix, around 10000 each.) * * Please note this function does NOT validate input. That should be the job of the program * driving this function. So please, check your addresses! */ function send_smtp_mail( $server, $to, $from, $subject, $message, $cc = "", $bcc = "", $extra_headers = "" ) { //$debug = true; /* Since we must wait for replies from the mail server, we'll have to open the socket once, * do a series of fwrite() and fread() calls to handle the headers, then one fwrite() call * for data. */ $socket = fsockopen( $server, 25, $errno, $errstr, 30 ); if( !$socket ) { echo("Error connecting to $server on port 25.\r\n"); if($debug) { echo("$errstr - ($errno)\n"); } fclose( $socket ); exit(1); } $response = fread( $socket, 100 ); $code = get_smtp_code( $response ); if( 220 != $code ) { echo("No ESMTP response.\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(99); } fwrite( $socket, "HELO pwnzors\r\n" ); $response = fgets( $socket, 100 ); if( 250 != get_smtp_code( $response ) ) { echo("Failed at HELO stage\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(2); } fwrite( $socket, "mail from: $from\r\n" ); $response = fgets( $socket, 100 ); if( 250 != get_smtp_code( $response ) ) { echo("Failed at mail from: $from stage\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(3); } /* per RFC 2821, each person listed in Bcc: must be RCPT TO:'d, so we * split that string into an array, and then append the $to variable * to the end, thus doing all our rcpt work in one fell swoop. */ $bccs = split( ",", $bcc ); $bccs[] = $to; if($debug) { print_r($bccs); } foreach( $bccs as $addy ) { fwrite( $socket, "rcpt to: " . trim($addy) . "\r\n" ); $response = fgets( $socket, 100 ); if( 250 != get_smtp_code( $response ) ) { echo("Failed at rcpt to: $addy stage\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(4); } } fwrite( $socket, "data\r\n" ); $response = fgets( $socket, 80 ); if( 354 != get_smtp_code( $response ) ) { echo("Failed at data stage.\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(5); } /* writing additional headers. * Do I need the Date: header? For now, I'm leaving it off, but the RFC2821 format * is gained by passing the format string: "r" to date(). I think most MTA's will * take care of this for you though, Postfix seems to. */ fwrite( $socket, "From: $from\r\nTo: $to\r\nSubject:$subject\r\n" ); /* write message */ fwrite( $socket, $message."\r\n" ); /* queue and close connection */ fwrite( $socket, "\r\n.\r\n" ); $response = fgets( $socket, 80 ); if( 250 != get_smtp_code( $response ) ) { echo("Failed at queuing stage.\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(6); } fwrite( $socket, "quit\r\n" ); $response = fgets( $socket, 80 ); if( 221 != get_smtp_code( $response ) ) { echo("Failed at quitting stage.\n"); if($debug) { echo("Server response: $response\n"); } fclose( $socket ); exit(7); } fclose( $socket ); return true; } ?>