Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Using PHPMailer to send emails from external SMTP


Go to End
Reply

9 Posts   35456 Views

Avatar
jhirm

7 May 2009 at 2:56am (Last edited: 21 December 2010 3:51am), Community Member, 21 Posts

There is a thread about this in the archives, but I figured I'd start a new one with instructions for SilverStripe 2.3.1, since the process is a little different. Here is what I did to get this working:

1) Download [url=http://phpmailer.codeworxtech.com/index.php?pg=sf&p=dl]PHPMailer[/url]

2) Expand the .tar/.zip into your SS root, rename phpmailer

3) In your _config.php, add the following:

/* { PHPMAILER */
$path = Director::baseFolder().'/phpmailer/';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once 'class.phpmailer.php';
/* PHPMAILER } */

4) In saphire/email/Mailer.php, add a new function in the Mailer class beneath sendHTML() called sendHTML_phpMailer():

function sendHTML_phpMailer($to, $from, $subject, $htmlContent, $attachedFiles = false, $customheaders = false, $plainContent = false, $inlineImages = false) {
return htmlEmail_phpMailer($to, $from, $subject, $htmlContent, $attachedFiles, $customheaders, $plainContent, $inlineImages);
}

5) In the same file (Mailer.php), but outside the class, add the htmlEmail_phpMailer() function that is called by sendHTML_phpMailer(). It is nearly identical to the htmlEmail function, except that instead of using php's mail() function to send the email it uses a PHPMailer object:

/*
* Use phpMailer to send from external SMTP
*/
function htmlEmail_phpMailer($to, $from, $subject, $htmlContent, $attachedFiles = false, $customheaders = false, $plainContent = false, $inlineImages = false) {

   if ($customheaders && is_array($customheaders) == false) {
      echo "htmlEmail($to, $from, $subject, ...) could not send mail: improper \$customheaders passed:<BR>";
      dieprintr($headers);
   }

   $subjectIsUnicode = (strpos($subject,"&#") !== false);
   $bodyIsUnicode = (strpos($htmlContent,"&#") !== false);
$plainEncoding = "";
   
   // We generate plaintext content by default, but you can pass custom stuff
   $plainEncoding = '';
   if(!$plainContent) {
      $plainContent = Convert::xml2raw($htmlContent);
      if(isset($bodyIsUnicode) && $bodyIsUnicode) $plainEncoding = "base64";
   }

   // If the subject line contains extended characters, we must encode the
   $subject = Convert::xml2raw($subject);
   if(isset($subjectIsUnicode) && $subjectIsUnicode)
      $subject = "=?UTF-8?B?" . base64_encode($subject) . "?=";

   // Make the plain text part
   $headers["Content-Type"] = "text/plain; charset=\"utf-8\"";
   $headers["Content-Transfer-Encoding"] = $plainEncoding ? $plainEncoding : "quoted-printable";

   $plainPart = processHeaders($headers, ($plainEncoding == "base64") ? chunk_split(base64_encode($plainContent),60) : wordwrap($plainContent,120));

   // Make the HTML part
   $headers["Content-Type"] = "text/html; charset=\"utf-8\"";

   
   // Add basic wrapper tags if the body tag hasn't been given
   if(stripos($htmlContent, '<body') === false) {
      $htmlContent =
         "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" .
         "<HTML><HEAD>\n" .
         "<META http-equiv=Content-Type content=\"text/html; charset=utf-8\">\n" .
         "<STYLE type=3Dtext/css></STYLE>\n\n".
         "</HEAD>\n" .
         "<BODY bgColor=#ffffff>\n" .
            $htmlContent .
         "\n</BODY>\n" .
         "</HTML>";
   }

   if($inlineImages) {
      $htmlPart = wrapImagesInline($htmlContent);
   } else {
      $headers["Content-Transfer-Encoding"] = "quoted-printable";
      $htmlPart = processHeaders($headers, wordwrap(QuotedPrintable_encode($htmlContent),120));
   }
   
   list($messageBody, $messageHeaders) = encodeMultipart(array($plainPart,$htmlPart), "multipart/alternative");

   // Messages with attachments are handled differently
   if($attachedFiles && is_array($attachedFiles)) {
      
      // The first part is the message itself
      $fullMessage = processHeaders($messageHeaders, $messageBody);
      $messageParts = array($fullMessage);

      // Include any specified attachments as additional parts
      foreach($attachedFiles as $file) {
         if($file['tmp_name'] && $file['name']) {
            $messageParts[] = encodeFileForEmail($file['tmp_name'], $file['name']);
         } else {
            $messageParts[] = encodeFileForEmail($file);
         }
      }
         
      // We further wrap all of this into another multipart block
      list($fullBody, $headers) = encodeMultipart($messageParts, "multipart/mixed");

   // Messages without attachments do not require such treatment
   } else {
      $headers = $messageHeaders;
      $fullBody = $messageBody;
   }

   // Email headers
   $headers["From"]       = validEmailAddr($from);

   // Messages with the X-SilverStripeMessageID header can be tracked
if(isset($customheaders["X-SilverStripeMessageID"]) && defined('BOUNCE_EMAIL')) {
$bounceAddress = BOUNCE_EMAIL;
} else {
$bounceAddress = $from;
}

// Strip the human name from the bounce address
if(ereg('^([^<>]*)<([^<>]+)> *$', $bounceAddress, $parts)) $bounceAddress = $parts[2];   
   
   // $headers["Sender"]       = $from;
   $headers["X-Mailer"]   = X_MAILER;
   if (!isset($customheaders["X-Priority"])) $headers["X-Priority"]   = 3;
   
   $headers = array_merge((array)$headers, (array)$customheaders);

   // the carbon copy header has to be 'Cc', not 'CC' or 'cc' -- ensure this.
   if (isset($headers['CC'])) { $headers['Cc'] = $headers['CC']; unset($headers['CC']); }
   if (isset($headers['cc'])) { $headers['Cc'] = $headers['cc']; unset($headers['cc']); }
   
   // the carbon copy header has to be 'Bcc', not 'BCC' or 'bcc' -- ensure this.
   if (isset($headers['BCC'])) {$headers['Bcc']=$headers['BCC']; unset($headers['BCC']); }
   if (isset($headers['bcc'])) {$headers['Bcc']=$headers['bcc']; unset($headers['bcc']); }
      
   
   // Send the email
   $headers = processHeaders($headers);
   $to = validEmailAddr($to);

   // Send using phpMailer created in the _config.php file
   
   $phpmailer = new PHPMailer();
   $phpmailer->CharSet = "UTF-8";
   $phpmailer->IsSMTP(); // send via SMTP
   $phpmailer->Host = "smtp.domain.com"; // SMTP servers
   $phpmailer->SMTPAuth = true; // turn on SMTP authentication
   $phpmailer->Username = "user@domain.com"; // SMTP username
   $phpmailer->Password = "password"; // SMTP password
   $phpmailer->From = "from@domain.com";
   $phpmailer->FromName = "From Name";
   $phpmailer->ClearAddresses();
   $phpmailer->AddAddress($to);
   $phpmailer->IsHTML(true); // send as HTML
   $phpmailer->Subject = $subject;
   $phpmailer->Body = $fullBody;
   $phpmailer->AddCustomHeader($headers);
   
   if(!$phpmailer->Send()) {
      return false;
   } else {
      return true;
   }
}

