From eeb17be51154fb909206aef8ef251c3d8427c4a8 Mon Sep 17 00:00:00 2001 From: stekkel Date: Mon, 5 Apr 2004 23:42:26 +0000 Subject: [PATCH] Fixed sending MDN messages. According RFC2298: The From field of the message header of the MDN MUST contain the address of the person for whom the message disposition notification is being issued. The envelope sender address (i.e., SMTP MAIL FROM) of the MDN MUST be null (<>), specifying that no Delivery Status Notification messages or other messages indicating successful or unsuccessful delivery are to be sent in response to an MDN. git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@7035 7612ce4b-ef26-0410-bec9-ea0150e637f0 --- class/deliver/Deliver_SMTP.class.php | 431 ++++++++++++++------------- 1 file changed, 220 insertions(+), 211 deletions(-) diff --git a/class/deliver/Deliver_SMTP.class.php b/class/deliver/Deliver_SMTP.class.php index d1b5c950..f2e980ee 100644 --- a/class/deliver/Deliver_SMTP.class.php +++ b/class/deliver/Deliver_SMTP.class.php @@ -1,232 +1,242 @@ authPop($host, '', $user, $pass); - } - - $rfc822_header = $message->rfc822_header; - $from = $rfc822_header->from[0]; - $to = $rfc822_header->to; - $cc = $rfc822_header->cc; - $bcc = $rfc822_header->bcc; - - if (($use_smtp_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) { - $stream = fsockopen('tls://' . $host, $port, $errorNumber, $errorString); - } else { - $stream = fsockopen($host, $port, $errorNumber, $errorString); - } - - if (!$stream) { - $this->dlv_msg = $errorString; - $this->dlv_ret_nr = $errorNumber; - return(0); - } - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - - /* - * If $_SERVER['HTTP_HOST'] is set, use that in our HELO to the SMTP - * server. This should fix the DNS issues some people have had - */ - if (sqgetGlobalVar('HTTP_HOST', $HTTP_HOST, SQ_SERVER)) { // HTTP_HOST is set - // optionally trim off port number - if($p = strrpos($HTTP_HOST, ':')) { - $HTTP_HOST = substr($HTTP_HOST, 0, $p); + global $use_smtp_tls,$smtp_auth_mech; + + if ($authpop) { + $this->authPop($host, '', $user, $pass); } - $helohost = $HTTP_HOST; - } else { // For some reason, HTTP_HOST is not set - revert to old behavior - $helohost = $domain; - } - - /* Lets introduce ourselves */ - fputs($stream, "EHLO $helohost\r\n"); - $tmp = fgets($stream,1024); - if ($this->errorCheck($tmp,$stream)) { - return(0); - } - - if (( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) { - // Doing some form of non-plain auth - if ($smtp_auth_mech == 'cram-md5') { - fputs($stream, "AUTH CRAM-MD5\r\n"); - } elseif ($smtp_auth_mech == 'digest-md5') { - fputs($stream, "AUTH DIGEST-MD5\r\n"); - } - - $tmp = fgets($stream,1024); - - if ($this->errorCheck($tmp,$stream)) { - return(0); - } - - // At this point, $tmp should hold "334 " - $chall = substr($tmp,4); - // Depending on mechanism, generate response string - if ($smtp_auth_mech == 'cram-md5') { - $response = cram_md5_response($user,$pass,$chall); - } elseif ($smtp_auth_mech == 'digest-md5') { - $response = digest_md5_response($user,$pass,$chall,'smtp',$host); - } - fputs($stream, $response); - - // Let's see what the server had to say about that - $tmp = fgets($stream,1024); - if ($this->errorCheck($tmp,$stream)) { - return(0); - } - - // CRAM-MD5 is done at this point. If DIGEST-MD5, there's a bit more to go - if ($smtp_auth_mech == 'digest-md5') - { - // $tmp contains rspauth, but I don't store that yet. (No need yet) - fputs($stream,"\r\n"); - $tmp = fgets($stream,1024); - - if ($this->errorCheck($tmp,$stream)) { - return(0); - } - } - // CRAM-MD5 and DIGEST-MD5 code ends here - } elseif ($smtp_auth_mech == 'none') { - // No auth at all, just send helo and then send the mail - // We already said hi earlier, nothing more is needed. - } elseif ($smtp_auth_mech == 'login') { - // The LOGIN method - fputs($stream, "AUTH LOGIN\r\n"); - $tmp = fgets($stream, 1024); - - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - fputs($stream, base64_encode ($user) . "\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - - fputs($stream, base64_encode($pass) . "\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - } elseif ($smtp_auth_mech == "plain") { - /* SASL Plain */ - $auth = base64_encode("$user\0$user\0$pass"); - - $query = "AUTH PLAIN\r\n"; - fputs($stream, $query); - $read=fgets($stream, 1024); + + $rfc822_header = $message->rfc822_header; + + $from = $rfc822_header->from[0]; + $to = $rfc822_header->to; + $cc = $rfc822_header->cc; + $bcc = $rfc822_header->bcc; + $content_type = $rfc822_header->content_type; - if (substr($read,0,3) == '334') { // OK so far.. - fputs($stream, "$auth\r\n"); - $read = fgets($stream, 1024); - } + // MAIL FROM: MUST be empty in cae of MDN (RFC2298) + if ($content_type->type0 == 'multipart' && + $content_type->type1 == 'report' && + isset($content_type->properties['report-type']) && + $content_type->properties['report-type']=='disposition-notification') { + $from->host = ''; + $from->mailbox = ''; + } + + if (($use_smtp_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) { + $stream = fsockopen('tls://' . $host, $port, $errorNumber, $errorString); + } else { + $stream = fsockopen($host, $port, $errorNumber, $errorString); + } + + if (!$stream) { + $this->dlv_msg = $errorString; + $this->dlv_ret_nr = $errorNumber; + return(0); + } + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + + /* + * If $_SERVER['HTTP_HOST'] is set, use that in our HELO to the SMTP + * server. This should fix the DNS issues some people have had + */ + if (sqgetGlobalVar('HTTP_HOST', $HTTP_HOST, SQ_SERVER)) { // HTTP_HOST is set + // optionally trim off port number + if($p = strrpos($HTTP_HOST, ':')) { + $HTTP_HOST = substr($HTTP_HOST, 0, $p); + } + $helohost = $HTTP_HOST; + } else { // For some reason, HTTP_HOST is not set - revert to old behavior + $helohost = $domain; + } + + /* Lets introduce ourselves */ + fputs($stream, "EHLO $helohost\r\n"); + $tmp = fgets($stream,1024); + if ($this->errorCheck($tmp,$stream)) { + return(0); + } + + if (( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) { + // Doing some form of non-plain auth + if ($smtp_auth_mech == 'cram-md5') { + fputs($stream, "AUTH CRAM-MD5\r\n"); + } elseif ($smtp_auth_mech == 'digest-md5') { + fputs($stream, "AUTH DIGEST-MD5\r\n"); + } + + $tmp = fgets($stream,1024); + + if ($this->errorCheck($tmp,$stream)) { + return(0); + } + + // At this point, $tmp should hold "334 " + $chall = substr($tmp,4); + // Depending on mechanism, generate response string + if ($smtp_auth_mech == 'cram-md5') { + $response = cram_md5_response($user,$pass,$chall); + } elseif ($smtp_auth_mech == 'digest-md5') { + $response = digest_md5_response($user,$pass,$chall,'smtp',$host); + } + fputs($stream, $response); + + // Let's see what the server had to say about that + $tmp = fgets($stream,1024); + if ($this->errorCheck($tmp,$stream)) { + return(0); + } + + // CRAM-MD5 is done at this point. If DIGEST-MD5, there's a bit more to go + if ($smtp_auth_mech == 'digest-md5') { + // $tmp contains rspauth, but I don't store that yet. (No need yet) + fputs($stream,"\r\n"); + $tmp = fgets($stream,1024); - $results=explode(" ",$read,3); - $response=$results[1]; - $message=$results[2]; - - - } else { - /* Right here, they've reached an unsupported auth mechanism. - This is the ugliest hack I've ever done, but it'll do till I can fix - things up better tomorrow. So tired... */ - if ($this->errorCheck("535 Unable to use this auth type",$stream)) { - return(0); - } - } + if ($this->errorCheck($tmp,$stream)) { + return(0); + } + } + // CRAM-MD5 and DIGEST-MD5 code ends here + } elseif ($smtp_auth_mech == 'none') { + // No auth at all, just send helo and then send the mail + // We already said hi earlier, nothing more is needed. + } elseif ($smtp_auth_mech == 'login') { + // The LOGIN method + fputs($stream, "AUTH LOGIN\r\n"); + $tmp = fgets($stream, 1024); + + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + fputs($stream, base64_encode ($user) . "\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + + fputs($stream, base64_encode($pass) . "\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + } elseif ($smtp_auth_mech == "plain") { + /* SASL Plain */ + $auth = base64_encode("$user\0$user\0$pass"); + + $query = "AUTH PLAIN\r\n"; + fputs($stream, $query); + $read=fgets($stream, 1024); + + if (substr($read,0,3) == '334') { // OK so far.. + fputs($stream, "$auth\r\n"); + $read = fgets($stream, 1024); + } + + $results=explode(" ",$read,3); + $response=$results[1]; + $message=$results[2]; + } else { + /* Right here, they've reached an unsupported auth mechanism. + This is the ugliest hack I've ever done, but it'll do till I can fix + things up better tomorrow. So tired... */ + if ($this->errorCheck("535 Unable to use this auth type",$stream)) { + return(0); + } + } + + /* Ok, who is sending the message? */ + $fromaddress = ($from->mailbox && $from->host) ? + $from->mailbox.'@'.$from->host : ''; + fputs($stream, 'MAIL FROM:<'.$fromaddress.">\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + + /* send who the recipients are */ + for ($i = 0, $cnt = count($to); $i < $cnt; $i++) { + if (!$to[$i]->host) $to[$i]->host = $domain; + if ($to[$i]->mailbox) { + fputs($stream, 'RCPT TO:<'.$to[$i]->mailbox.'@'.$to[$i]->host.">\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + } + } + + for ($i = 0, $cnt = count($cc); $i < $cnt; $i++) { + if (!$cc[$i]->host) $cc[$i]->host = $domain; + if ($cc[$i]->mailbox) { + fputs($stream, 'RCPT TO:<'.$cc[$i]->mailbox.'@'.$cc[$i]->host.">\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + } + } - /* Ok, who is sending the message? */ - fputs($stream, 'MAIL FROM:<'.$from->mailbox.'@'.$from->host.">\r\n"); + for ($i = 0, $cnt = count($bcc); $i < $cnt; $i++) { + if (!$bcc[$i]->host) $bcc[$i]->host = $domain; + if ($bcc[$i]->mailbox) { + fputs($stream, 'RCPT TO:<'.$bcc[$i]->mailbox.'@'.$bcc[$i]->host.">\r\n"); + $tmp = fgets($stream, 1024); + if ($this->errorCheck($tmp, $stream)) { + return(0); + } + } + } + /* Lets start sending the actual message */ + fputs($stream, "DATA\r\n"); $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - - /* send who the recipients are */ - for ($i = 0, $cnt = count($to); $i < $cnt; $i++) { - if (!$to[$i]->host) $to[$i]->host = $domain; - if ($to[$i]->mailbox) { - fputs($stream, 'RCPT TO:<'.$to[$i]->mailbox.'@'.$to[$i]->host.">\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - } - } - - for ($i = 0, $cnt = count($cc); $i < $cnt; $i++) { - if (!$cc[$i]->host) $cc[$i]->host = $domain; - if ($cc[$i]->mailbox) { - fputs($stream, 'RCPT TO:<'.$cc[$i]->mailbox.'@'.$cc[$i]->host.">\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - } - } - - for ($i = 0, $cnt = count($bcc); $i < $cnt; $i++) { - if (!$bcc[$i]->host) $bcc[$i]->host = $domain; - if ($bcc[$i]->mailbox) { - fputs($stream, 'RCPT TO:<'.$bcc[$i]->mailbox.'@'.$bcc[$i]->host.">\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - } + if ($this->errorCheck($tmp, $stream)) { + return(0); } - /* Lets start sending the actual message */ - fputs($stream, "DATA\r\n"); - $tmp = fgets($stream, 1024); - if ($this->errorCheck($tmp, $stream)) { - return(0); - } - return $stream; + return $stream; } function finalizeStream($stream) { - fputs($stream, "\r\n.\r\n"); /* end the DATA part */ - $tmp = fgets($stream, 1024); - $this->errorCheck($tmp, $stream); - if ($this->dlv_ret_nr != 250) { - return(0); - } - fputs($stream, "QUIT\r\n"); /* log off */ - fclose($stream); - return true; + fputs($stream, "\r\n.\r\n"); /* end the DATA part */ + $tmp = fgets($stream, 1024); + $this->errorCheck($tmp, $stream); + if ($this->dlv_ret_nr != 250) { + return(0); + } + fputs($stream, "QUIT\r\n"); /* log off */ + fclose($stream); + return true; } /* check if an SMTP reply is an error and set an error message) */ @@ -241,9 +251,8 @@ class Deliver_SMTP extends Deliver { $server_msg .= substr($line, 4); } - if ( ((int) $err_num{0}) < 4) - { - return false; + if ( ((int) $err_num{0}) < 4) { + return false; } switch ($err_num) { @@ -307,7 +316,7 @@ class Deliver_SMTP extends Deliver { $popConnection = fsockopen($pop_server, $pop_port, $err_no, $err_str); if (!$popConnection) { error_log("Error connecting to POP Server ($pop_server:$pop_port)" - . " $err_no : $err_str"); + . " $err_no : $err_str"); } else { $tmp = fgets($popConnection, 1024); /* banner */ if (substr($tmp, 0, 3) != '+OK') { -- 2.25.1