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   36504 Views

Avatar
jhirm

Community Member, 21 Posts

7 May 2009 at 2:56am

Edited: 21/12/2010 3:51am

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

Community Member, 34 Posts

15 September 2009 at 4:27am

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

Community Member, 283 Posts

19 September 2009 at 4:34am

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

Community Member, 1 Post

25 June 2010 at 7:22am

Edited: 25/06/2010 7:23am

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

Forum Moderator, 435 Posts

25 June 2010 at 7:27pm

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

Community Member, 21 Posts

21 December 2010 at 4:05am

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

Community Member, 14 Posts

22 December 2010 at 9:45pm

Edited: 22/12/2010 9:46pm

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

Community Member, 3 Posts

25 January 2011 at 8:57am

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