6) In saphire/email/Email.php, find the send() function. Change the last return statement so that it uses the new phpMailer functions if the PHPMailer class is loaded, as follows:

if (class_exists("PHPMailer")) {
return self::mailer()->sendHTML_phpMailer($to, $this->from, $subject, $this->body, $this->attachments, $headers, $this->plaintext_body);
} else {
return self::mailer()->sendHTML($to, $this->from, $subject, $this->body, $this->attachments, $headers, $this->plaintext_body);
}

That's it. It seems to work. I know it seems strange to manually set the From and FromName this way, but for me the function failed without these variables set like this. However, because the From address is set in the headers, your manually set From address is overridden. So when sending from the Newsletter module, for instance, the from address you enter in your newsletter type is what appears in the sent email, NOT the $phpmailer->From address.

Avatar
Jeramie

15 September 2009 at 4:27am Community Member, 34 Posts

This post was instrumental to me keeping Silverstripe in production for us on our shared hosted space. I followed the instructions and had no issues getting it up and running outside of setting the proper SMTP etc. Those were issues on my behalf, Iam a php n00b. Thanks for the great write up.

Avatar
dalesaurus

19 September 2009 at 4:34am Community Member, 283 Posts

If you are reading this and thinking of giving it a go, take a moment to reconsider. There is a better way! Please see my post on fixing your php's mail() function before you consider hacking up core SS files:

http://www.silverstripe.org/general-questions/show/269276

Avatar
MrGingerbear

25 June 2010 at 7:22am (Last edited: 25 June 2010 7:23am), Community Member, 1 Post

You seem to have a typo in your PHP in step 5, near the end.

$phpmailer->Username = "user@domain.com; // SMTP username

should read:

$phpmailer->Username = "user@domain.com"; // SMTP username

(missing ending double quote)
No biggie, but you will have some issues if you copy and paste directly. :)

Avatar
biapar

25 June 2010 at 7:27pm Forum Moderator, 435 Posts

I read that smtp autentication is possible setting up php.ini:

[mail function]
SMTP = YOUR_PROVIDER
smtp_port = 25
username = USERNAME
password = YOUR_PASSWORD

Avatar
jhirm

21 December 2010 at 4:05am Community Member, 21 Posts

It's been a while since I wrote this, just happened to stumble upon it again. Delasaurus is absolutely correct, modifying the core is NEVER a good idea, unless it's absolutely necessary! His post (http://www.silverstripe.org/general-questions/show/269276) presents a method for setting up php's built-in mail() function to send via an SMTP relay, which indeed is a MUCH preferred option... if you've got sufficient server access to make the necessary changes. In my experience, I've run into two scenarios which kept me from doing this: 1) Small site with shared hosting. It's rare that a shared host will allow you to install software or make server changes. 2) Huge site with corporate IT department. Putting in a server change request means waiting for weeks to get it installed on Dev, QA, and production servers, which isn't conducive to smooth development.

But yeah. If you're able to modify the server's mail sending capabilities, don't consider modifying the core!

Avatar
KungK

22 December 2010 at 9:45pm (Last edited: 22 December 2010 9:46pm), Community Member, 14 Posts

I noticed there's a unsupported module that solves this issue (http://silverstripe.org/smtpmailer-module/). I tried it and it worked like a charm, any reason not to use it?

Edit: Only tried with GMail smtp though.

Avatar
Indika

25 January 2011 at 8:57am Community Member, 3 Posts

But some time hotmail can get encoding error .

If you really interest to fix them, you can use my instructions on my blog--- http://indikagamage.com/blog/how-to-use-phpmailer-with-silverstripe-without-any-hotmail-issues/

Go to Top