Click here to Skip to main content
Click here to Skip to main content

Tagged as

How to use Amazon SES to Send Email from PHP

, 11 Aug 2014
Rate this:
Please Sign up or sign in to vote.
Sending mail using Amazon's SES (Simple Email Service)I couldn't find too many good examples for this online and the Amazon AWS PHP SDK had incomplete documentation for a SendEmail function when I was researching this topic.NOTE: My biggest flaw with this was I was using the SMTP username

Sending mail using Amazon's SES (Simple Email Service)

I couldn't find too many good examples for this online and the Amazon AWS PHP SDK had incomplete documentation for a SendEmail function when I was researching this topic.

NOTE: My biggest flaw with this was I was using the SMTP username and password instead of my AWS credentials.  Use your AWS credentials when sending emails using the SDK.

I was getting this error:

SignatureDoesNotMatch, Status Code: 403, AWS Request ID: xxxxx, AWS Error Type: client, AWS Error Message: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. The Canonical String for this request should have been

Setup

It's easy to install the Amazon SDK using PEAR (per Amazon documentation):sudo pear -D auto_discover=1 install pear.amazonwebservices.com/sdk

Once you get the SDK, you also need to make sure you have the Amazon SES setup correctly to let you send emails.  If you account is sandboxed, you will only be able to send emails to the email addresses in the verified senders list.  Verify an email address that you own and use that in your sample code.

When you have the right credentials, sending Email using the SDK is very easy.

Sample Code

require 'AWSSDKforPHP/aws.phar';

use Aws\Ses\SesClient;
$client = SesClient::factory(array(
    'key'    => 'aws_key',
    'secret' => 'aws_secret',
    'region' => 'us-east-1'
));

//Now that you have the client ready, you can build the message
$msg = array();
$msg['Source'] = "authorized_aws_email@somewhere.com";
//ToAddresses must be an array
$msg['Destination']['ToAddresses'][] = "someone@somwhere.com";

$msg['Message']['Subject']['Data'] = "Text only subject";
$msg['Message']['Subject']['Charset'] = "UTF-8";

$msg['Message']['Body']['Text']['Data'] ="Text data of email";
$msg['Message']['Body']['Text']['Charset'] = "UTF-8";
$msg['Message']['Body']['Html']['Data'] ="HTML Data of email<br />";
$msg['Message']['Body']['Html']['Charset'] = "UTF-8";

try{
     $result = $client->sendEmail($msg);

     //save the MessageId which can be used to track the request
     $msg_id = $result->get('MessageId');
     echo("MessageId: $msg_id");

     //view sample output
     print_r($result);
} catch (Exception $e) {
     //An error happened and the email did not get sent
     echo($e->getMessage());
}
//view the original message passed to the SDK 
print_r($msg);

Result

Run the above code using the correct information and your emails should be on their way.  Make sure to set the SenderID, DKIM, and SPF on your domain and Amazon properly to prevent your emails getting marked as spam.

Sending Attachments

Use the example usage code below in your main program to send attachments using SES's sendRawEmail function:

include_once("SESUtils.php");

$subject_str = "Some Subject";
$body_str = "<strong>Some email body</strong>";
$attachment_str = get_file_contents("/htdocs/test/sample.pdf");

//send the email
$result = SESUtils::deliver_mail_with_attachment(
    array('email1@gmail.com', 'email2@lutz-engr.com'),       
    $subject_str, $body_str, 'sender@verifiedbyaws', 
    $attachment_str);

//now handle the result if you wish
print_r($result);

Here is the supporting code to help the code above work.  Save the code below as 'SESUtils.PHP' and include it in your main program.  Happy emailing!

<?php
require 'AWSSDKforPHP/aws.phar';
use Aws\Ses\SesClient;

/**
 * SESUtils is a tool to make it easier to work with Amazon Simple Email Service
 * Features:
 * A client to prepare emails for use with sending attachments or not
 * 
 * There is no warranty - use this code at your own risk.  
 * @author sbossen 
 * http://right-handed-monkey.blogspot.com
 */
class SESUtils {

    const version = "1.0";
    const AWS_KEY = "your_aws_key";
    const AWS_SEC = "your_aws_secret";
    const AWS_REGION = "us-east-1";
    const BOUNCER = "bouncer@checkliststogo.com";  //if used, this also needs to be a verified email
    const LINEBR = "\n";
    const MAX_ATTACHMENT_NAME_LEN = 60;

