Fixed sending MDN messages. According RFC2298:
authorstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 5 Apr 2004 23:42:26 +0000 (23:42 +0000)
committerstekkel <stekkel@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Mon, 5 Apr 2004 23:42:26 +0000 (23:42 +0000)
   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

index d1b5c95..f2e980e 100644 (file)
 <?php
 /**
 <?php
 /**
- * Deliver_SMTP.class.php
- *
- * Copyright (c) 1999-2004 The SquirrelMail Project Team
- * Licensed under the GNU GPL. For full terms see the file COPYING.
- *
- * Delivery backend for the Deliver class.
- *
- * $Id$
- * @package squirrelmail
- */
+* Deliver_SMTP.class.php
+*
+* Copyright (c) 1999-2004 The SquirrelMail Project Team
+* Licensed under the GNU GPL. For full terms see the file COPYING.
+*
+* Delivery backend for the Deliver class.
+*
+* $Id$
+* @package squirrelmail
+*/
 
 /** This of course depends upon Deliver */
 require_once(SM_PATH . 'class/deliver/Deliver.class.php');
 
 /**
 
 /** This of course depends upon Deliver */
 require_once(SM_PATH . 'class/deliver/Deliver.class.php');
 
 /**
- * Deliver messages using SMTP
- * @package squirrelmail
- */
+* Deliver messages using SMTP
+* @package squirrelmail
+*/
 class Deliver_SMTP extends Deliver {
 
     function preWriteToStream(&$s) {
 class Deliver_SMTP extends Deliver {
 
     function preWriteToStream(&$s) {
-       if ($s) {
-          if ($s{0} == '.')   $s = '.' . $s;
-         $s = str_replace("\n.","\n..",$s);
-       }
+        if ($s) {
+            if ($s{0} == '.')   $s = '.' . $s;
+            $s = str_replace("\n.","\n..",$s);
+        }
     }
     
     function initStream($message, $domain, $length=0, $host='', $port='', $user='', $pass='', $authpop=false) {
     }
     
     function initStream($message, $domain, $length=0, $host='', $port='', $user='', $pass='', $authpop=false) {
-       global $use_smtp_tls,$smtp_auth_mech;
-
-       if ($authpop) {
-          $this->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 <challenge string>"
-         $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: <from address> 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 <challenge string>"
+            $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);
         $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) {
     }
     
     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) */
     }
     
     /* 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);
         }
 
             $server_msg .= substr($line, 4);
         }
 
-        if ( ((int) $err_num{0}) < 4)
-        {
-               return false;
+        if ( ((int) $err_num{0}) < 4) {
+            return false;
         }
 
         switch ($err_num) {
         }
 
         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)"
         $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') {
         } else {
             $tmp = fgets($popConnection, 1024); /* banner */
             if (substr($tmp, 0, 3) != '+OK') {