Advertisement
carbonize

SMTP Sending

Aug 12th, 2011
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.34 KB | None | 0 0
  1. <?php
  2. /*
  3.  * SMTP Email Sending
  4.  * By Stewart Souter
  5.  * Date Created: Thurs, 11 August 2011 17:15:37 GMT
  6.  * Last Updated: Fri, 19 August 2011 10:54:35 GMT
  7.  *
  8.  * By using this script you are agreeing to leave this
  9.  * comment and agreement in place and untouched. If you
  10.  * use any part of this code you must make it clear where
  11.  * it came from and give credit where it is due.
  12.  */
  13.  
  14. $mailCfg['Server']    = '';    // Servername
  15. $mailCfg['User']      = '';    // SMTP username if needed
  16. $mailCfg['Pass']      = '';    // SMTP Password if needed
  17. $mailCfg['Port']      = 25;    // SMTP server port. 25 is the usual and 465 if using SSL
  18. $mailCfg['popServer'] = '';    // Name of the pop server. Leave empty if POP Auth not required
  19. $mailCfg['popPort']   = 110;   // Port for the pop server. 110 is the usual and 995 if using SSL
  20. $mailCfg['SSL']       = 0;     // Does your SMTP server need you to use SSL or TLS? 0 = no, 1 = SSL, 2 = TLS
  21.  
  22. // This function delivers the email directly to the recipients mail server so bypassing the need for your own
  23. function directMail($mailTo, $mailSubject, $mailMsg, $mailHeaders = '', $mailFrom = '', $mailCfg)
  24. {
  25.   if(empty($mailFrom))
  26.   {
  27.     return false; // No from address == no sending
  28.   }
  29.   $mailParts = explode('@', $mailTo);  // Seperate the parts of the email address
  30.   @getmxrr($mailParts[1], $mxHosts, $mxWeight); // Get the MX records for the emails domain
  31.   for($i=0;$i<count($mxHosts);$i++) // Put the records and weights into an array
  32.   {
  33.       $mxServers[$mxHosts[$i]] = $mxWeight[$i];
  34.   }
  35.   asort($mxServers); // Sort the array so they are in weighted order
  36.   foreach($mxServers as $key => $value)
  37.   {
  38.     $mailCfg['Server'] = $key; // Set the SMTP server to the current MX record
  39.     if(smtpMail($mailTo, $mailSubject, $mailMsg, $mailHeaders, $mailFrom, $mailCfg)) // Send the email using the MX server
  40.     {
  41.       return true;  // The email was successfully sent
  42.     }
  43.   }
  44.   return false;  // Houston we have a problem
  45. }
  46.  
  47. // This function connects to the SMTP server and does the AUTH if needed. Can also do a POP login if server requires that.
  48. function smtpMail($mailTo, $mailSubject, $mailMsg, $mailHeaders = '', $mailFrom = '', $mailCfg )
  49. {
  50.   if(empty($mailFrom))
  51.   {
  52.     return false; // No from address == no sending
  53.   }
  54.   $timeout = '30'; // How long to keep trying to connect
  55.   $localhost = 'localhost'; // How to identify ourselves
  56.   $logArray = array(); // For storing the replies
  57.  
  58.   /* * * * POP Login if required * * */
  59.  
  60.   if(!empty($mailCfg['popServer'])) // Can't really do POP Auth without a server
  61.   {
  62.     $ssl = ($mailCfg['SSL'] != 0) ? (($mailCfg['SSL'] == 1) ? 'ssl://' : 'tls://') : ''; // If SSL or TLS add it
  63.     $popConnect = @fsockopen($ssl.$mailCfg['popServer'], $mailCfg['popPort'], $errno, $errstr, $timeout); // Connect
  64.     if(!$popConnect) // If we fail to connect...
  65.     {
  66.       $logArray['POPconnect'] = $errstr . '(' . $errno . ')'; // Log the given reason...
  67.       logMailError($logArray); // And output to the log file.
  68.       return false;
  69.     }
  70.     else
  71.     {
  72.       $logArray['POPconnect'] = @fgets($popConnect, 515)); // POP servers only return single line replies. Or should.
  73.       if(!mailPackets('AUTH LOGIN', $popConnect, 'SMTPauth')) //Request Auth Login
  74.       {
  75.         return false;
  76.       }
  77.       if(!mailPackets('USER ' . $smtpUser, $popConnect, 'POPuser')) // Send username. POP is plaintext
  78.       {
  79.         return false;
  80.       }    
  81.       if(!mailPackets('PASS ' . $smtpPass, $popConnect, 'POPpass')) // Send password, again in plaintext
  82.       {
  83.         return false;
  84.       }
  85.       if(!mailPackets('QUIT', $popConnect, 'POPquit')) // Say bye to the server
  86.       {
  87.         return false;
  88.       }    
  89.       fclose($popConnect); // Close connection
  90.     }
  91.   }
  92.  
  93.   /* * * * End of POP Login * * * * */
  94.  
  95.   /* * * * Start of SMTP stuff * * * */
  96.  
  97.   $ssl = ($mailCfg['SSL'] != 0) ? (($mailCfg['SSL'] == 1) ? 'ssl://' : 'tls://') : ''; // Set the encryption if needed
  98.   $smtpConnect = @fsockopen($ssl.$mailCfg['Server'], $mailCfg['Port'], $errno, $errstr, $timeout); // Connect
  99.   if(!$smtpConnect) // If we fail to connect...
  100.   {
  101.     $logArray['SMTPconnect'] = $errstr . '(' . $errno . ')'; // Add the reason to the log...
  102.     logMailError($logArray); // Then output the log
  103.     return false;
  104.   }
  105.   else
  106.   {
  107.     $cnectKey = 0; // A counter for when we receive multiple lines in reply
  108.     do
  109.     {
  110.       $smtpResponse = @fgets($smtpConnect, 515); // Get the reply
  111.       $cnectKey++; // Increment the counter
  112.       $logArray['SMTPconnect' . $cnectKey] = $smtpResponse; // Log the response
  113.       $responseCode = substr($smtpResponse, 0, 3); // Grab the response code from start of the response
  114.       // If we get an error terminate the connection and log the results so far
  115.       if($responseCode >= 400)
  116.       {  
  117.         logMailError($logArray, $smtpConnect);
  118.         return false;
  119.       }        
  120.     }  
  121.     while((strlen($smtpResponse) > 3) && (strpos($smtpResponse, ' ') != 3)); // Loop until we get told it's the last line
  122.       $ehlo = mailPackets('EHLO ' . $localhost, $smtpConnect, $logArray, 'SMTPehlo'); // Let's try using EHLO first
  123.       if($ehlo != 250) // Server said it didn't like EHLO so drop back to HELO
  124.       {
  125.         if(!mailPackets('HELO ' . $localhost, $smtpConnect, $logArray, 'SMTPhelo')) // Send HELO. No EHLO means server doesn't support AUTH
  126.         {
  127.           return false;
  128.         }
  129.       }
  130.       if(!empty($mailCfg['User']) && ($ehlo == 250)) // We have a username and server supports EHLO so send login credentials
  131.       {
  132.         if(!mailPackets('AUTH LOGIN', $smtpConnect, $logArray, 'SMTPauth')) // Request Auth Login
  133.         {
  134.           return false;
  135.         }
  136.         if(!mailPackets(base64_encode($mailCfg['User']), $smtpConnect, $logArray, 'SMTPuser')) // Send username
  137.         {
  138.           return false;
  139.         }
  140.         if(!mailPackets(base64_encode($mailCfg['Pass']), $smtpConnect, $logArray, 'SMTPpass')) // Send password
  141.         {
  142.           return false;
  143.         }
  144.       }
  145.       if(!mailPackets('MAIL FROM:<' . $mailFrom . '>', $smtpConnect, $logArray, 'SMTPfrom')) // Email From
  146.       {
  147.         return false;
  148.       }
  149.       if(!mailPackets('RCPT TO:<' . $mailTo . '>', $smtpConnect, $logArray, 'SMTPrcpt')) // Email To
  150.       {
  151.         return false;
  152.       }
  153.       if(!mailPackets('DATA', $smtpConnect, $logArray, 'SMTPmsg')) // We are about to send the message
  154.       {
  155.         return false;
  156.       }
  157.       // First lets make sure both the message and additional headers do not contain anythign that might be seen as end of message marker
  158.       $mailMsg = preg_replace(array("/(?<!\r)\n/", "/\r(?!\n)/", "/\r\n\./"), array("\r\n", "\r\n", "\r\n.."), $mailMsg);
  159.       $mailHeaders = (!empty($mailHeaders)) ? "\r\n" . preg_replace(array("/(?<!\r)\n/", "/\r(?!\n)/", "/\r\n\./"), array("\r\n", "\r\n", "\r\n.."), $mailHeaders) : '';
  160.       // Create the default headers, attach any additonal headers
  161.       $mailHeaders = "To: <".$mailCfg['To'].">\r\nFrom: <".$mailCfg['From'].">\r\nSubject: ".$mailCfg['Subject']."\r\nDate: " . gmdate('D, d M Y H:i:s') . " -0000".$mailHeaders;
  162.       if(!mailPackets($mailHeaders."\r\n\r\n".$mailMsg."\r\n.", $smtpConnect, $logArray, 'SMTPbody')) // The message
  163.       {
  164.         return false;
  165.       }
  166.       mailPackets('QUIT', $smtpConnect, $logArray, 'SMTPquit'); // Say Bye to SMTP server
  167.       fclose($smtpConnect); // Be nice and close the connection
  168.       return true; // Return the fact we sent the message
  169.   }
  170. }
  171.  
  172. // This function sends the actual packets then logs the reponses and parses the reponse code
  173. function mailPackets($sendStr,$mailConnect,&$logArray,$logName = '')
  174. {
  175.   $newLine = "\r\n"; // LEAVE THIS ALONE  
  176.   $keyCount = 0;  // Just an incremental counter for when we get more than a single line response
  177.   @fputs($mailConnect,$sendStr . $newLine); // Send the packet
  178.   do // Start grabbing the responses until we either get a terminal error or told we are at the end
  179.   {
  180.     $mailResponse = @fgets($mailConnect, 515); // Receive the response
  181.     $keyCount++; // Incrememnt the key count
  182.     $logArray[$logName . $keyCount] = $mailResponse; // Put the response in to the log array
  183.     $responseCode = substr($smtpResponse, 0, 3); // Grab the response code from start of the response
  184.     // Check for error codes except on ehlo, auth, and user details as they are not always fatal
  185.     if((($logName != 'SMTPauth') && ($logName != 'SMTPuser') && ($logName != 'SMTPehlo') && ($logName != 'SMTPpass')) && ($responseCode >= 400))
  186.     {  
  187.        logMailError($logArray,$mailConnect);
  188.        return false;
  189.     }
  190.     elseif((substr($responseCode, 0, 1) == 4) || ($responseCode >= 521) && ($logName != 'SMTPehlo'))
  191.     {  
  192.        logMailError($logArray,$mailConnect);
  193.        return false;
  194.     }
  195.   }
  196.   while((strlen($mailResponse) > 3) && (strpos($mailResponse, ' ') != 3)); // Loop until we get the end response
  197.   return $responseCode; // Return the response code
  198. }
  199.  
  200. function logMailError(&$logArray, $mailServer = false)
  201. {
  202.   if($mailServer)
  203.   {
  204.     fclose($mailServer); // Be nice and close the connection
  205.   }
  206.   $fd = @fopen ('smtplog.txt', 'a'); // open the log file
  207.   $mailResults = print_r($logArray, true); // Create a nice printable version of logArray
  208.   @fwrite($fd,$mailResults); // Write the log
  209.   @fclose ($fd); // Close the file
  210. }
  211.  
  212. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement