<?php
define("DEBUG", true);
function _HMAC_MD5($key, $data) {
$pass = $key;
if (strlen($key)>64) {
$key = pack('H32',md5($pass));
}
if (strlen($key)<64) {
$key = str_pad($key, 64, chr(0));
}
$k_ipad = '';
$k_opad = '';
for( $i = 0; $i < 64; $i++ ) {
$byte = ord($key{$i});
$k_ipad .= chr( $byte ^ 0x36);
$k_opad .= chr( $byte ^ 0x5C);
}
$inner = pack('H32', md5($k_ipad . $data));
$digest = md5($k_opad . $inner);
return $digest;
}
function SmtpAuthCramMd5Mail($to,$from,$subject,$headers,$message,$user,$password) {
$timeout = 25; // timeout of request;
if (DEBUG) {
echo "<pre>";
echo "function SmtpAuthCramMd5Mail();\n\n";
echo "TO: $to\n";
echo "FROM: $from\n";
echo "SUBJECT: $subject\n";
echo "HEADERS:\n$headers\n";
echo "MESSAGE:\n$message\n";
echo "USER: $user\n";
echo "PASSWORD: ";
for( $i=0; $i < strlen($password); $i++) {
echo "*";
}
echo "\n";
}
list($me,$mydomain) = split("@",$from);
if (DEBUG) {
echo "USEFROM: $me\n";
echo "DOMAINFROM: $mydomain\n";
}
//Lets word with smtp server of user from
/*// Now look up the mail exchangers for the recipient
list($user,$domain) = split("@",$to,2);*/
$domain = $mydomain;
/* if (DEBUG) {
echo "USERTO: $user\n";
echo "DOMAINTO: $domain\n";
}*/
if( getmxrr($domain,$mx,$weight) == 0 ) {
if (DEBUG) {
echo "Can not find MX record, returned\n";
}
return FALSE;
}
// Try them in order of lowest weight first
array_multisort($mx,$weight);
$success=0;
foreach($mx as $host) {
// Open an SMTP connection
$connection = fsockopen ($host, 25, &$errno, &$errstr, $timeout);
if (!$connection) {
if (DEBUG) {
echo "Can not connect to $host:25 with timeout $timeout, continue\n";
echo "Error #$errno\n";
echo "Error string: $errstr\n";
}
continue;
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if (substr($res,0,3) != "220") {
if (DEBUG) {
echo "Server answer is not 220, break\n";
}
break;
}
// Introduce ourselves
fputs($connection, "EHLO $mydomain\n");
if (DEBUG) {
echo "C<< EHLO $mydomain\n";
}
$cramMd5Allowed = false;
//read all server send
while (true) {
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if (strpos($res,"CRAM-MD5") && (strpos($res,"AUTH"))) {
$cramMd5Allowed = true;
}
if(substr($res,0,3) != "250") {
if (DEBUG) {
echo "Server answer is not 250, break\n";
}
break;
}
$status = socket_get_status($connection);
if ( $status["unread_bytes"] == 0) break;
}
if ( $cramMd5Allowed ) {
//Authorization CRAM-MD5
// _HMAC_MD5($key,$data);
//Auth
fputs($connection, "AUTH CRAM-MD5\n");
if (DEBUG) {
echo "C<< AUTH CRAM-MD5\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "334") {
if (DEBUG) {
echo "Server answer is not 334, break\n";
}
break;
}
list($none,$data) = split(" ", $res, 2);
$data = base64_decode( $data );
$data = str_replace("\n","",$data);
$diggest = _HMAC_MD5( $password, $data);
$tosend = base64_encode($user." ".$diggest);
fputs($connection, "$tosend\n");
if (DEBUG) {
echo "C<< $tosend\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "235") {
if (DEBUG) {
echo "Server answer is not 235, break\n";
}
break;
}
}
// Envelope from
fputs($connection, "MAIL FROM: $from\n");
if (DEBUG) {
echo "C<< MAIL FROM: $from\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "250") {
if (DEBUG) {
echo "Server answer is not 250, break\n";
}
break;
}
// Envelope to
fputs($connection, "RCPT TO: $to\n");
if (DEBUG) {
echo "C<< RCPT TO: $to\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "250") {
if (DEBUG) {
echo "Server answer is not 250, break\n";
}
break;
}
// The message
fputs($connection, "DATA\n");
if (DEBUG) {
echo "C<< DATA\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "354") {
if (DEBUG) {
echo "Server answer is not 354, break\n";
}
break;
}
// Send To:, From:, Subject:, other headers, blank line, message, and finish
// with a period on its own line.
// Stop: \r\n required instead \n !!!
fputs($connection, "To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
if (DEBUG) {
echo "C<< To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "250") {
if (DEBUG) {
echo "Server answer is not 250, break\n";
}
break;
}
// Say bye bye
fputs($connection,"QUIT\n");
if (DEBUG) {
echo "C<< QUIT\n";
}
$res=fgets($connection,256);
if (DEBUG) {
echo "S>> $res";
}
if(substr($res,0,3) != "221") {
if (DEBUG) {
echo "Server answer is not 221, break\n";
}
break;
}
// It worked! So break out of the loop which tries all the mail exchangers.
$success=1;
if (DEBUG) {
echo "function SmtpAuthCramMd5Mail();";
echo "SUCCESS\n";
}
break;
}
// Debug for if we fall over - uncomment as desired
// print $success?"Mail sent":"Failure: $res\n";
if($connection) {
if($success==0) fputs($connection, "QUIT\n");
fclose ($connection);
}
if (DEBUG) {
echo "</pre>";
}
return $success?TRUE:FALSE;
}
SmtpAuthCramMd5Mail($to,$from,$subject,$headers,$message,$user,$password);
?>