Getting ready for 1.4.0 RC1
[squirrelmail.git] / class / deliver / Deliver_SMTP.class.php
index 8fdbf56f717f6ee3217604796859363266ec3c41..0706105164d5f07efa0e24c41949dc98b232f2c4 100644 (file)
@@ -1,6 +1,16 @@
 <?php
+/**
+ * Deliver_SMTP.class.php
+ *
+ * Copyright (c) 1999-2003 The SquirrelMail Project Team
+ * Licensed under the GNU GPL. For full terms see the file COPYING.
+ *
+ * Delivery backend for the Deliver class.
+ *
+ * $Id$
+ */
 
-require_once('Deliver.class.php');
+require_once(SM_PATH . 'class/deliver/Deliver.class.php');
 
 class Deliver_SMTP extends Deliver {
 
@@ -12,18 +22,24 @@ class Deliver_SMTP extends Deliver {
     }
     
     function initStream($message, $domain, $length=0, $host='', $port='', $user='', $pass='', $authpop=false) {
-
-        if ($authpop) {
-          $this->authPop($host, '', $user, $pass);
+       global $use_smtp_tls,$smtp_auth_mech,$username,$key,$onetimepad;
+    
+       if ($authpop) {
+          $this->authPop($host, '', $username, $pass);
        }
-
-        $rfc822_header = $message->rfc822_header;      
+       
+    $rfc822_header = $message->rfc822_header;      
        $from = $rfc822_header->from[0];  
        $to =   $rfc822_header->to;
        $cc =   $rfc822_header->cc;
-       $bcc =   $rfc822_header->bcc;
+       $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);
+       }
 
-       $stream = fsockopen($host, $port, $errorNumber, $errorString);
        if (!$stream) {
            $this->dlv_msg = $errorString;
            $this->dlv_ret_nr = $errorNumber;
@@ -35,36 +51,83 @@ class Deliver_SMTP extends Deliver {
        }
     
        /* Lets introduce ourselves */
-       if (! isset ($use_authenticated_smtp) 
-           || $use_authenticated_smtp == false) {
-           fputs($stream, "HELO $domain\r\n");
-           $tmp = fgets($stream, 1024);
-           if ($this->errorCheck($tmp, $stream)) {
-               return(0);
-           }
-        } else {
-           fputs($stream, "EHLO $domain\r\n");
-           $tmp = fgets($stream, 1024);
-           if ($this->errorCheck($tmp, $stream)) {
-               return(0);
-           }
-           fputs($stream, "AUTH LOGIN\r\n");
-           $tmp = fgets($stream, 1024);
+       if (( $smtp_auth_mech == 'cram-md5') or ( $smtp_auth_mech == 'digest-md5' )) {
+         // Doing some form of non-plain auth
+         fputs($stream, "EHLO $domain\r\n");
+         $tmp = fgets($stream,1024);
+         if ($this->errorCheck($tmp,$stream)) {
+           return(0);
+         }
+         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($username,$pass,$chall);
+         } elseif ($smtp_auth_mech == 'digest-md5') {
+           $response = digest_md5_response($username,$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
+         fputs($stream, "HELO $domain\r\n");
+      $tmp = fgets($stream, 1024);
+         if ($this->errorCheck($tmp, $stream)) {
+        return(0);
+         }
+       } elseif ($smtp_auth_mech == 'plain') {
+         // The plain LOGIN method
+      fputs($stream, "EHLO $domain\r\n");
+      $tmp = fgets($stream, 1024);
+         if ($this->errorCheck($tmp, $stream)) {
+       return(0);
+         }
+      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);
-           }
+         if ($this->errorCheck($tmp, $stream)) {
+       return(0);
+         }
+      fputs($stream, base64_encode ($username) . "\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);
-           }
+      fputs($stream, base64_encode($pass) . "\r\n");
+      $tmp = fgets($stream, 1024);
+         if ($this->errorCheck($tmp, $stream)) {
+       return(0);
+         }
        }
     
        /* Ok, who is sending the message? */
@@ -77,26 +140,33 @@ class Deliver_SMTP extends Deliver {
        /* send who the recipients are */
        for ($i = 0, $cnt = count($to); $i < $cnt; $i++) {
            if (!$to[$i]->host) $to[$i]->host = $domain;
-           fputs($stream, 'RCPT TO: <'.$to[$i]->mailbox.'@'.$to[$i]->host.">\r\n");
-           $tmp = fgets($stream, 1024);
-           if ($this->errorCheck($tmp, $stream)) {
-               return(0);
+           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;        
-           fputs($stream, 'RCPT TO: <'.$cc[$i]->mailbox.'@'.$cc[$i]->host.">\r\n");
-           $tmp = fgets($stream, 1024);
-           if ($this->errorCheck($tmp, $stream)) {
-               return(0);
+           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;      
-           fputs($stream, 'RCPT TO: <'.$bcc[$i]->mailbox.'@'.$bcc[$i]->host.">\r\n");
-           $tmp = fgets($stream, 1024);
-           if ($this->errorCheck($tmp, $stream)) {
-               return(0);
+           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 */
@@ -122,7 +192,7 @@ class Deliver_SMTP extends Deliver {
     
     function errorCheck($line, $smtpConnection) {
        global $color, $compose_new_win;
-    
+       
        /* Read new lines on a multiline response */
        $lines = $line;
        while(ereg("^[0-9]+-", $line)) {
@@ -161,18 +231,21 @@ class Deliver_SMTP extends Deliver {
        case 221:   $message = 'Service closing transmission channel';
            $status = 5;
            break;
-       case 421:   $message = 'Service not available, closing chanel';
+       case 421:   $message = 'Service not available, closing channel';
            $status = 0;
            break;
-       case 235:   return(5); 
-           break;
+       case 235:   $message = 'Authentication successful';
+                       $status = 5;
+                       break;
        case 250:   $message = 'Requested mail action okay, completed';
            $status = 5;
            break;
        case 251:   $message = 'User not local; will forward';
            $status = 5;
            break;
-       case 334:   return(5); break;
+       case 334:   $message = 'OK - continue request';
+                       $status = 5;
+                       break;
        case 450:   $message = 'Requested mail action not taken:  mailbox unavailable';
            $status = 0;
            break;
@@ -217,6 +290,9 @@ class Deliver_SMTP extends Deliver {
            $status = 0;
            break;
         /* end RFC2554 */      
+       case 535: $message = 'Authentication failed';
+               $status = 0;
+        break;
        default:    $message = 'Unknown response: '. nl2br(htmlspecialchars($lines));
            $status = 0;
            $err_num = '001';