How to integrate existing website into Amazon Simple Email Service

I was preparing to integrate a client’s business to send emails through AWeber last week when I realized that their api does not support sending transactional emails to one or more people on an as needed basis. I confirmed with AWeber’s tech support that their API is read only, it does not allow the sending of emails at all (they have a web interface for sending emails). I asked them what they would use in my situation and they said that the other big newsletter names I had heard of before (MailChimp, Constant Contact, etc.) also only supported newsletter type messages.

What my client needed was a more robust email system because every week they had situations where people were not getting emails (sent from their own server using the php mail command). I recommended AWeber because I knew their deliverability was very high and they would keep up with any changes in email standards. I figured since they had an API that I could specify email addresses and email contents to send using it but after looking for that functionality I came up empty handed.

The Aweber tech I spoke to mentioned the possibility of using SalesForce for this type of account message emailing, but I knew that would be overkill and overpriced for just sending emails. After a quick search I was happy to find out that Amazon provides an email service called “Simple Email Service” (SES) that allows for a certain number of emails for free if you already have an Amazon Web Services (AWS) account. Since my client had signed up for the Amazon S3 service (a storage solution) a few months prior in order to save backups of their weblogs they already had an AWS account.

After reading a few documents about different ways to use the Amazon Simple Email Service I decided that it would be simplest for me to integrate using an authenticated SMTP connection. Since there were only half a dozen files that use the mail command (found by using ‘grep “mail(” *php’ and ‘grep “mail(” *\*php’ and so on in the webroot), I only needed to update those files after getting the Pear modules installed.

I started using just the pear Mail module but then when I tried to send html emails they showed up as source code and not rendered, so I added the Mail_Mime files too. The way I did it was to first try installing it using “pear install Mail” (and pear install Mail_Mime) as root, but after a bunch of trouble with include paths I ended up downloading the tarballs to the server using wget, then extracting them into a subdirectory under the webroot (which I later protected using htaccess to deny all connections directly to the files). Next I tried including the main Mail.php file with error printing on and updated several of the pear files to refer to the right relative path for inclusion. I did the same thing with the Mail/mime.php file, adjusting paths as needed until the errors were all gone.

I had a common included file at the top of each of my php files so inside that common file I included the pear files and defined a few constants for connecting to the smtp server at amazon (pear is the name of the folder in my webroot where I put the pear files):

#Show errors - after I got the paths right I commented this section
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', true);

#Pear email modules
require_once "pear/Mail.php";
require_once "pear/Mail/mime.php";
define("MAILHOST","ssl://email-smtp.us-east-1.amazonaws.com");
define("MAILPORT","465");
define("MAILUSER","myAmazonSMTPUserNameHere");
define("MAILPWD","myAmazonSMTPPasswordHere");

Then in each file where I wanted to send email, I used this framework to do it:

# Constructing the email
$sender = "Sender Name <senderName@domain.com>";                              
$recipient = "recipientName@domain.com;                           // The Recipients name and email address
$text = "this will be sent as text;                                  // Text version of the email
$html = "<h1>This will be rendered as html</h1>";  // HTML version of the email
$crlf = "\n";
 		        
$headers = array(
        'From'          => $sender,
        'To'          => $recipient,
        'Subject'       => $subject
        );

# Creating the Mime message
$mime = new Mail_mime($crlf);

# Setting the body of the email
if (!empty($text)) {
        $mime->setTXTBody($text);
} else if (!empty($html)){
        $mime->setHTMLBody($html);
}

#Get the header and body into the right format
$body = $mime->get();
$headers = $mime->headers($headers);
$headers['From'] = $sender;  //I heard some people had trouble with this header getting messed up

#Setup the connection parameters to connect to Amazon SES
$smtp_params["host"]     = MAILHOST;
$smtp_params["port"]     = MAILPORT;
$smtp_params["auth"]     = true;
$smtp_params["username"] = MAILUSER;
$smtp_params["password"] = MAILPWD;
 
# Sending the email using smtp
$mail =&amp;amp; Mail::factory("smtp", $smtp_params);
$result = $mail->send($recipient, $headers, $body);		

#Below is only used for debugging until you get it working
if (PEAR::isError($result)) {
   echo("<p>" . $result->getMessage() . "</p>");
} else {
   echo("<p>Message successfully sent!</p>");
}

Caveat

Amazon doesn’t put your emails into a queue if you send them too fast, so in order to stay under their sending limits when sending batches of messages you can use the php usleep command to delay execution. I found that this delay didn’t actually work until I added “set_time_limit(0);” to the top of the file sending the batch of emails, however. Test everything, different server environments will respond differently (just like Browsers are like Churches). I used an echo date(‘h:i:s’) command between delays to see whether the delay worked or not.