    /**
     * Usage
     * $result = SESUtils::deliver_mail_with_attachment(array('receipt@r.com', 'receipt2@b.com'), $subject_str, $body_str, 'validatedsender@aws', $attachment_str);
     * use $result->success to check if it was successful
     * use $result->message_id to check later with Amazon for further processing
     * use $result->result_text to look for error text if the task was not successful
     * 
     * @param type $to - individual address or array of email addresses
     * @param type $subject - UTF-8 text for the subject line
     * @param type $body - Text for the email
     * @param type $from - email address of the sender (Note: must be validated with AWS as a sender)
     * @return \ResultHelper
     */
    public static function deliver_mail_with_attachment($to, $subject, $body, $from, &$attachment = "", $attachment_name = "doc.pdf", $attachment_type = "Application/pdf", $is_file = false, $encoding = "base64", $file_arr = null) {
        $result = new ResultHelper();
        //get the client ready
        $client = SesClient::factory(array(
                    'key' => self::AWS_KEY,
                    'secret' => self::AWS_SEC,
                    'region' => self::AWS_REGION
        ));
        //build the message
        if (is_array($to)) {
            $to_str = rtrim(implode(',', $to), ',');
        } else {
            $to_str = $to;
        }
        $msg = "To: $to_str".self::LINEBR;
        $msg .="From: $from".self::LINEBR;
        //in case you have funny characters in the subject
        $subject = mb_encode_mimeheader($subject, 'UTF-8');
        $msg .="Subject: $subject".self::LINEBR;
        $msg .="MIME-Version: 1.0".self::LINEBR;
        $msg .="Content-Type: multipart/alternative;".self::LINEBR;
        $boundary = uniqid("_Part_".time(), true); //random unique string
        $msg .=" boundary=\"$boundary\"".self::LINEBR;
        $msg .=self::LINEBR;
        //now the actual message
        $msg .="--$boundary".self::LINEBR;
        //first, the plain text
        $msg .="Content-Type: text/plain; charset=utf-8".self::LINEBR;
        $msg .="Content-Transfer-Encoding: 7bit".self::LINEBR;
        $msg .=self::LINEBR;
        $msg .=strip_tags($body);
        $msg .=self::LINEBR;
        //now, the html text
        $msg .="--$boundary".self::LINEBR;
        $msg .="Content-Type: text/html; charset=utf-8".self::LINEBR;
        $msg .="Content-Transfer-Encoding: 7bit".self::LINEBR;
        $msg .=self::LINEBR;
        $msg .=$body;
        $msg .=self::LINEBR;
        //add attachments
        if (!empty($attachment)) {
            $msg .="--$boundary".self::LINEBR;
            $msg .="Content-Transfer-Encoding: base64".self::LINEBR;
            $clean_filename = mb_substr($attachment_name, 0, self::MAX_ATTACHMENT_NAME_LEN);
            $msg .="Content-Type: $attachment_type; name=$clean_filename;".self::LINEBR;
            $msg .="Content-Disposition: attachment; filename=$clean_filename;".self::LINEBR;
            $msg .=self::LINEBR;
            $msg .=base64_encode($attachment);
            //only put this mark on the last entry
            if (!empty($file_arr))
                $msg .="==".self::LINEBR;
            $msg .="--$boundary";
        }
        if (!empty($file_arr) && is_array($file_arr)) {
            foreach ($file_arr as $file) {
                $msg .="Content-Transfer-Encoding: base64".self::LINEBR;
                $clean_filename = mb_substr($attachment_name, 0, self::MAX_ATTACHMENT_NAME_LEN);
                $msg .="Content-Type: application/octet-stream; name=$clean_filename;".self::LINEBR;
                $msg .="Content-Disposition: attachment; filename=$clean_filename;".self::LINEBR;
                $msg .=self::LINEBR;
                $msg .=base64_encode($attachment);
                //only put this mark on the last entry
                if (!empty($file_arr))
                    $msg .="==".self::LINEBR;
                $msg .="--$boundary";
            }
        }
        //close email
        $msg .="--".self::LINEBR;

        //now send the email out
        try {
            $ses_result = $client->sendRawEmail(array(
                'RawMessage' => array('Data' => base64_encode($msg))), array('Source' => $from, 'Destinations' => $to_str));
            if ($ses_result) {
                $result->message_id = $ses_result->get('MessageId');
            } else {
                $result->success = false;
                $result->result_text = "Amazon SES did not return a MessageId";
            }
        } catch (Exception $e) {
            $result->success = false;
            $result->result_text = $e->getMessage()." - To: $to_str, Sender: $from, Subject: $subject";
        }
        return $result;
    }

}

class ResultHelper {

    public $success = true;
    public $result_text = "";
    public $message_id = "";

}

?>

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Right Handed Monkey
Software Developer WorxForUs
United States United States
I am a programmer who posts rambling on about java, Android, PHP, or whatever I am motivated to type on my charcoal colored Kinesis Freestyle2 keyboard. Please send +1's, shared links, warm thoughts of encouragement, or emasculating flames of internet fury to my blog. Why not? In fact, say anything... but please don't say 'thank'. I don't know, but something about it makes my skin crawl like an electric eel is asking to give me a kiss. No, thanks. (See there's an 's' in there. Was that really so hard?
 
right-handed-monkey.blogspot.com

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140814.1 | Last Updated 11 Aug 2014
Article Copyright 2014 by Right Handed Monkey
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid