Simple Email Service

Amazon Simple Email Service provides a simple way to send e-mails without having to maintain your own mail server.  This PHP class is a REST-based interface to that service.

A bit of example code will be a good demonstration of how simple this class is to use. Please read through these examples, and then feel free leave a comment if you have any questions or suggestions.

Update: Daniel Zahariev has forked the project and implemented the missing SendRawEmail functionality as well as Sig V4 support. You can download it at his github project page.

First, you’ll need to create a SimpleEmailService class object:

require_once('ses.php');
$ses = new SimpleEmailService('Access Key Here', 'Secret Key Here');

If this is your first time using Simple Email Service, you will need to request verification of at least one e-mail address, so you can send messages:

print_r($ses->verifyEmailAddress('user@example.com'));
-------
Array
(
  [RequestId] => 1b086469-291d-11e0-85af-df1284f62f28
)

Every request you make to SimpleEmailService will return a request id. This id may be useful if you need to contact AWS about any problems.  For brevity, I will omit the request id if it is the only value returned from a service call.

After you’ve requested verification, you’ll get an e-mail at that address with a link. Click the link to get your address approved.  Once you’ve done that, you can use it as the ‘From’ address in the e-mails you send through SES.  If you don’t have production access yet, you’ll also need to request verification for all addresses you want to send mail to.

If you want to see what addresses have been verified on your account, it’s easy:

print_r($ses->listVerifiedEmailAddresses());
-------
Array
(
  [RequestId] => 77128e89-291d-11e0-986f-43f07db0572a
  [Addresses] => Array
    (
      [0] => user@example.com
      [1] => recipient@example.com
    )
)

Removing an address from the verified address list is just as easy:

$ses->deleteVerifiedEmailAddress('user@example.com');

This call will return a request id if you need it.

The only thing left to do is send an e-mail, so let’s try it. First, you’ll need a SimpleEmailServiceMessage object.  Then, you’ll want to set various properties on the message.  For example:

$m = new SimpleEmailServiceMessage();
$m->addTo('recipient@example.com');
$m->setFrom('user@example.com');
$m->setSubject('Hello, world!');
$m->setMessageFromString('This is the message body.');

print_r($ses->sendEmail($m));
-------
Array
(
  [MessageId] => 0000012dc5e4b4c0-b2c566ad-dcd0-4d23-bea5-f40da774033c-000000
  [RequestId] => 4953a96e-29d4-11e0-8907-21df9ed6ffe3
)

And that’s all there is to it!

There are a few more things you can do with this class. You can make two informational queries, try these out:

print_r($ses->getSendQuota());
print_r($ses->getSendStatistics());

For brevity I will not show the output of those two API calls. This information will help you keep track of the health of your account. See the Simple Email Service documentation on GetSendQuota and GetSendStatistics for more information on these calls.

You can set multiple to/cc/bcc addresses, either individually or all at once:

$m->addTo('jim@example.com');
$m->addTo(array('dwight@example.com', 'angela@example.com'));
$m->addCC('holly@example.com');
$m->addCC(array('kelly@example.com', 'ryan@example.com'));
$m->addBCC('michael@example.com');
$m->addBCC(array('kevin@example.com', 'oscar@example.com'));

These calls are cumulative, so in the above example, three addresses end up in each of the To, CC, and BCC fields.

You can also set one or more Reply-To addresses:

$m->addReplyTo('andy@example.com');
$m->addReplyTo(array('stanley@example.com', 'erin@example.com'));

You can set a return path address:

$m->setReturnPath('noreply@example.com');

You can use the contents of a file as the message text instead of a string:

$m->setMessageFromFile('/path/to/some/file.txt');
// or from a URL, if allow_url_fopen is enabled:
$m->setMessageFromURL('http://example.com/somefile.txt');

If you have both a text version and an HTML version of your message, you can set both:

$m->setMessageFromString($text, $html);

Or from a pair of files instead:

$m->setMessageFromFile($textfilepath, $htmlfilepath);
// or from a URL, if allow_url_fopen is enabled:
$m->setMessageFromURL($texturl, $htmlurl);

Remember that setMessageFromString, setMessageFromFile, and setMessageFromURL are mutually exclusive. If you call more than one, then whichever call you make last will be the message used.

Finally, if you need to specify the character set used in the subject or message:

$m->setSubjectCharset('ISO-8859-1');
$m->setMessageCharset('ISO-8859-1');

The default is UTF-8 if you do not specify a charset, which is usually the right setting. You can read more information in the SES API documentation.


My version of this library does not support the SendRawEmail call, which means you cannot send emails with attachments or custom headers; however, Daniel Zahariev has forked the project and implemented this functionality. You can download it at his github project page.


Disclaimer: Although I worked for Amazon in the past, this class was neither produced, endorsed nor supported by Amazon.  I wrote this class as a personal project, just for fun.

319 thoughts on “Simple Email Service

  1. Keegan Street

    That’s really helpful. Thanks for publishing it. I’m going to jump into EC2 (and probably SES now) for a new web app I’m building.

    Reply
  2. atragan

    very good work on the wrapper!

    i was wondering if its possible to send an email and use as an email body a dynamically created webpage (thankyou.php?return=true), so instead of writing the body by hand you just include an HTML page?

    Reply
  3. Dan

    That’s a good suggestion. I’ve added another method to the message object, setMessageFromURL(), that will do this:

    $m->setMessageFromURL('http://example.com/thankyou.php?return=true');

    Your php.ini must have allow_url_fopen enabled for this to work.

    If you’re trying to use the output of a php file that’s on the same server you’re sending the message from, I would recommend you write a function to generate the text output and use setMessageFromString() instead.

    Hop over to the Sourceforge project page to download the updated library.

    Reply
  4. Fadzly

    Hi Dan,

    Firstly, great job on this! Do we need to install the Amazon AWS PHP SDK, prior to using your PHP Class

    Reply
  5. Dan

    Nope! This class is self-contained. You only need to make sure your server’s PHP has the openssl and curl modules installed and enabled, and if you want to use setMessageFromURL, you need to make sure allow_url_fopen is enabled in php.ini.

    Reply
  6. Scott

    Dan, I’m wondering if it’s possible to add the sender’s name to the email. That way it arrives in the inbox as being from “John Doe” instead of just an email address.

    Reply
  7. Dan

    Scott,

    You can indeed, it’s easy. Suppose you have a message object $m:

    $m->addTo(‘Joe Consumer <joe@example.com>’);
    $m->setFrom(‘Customer Service <service@example.com>’);

    Enjoy 🙂

    Reply
  8. Laxmikant

    I tried for array for $m->addTo();

    $to_emailid = array(“emailid1@yahoo.com”,”emailid2@yahoo.com”);

    as

    $m->addTo($to_emailid); but email was not sent for array list.

    can u help me plz how it will resolve?

    Reply
  9. Dan

    Does it work if you set up the message like this?

    $m->addTo('emailid1@yahoo.com');
    $m->addTo('emailid2@yahoo.com');

    If so, I’ll need to look and see if there’s a bug in my code.

    If your SES account has not been approved for production use by AWS, then all addresses in the To list must be on your verified email address list, so that could also be the problem.

    Reply
  10. Laxmikant

    Hi, Dan

    $m->addTo(’emailid1@yahoo.com’);
    $m->addTo(’emailid2@yahoo.com’);

    above code works fine,Emails has been sent successfully.

    but in array variable it fails as mentioned in last code.

    so, Can u help me plz ASAP?

    for how array will use for $m->addTo();

    Reply
  11. Dan

    Ah, I see what’s wrong. There’s a bug in my code :S Right now passing an array to addTo() only works if you’ve already added a single address first.

    I’ll release a fix tomorrow. I apologize for the inconvenience.

    Reply
  12. Laxmikant

    Thanks, Dan
    I found the another issue also, I have message which contains html part
    and I tried these code one by one
    $m->setMessageFromString($text, $html);
    $m->setMessageFromString(“text”, “html”);

    but when email sent, email msg display like this

    body contents….. etc.

    and due to this email goes in spam.

    can u plz tell me how I can use html in message?

    Please help me.

    Reply
  13. Laxmikant

    Hi,Dan

    oh, in above replied i typed html table tags so, its does not show,

    i want to say message contains if html(table tags,hyper links,image tag) so, as its is code display in email message when sent and email goes in spam due to this.

    Reply
  14. David

    Thanks a lot for the code. It is really useful. I was looking at the AWS site trying to work out my first steps and then stumbled across your code which makes life so much easier.

    I don’t currently have the curl module installed (at least I get an error message:

    Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set in …../ses.php on line 493

    The email seems to send without any problem within the sandboxed environment. I have asked my hosting providers to give me access to the curl module but what is the reason for it and am I able to disable the code in the file (as it seems to work anyway)

    Thanks again for your code!

    Reply
  15. Dan

    Laxmikant: Some spam filters work based on content, so if you’re sending certain types or structure of content (even if it’s legitimate mail), the message might get marked as spam when it is received, depending on the destination.

    Unfortunately there’s nothing I can do except suggest that you fill in the content of your email so it doesn’t look like spam 🙂

    David: It looks like you have curl installed, but PHP is not configured to allow curl to use a configuration setting necessary for using my class in production. If you own the server you’re running this on, you’ll want to open up php.ini and make sure safe_mode is disabled and open_basedir is not set.

    If you’re on a shared webhost you might be out of luck, though there may be a way to set specific php.ini options in an .htaccess file. You’ll have to contact your hosting provider for more information.

    As for why you get this error in the sandboxed environment but not otherwise, it just happens that (apparently) the sandbox endpoint doesn’t do any redirects, while the production endpoint does.

    Hope that helps 🙂

    Reply
  16. Dan

    I’ve updated the library to fix the SimpleEmailServiceMessage-related bug Laxmikant reported.

    You can download the latest version from the SourceForge project page, or you can use this direct link.

    Reply
  17. David

    I have been struggling to find a work around to the open_basedir is set issue. My hosting provider tells me that safe mode is not on. For now I have commented out that one line. Are there any side effects of not having the
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    line in the code?

    If I do comment it out the email gets sent anyway.

    When I said that it worked in the sandboxed environment, I have yet to try it in the production environment.

    Thanks again

    Reply
  18. Dan

    The only side effect would be that if the web service issues an HTTP redirect (for example, if they decided to change their endpoint, and left the old one up for a while redirecting to the new endpoint) then your client would stop working.

    In any case, if service calls work without CURLOPT_FOLLOWLOCATION set, there’s no harm in disabling it.

    Reply
  19. Laxmikant

    Thanks, Dan

    I want to say my isssue is not related with spam, this issue occurs due to the, when email sent,email message contains ( html tags) which is display as it is in email body, sothat email goes in spam.
    If email contents shows properly then it will automatically resolve.

    but How i can display html data in meassge body,

    i tried as

    $m->setMessageFromString($text, $html);
    $m->setMessageFromString(“text”, “html”);
    $m->setMessageFromString($message);
    (variable $message contains htmls tags like image,hyperlink,table)

    but not work.

    Please help me for this issue.

    Reply
  20. Dan

    Laxmikant,

    If you want to send an HTML message without a text version of that message, you’ll want to do this:

    $m->setMessageFromString(null, $message);

    Whether the message ends up in the recipient’s spam folder really is beyond my control. It depends on the content of your message and possibly whether the DNS zone for your domain is set up with SPF to prevent unauthorized servers from sending mail from your domain.

    – Dan

    Reply
  21. Sean

    Dan, this is awesome! But one question… how do I view the Bounces, Complaints and Rejects? I know how to get the overall stats using print_r($con->getSendStatistics()); but I want to be able to see which emails where Bounced, Complained or Rejected.

    Reply
  22. Dan

    Sean,

    The API does not expose that information. However, if you get a complaint or a bounce, it will be sent back to you at the ReturnPath e-mail address on the message (or, if not specified, the From address). The ReturnPath e-mail address must be one of your account’s verified addresses for this to work.

    I only did a brief search of the SES community forums, but I didn’t see any information about rejections specifically.

    Laxmikant,

    You might want to check out this forum post about messages getting marked as spam (read the reply by JustinC@AWS): https://forums.aws.amazon.com/thread.jspa?threadID=61187&tstart=50

    Hope that helps, guys 🙂

    Reply
  23. dom

    thanks for all the great work. I have an issue close to the one described by David where I get the Warning: “Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set in…”.
    According to my php_test safe_mode is off and open_basedir has no value. However, the code is still spitting out this error. Any thoughts?

    Reply
  24. Dan

    Try looking at the output of php_info();. I think that’s the most reliable way to tell what settings PHP is using.

    Other than that I wouldn’t know where to look… Google, I guess. Sorry!

    Reply
  25. JD

    Great wrapper, thanks for publishing. That was going to be all but have a suggestion now! Would it be possible to auth based on a cert rather than passing keys to the wrapper as params?

    Reply
  26. Dan

    JD,

    As far as I am aware, SES only supports Query requests (REST-based requests), which only support key-based authentication. However, if SES later supports SOAP-based requests, I do not intend to support it. (One of the goals of my PHP AWS libraries is to avoid the overhead involved in SOAP requests.) Sorry!

    Reply
  27. Juan Alvarez

    Hi Dan,
    How can I send e-mails with the Sender name included in the “From” field? So far e-mails are arriving with the e-mail address, but I want to display the sender name.

    Thanks in advance

    Reply
    1. Dan

      Suppose you have a message object $m:

      $m->setFrom(‘Customer Service <service@example.com>’);

      That’s all you have to do 🙂 This same pattern works for To, CC, and BCC.

      Reply
      1. Alan R

        $m->setFrom(‘Customer Service ’);

        Well if I use this, the request fails – it doesn’t have from email? I’m little stuck and can’t see out here.

        As I understod you (it shure is wrong) it should be like this:

        $m->setFrom(‘john@example.com’);
        $m->setFrom(‘Customer Service ’);

        One overrides the other. Array doesn’t work either..?
        Tnx & great job, tnx for sharing.

        Reply
        1. Dan

          Oops, I didn’t realize the angle brackets are hiding the important bit…

          $m->setFrom('Customer Service <john@example.com>');

          … silly HTML.

          Reply
          1. Alan R

            I dove deeper into the API, email specs etc., and managed to work out the raw email where I control everything 🙂

            It’s bad though SES doesn’t support attachments. Do you know anything about that maybe?

            Tnx for fast reply,
            A

            Reply
  28. Vijayanand

    Hi,

    Thanks for sharing this link on AWS forums. I started using your code, but I am facing this problem. Can you please help me out.

    Warning: SimpleEmailService::listVerifiedEmailAddresses(): 60 SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in C:\xampp\htdocs\emails\ses.php on line 357

    Thanks,
    -Vijayanand Gurudev

    Reply
      1. Brad

        Vijayanand – to elaborate, going by your file path, it looks like you are possibly using WAMP as I was, and as far as I can tell, SSL+CURL via WAMP just doesn’t want to work correctly. So – you can use the above command to turn off the SSL verification piece of the class so that you can execute these commands locally. Obviously you will probably want to leave that out once the code makes it to production on your server, but this should help for development / testing for sure.

        Reply
  29. Sean

    Hi Dan!

    Thanks for letting me know. I did some more research on this and found you are right. The API does not support that at the moment. But I came up with a way to handle this from reading someone else’s blog on bounce handling.

    What can be done is to setup a catch all email for a subdomain of your site and then put an id for other identified data as the email address so if a bounce is made you just look at the email address it was bounced back to.

    Example: 12×627381@bouncer.com

    Where the 12 might be an id for an email address on your email list and 627381 might be the id for the email that was sent on that list.

    Reply
    1. Sidhu

      Hi Sean,

      We will have to verify all the Returh Path address that we use. So this method might not work if we are using Amazons SES.

      Let me know otherwise, because I am also looking for an easy way to capture Bounces and complaints.

      Reply
  30. Ted Mathias

    What do you know about including attachments using SES?

    Any word on when?

    Can you point to any documentation about attachments?

    Thanks.

    Reply
    1. Dan

      Attachments can be sent using the SendRawMessage API, which unfortunately this class does not yet support. It is at the top of my to-do list, however, so I will add it as soon as I can.

      Reply
      1. Todd

        According this this post https://forums.aws.amazon.com/thread.jspa?threadID=59658 it says that eventhough attachments are in the api they are not supported by amazon. Since you work there I would think you would have some insight on this. If it is not supported do you know how we can send attachments without the use of ses or third party integration?

        thanks
        (great script btw)

        Reply
        1. Todd

          [anal correction]
          “attachments are in the api” should read “attachments are a part of the api”

          Reply
        2. Dan

          Ah, I wasn’t actually aware that they reject multipart messages containing attachments. That being the case, it looks like there is no way to send attachments using SES.

          One alternative would be to upload your attachment to S3 and include a link to it in your email message.

          Reply
  31. Ray

    O, is there a sample code of .NET?
    I’m trying get the request from .NET, but the server always reply me 400-Bad Request.
    I don’t believe it’s because ofmy wrong code.

    Reply
  32. Danny

    Thank you for the library, very useful and simple.
    Just a quick question, do you have any time frame for the SendRawMessage API support?
    I only need the SES functionality, thinking of using your library instead of the amazon SDK.

    Reply
    1. Dan

      I apologize for the delay. I have some external constraints that are preventing me from adding SendRawMessage at the moment, but as soon as the situation is resolved I intend to add support for it. I am hoping this will happen within two weeks, but unfortunately I cannot make a firm promise.

      Reply
  33. rrmo

    Hi Dan,

    The class was very useful . When I use the function getSendStatistics()
    I see bounce has been detected, According to API the bounce emails come to mail that has been set to return path . But i never get the bounce mail to my inbox.
    Is there anything I am missing ?
    I even posted on the forums .. but I got no proper reply.
    https://forums.aws.amazon.com/thread.jspa?threadID=63490&tstart=25
    Could you help me out here.

    Reply
    1. Dan

      You did get proper replies, but you didn’t answer any of their questions 😛 I’m just going to ask the same questions:

      – Does the sendMessage() call return an error?
      – Does the address you’re using for the return path appear in the list of verified e-mail addresses when you call listVerifiedEmailAddresses()?
      – If you add a real recipient, in addition to the fake address, does the real recipient receive the e-mail?

      As the last commenter in your AWS forum thread stated, it may also possible that the bounce notification e-mail sent by the receiving domain’s mail server could be malformed, in which case SES might record that the mail bounced but not forward the malformed bounce notification to the return-path address. To verify this you’ll need to try sending to a non-existent address on a domain whose mail server sends valid bounce notifications; you could try a fake gmail address, for example.

      Reply
      1. rrmo

        Hi Dan,

        Sorry for the late reply.

        – Does the sendMessage() call return an error?
        No it does not return error. It returns request Id and Message ID . I am using $ses->sendEmail($m) btw.

        – Does the address you’re using for the return path appear in the list of verified e-mail addresses when you call listVerifiedEmailAddresses()?

        Yes the from email address and return path email address are the same and it appears in the listOfVerifiedEmailAddress

        – If you add a real recipient, in addition to the fake address, does the real recipient receive the e-mail?

        The real recipient receives the email .But the some non existen email address for eg sdfdsfds@gmail.com which i tried threw a bounce ( shown in getSendStatistics() ) .But I did not receive any bounce email from Amazon SES.

        Let me know if I am missing something else.

        Reply
        1. Dan

          Sorry, I’m not sure why you’re not receiving a bounce e-mail. You could try contacting SES about it; giving them the message ID returned to you by sendEmail() for one of these cases will help them figure it out.

          Reply
        2. Sidhu

          rrmo,

          Just a suggestion: Recheck your spam folder to see if you received any mails from MAILER-DAEMON@email-bounces.amazonses.com

          And also now we can add only one email address to returnPath.

          Dan,
          Is this(ability to add just one returnPath address) a restriction form the Amazons SES or Did you write the code to accept just one returnPath address. I looked into the Amazons API and I could not find any clear answer to this.

          Thank you for the brilliant and simple code.

          Reply
  34. Doug

    To start – thanks for developing!

    Secondly, I’m sorry but I’m having difficulty downloading it from SourceForge. I think it might be interpreting the the file extension on ses.php ?
    Would it be possible to get a ses.zip version or just a print out of the code?

    Thanks!

    Reply
    1. Dan

      When you go to download the file, you should get sent to a page that says “waiting for download”, and it will have a direct link to the file. Right-click on that link and choose “Save As…” and you’ll be able to download the file properly.

      Reply
      1. Doug

        I had tried a few different ‘file – save as’ combinations, but not on that link.
        Works great. Thanks very much for your prompt response.

        Reply
  35. George Nikolov

    I just wanted to share my appreciation for this great library! The application is easy to implement and examples are straightforward. Great job!

    Reply
  36. Rajiv

    Dan,

    I appreciate your work – your library and documentation helps navigate the AWS-SES API with ease. I was up and running in no time.

    When creating the SimpleEmailService class object is there a way to hide the access keys in the code?

    Thanks
    Rajiv

    Reply
  37. Rajiv

    Dan,

    This is further to the comment I had left earlier today. I got around visible access key issue by storing the keys in (and calling them back from) a configuration Db.

    Thanks again
    Rajiv

    Reply
    1. Reuben

      Dan: awesome script – thanks so much.

      Rajiv: a simple way to hide the AWS keys is to place them in a non-web-accessible directory and then include that config file in your script. You can use the same method to hide your DB authentication info.

      Server/private/ contains config files
      Server/public/ contains public facing files (root of web server)

      You just need to make sure that the includes/path in PHP allows access to the private folder.

      Reply
  38. Scott

    Dan,

    Great work but I’m having a problem. I can send a little over 100 html emails and then the script becomes unresponsive. Have to restart Apache before running it again. Something in the logs about child process still hasn’t finished. Don’t know if that’s related or not. Tried building the emails but not sending them and received no lockups so assume it’s curl related. Any ideas? Thanks.

    Reply
    1. Dan

      Apache usually has a timeout set for how long a PHP script can run. You might want to check that and make sure it’s sufficiently long; you might also want to see if you can break the work up into smaller chunks, maybe do 100 at a time.

      Reply
      1. Scott

        Wasn’t timeout problem. Also checked unsetting “$rest” and rewriting to allow CURLOPT_RETURNTRANSFER to be true, and a hundred other things without success. Guessing it’s a cumalitive resource problem. Did get around it by cronning 100 at a time. Thanks.

        Reply
  39. mohan

    Hi Dan,

    Awesome script.Any update when the raw support will be ready?

    Regards,
    Mohan

    Reply
  40. Alex Smith

    Hey Dan,

    First, awesome class. Very easy to use and it’s great to see you continue to update the class as you add more to it.

    Quick question for you though. Is there an ability (can’t find one in your class, but maybe Amazon has it) to change the priority of an email? We’re using this in part as an internal notification engine to notify us and our server administrators if a bug is detected or a server becomes unresponsive. We’re looking for a way to set the priority as ‘high’.

    Thanks,
    Alex Smith

    Reply
    1. Dan

      Hi Alex,

      I believe that would require the raw e-mail API (since you need to set the X-Priority header). Unfortunately my library does not currently support that API call, but I am hoping to have a solution for you in the next few weeks.

      Thanks,
      Dan

      Reply
  41. Guillermo

    If someone’s getting the following error:
    “Fatal error: Uncaught CurlException: 60: SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL ”

    The way to fix it is to do the following:
    curl_setopt($curl, CURLOPT_CAINFO,”PATH/apache/conf/ssl.crt/ca-bundle.crt”);

    If you don’t have a ca-bundle.crt you can download it from the net

    Reply
  42. Bryan

    FYI.. for those who want to send a message from URL, if not sending a text version, make sure the first parameter is “null’, such as (null , ‘http://www.yahoo.com/file.html’). I got hung up on that one.

    I got this working perfectly. The only thing I read here that some people had issue with sending many emails at once, it hanging, etc. I have about 2500 subscribers to my newsletter.

    Question, couldn’t I just do a WHILE loop and send them one at a time that way, taking the addresses from my MySQL db? If I did the WHILE loop, would that slow the sending of the email, as to not “hang?” Is this slower/different than adding 2500 emails into the TO write in the code?

    Or, is there a way to pause for a second, or half a second, after each iteration of the WHILE loop?

    I thought amazon does the emailing, so don’t they just queue the messages as they get them, so why does it matter if we send many at once? Don’t they have a system in place to accept them all, then send them on their time? I would think we could just dump them 2500, and let them handle it. Or maybe it doesn’t work that way?

    @Dan, if you have any good ideas, I’d be willing to listen. I’ve written a separate system PHP which handles subscribes/unsubscribes, as well as link tracking. I write that data to a MySQL db, and I use a Mac client (whoosh) to send the mail. I’d love to drop the Mac client, and use your PHP class, but the only obstacle is sending 2500 out at once, and making sure they all get properly sent.

    Bryan

    Reply
    1. Dan

      Even though it is faster, putting a big list of addresses in the To: line is generally undesirable because it exposes your entire address list to every recipient of the e-mail.

      If you make one API call per message, there should be no need to pause between each message, however keep in mind that SES rate-limits new accounts, so you’ll want to make sure you don’t exceed your limit.

      I would recommend sending the messages individually, in a loop.

      Reply
      1. Bryan

        Hi Dan- Thanks for your super-speedy reply! We are production ready, have 10,000 daily limit, like 5 per second, etc. So we are good to go with Amazon.

        So you think if I write a WHILE loop, and send a message each iteration, there shouldn’t be any problems? Of course, I guess I can always check the stats later on, and see just what actually went through.

        I would never put all in the TO:, I was just including that as an example. I actually had all the code good to go, then I read that people had issues with large lists, then I just trashed it. Glad I came back. I’ll write that again, and when my client is ready to send out, I think I’ll use your PHP class to send it. I’ll then write back and let you guys know what came of it. I REALLY like your work. You make my job easier!

        Anything I learn, I’ll certainly post back here to help out the next guy after me.

        Thanks!

        Bryan

        // Listening to ‘She Said She Said’ off Revolver by The Beatles

        Reply
  43. James Simpson

    I’m having issues with HTML e-mails sending very slowly. If I send an e-mail with just text, the script executes in around half a second. However, if I send an e-mail that contains HTML (still not a lot more than the text-only e-mail), the script takes 2.5-3 seconds to execute.

    Is this just the nature of the class in PHP? If so, would Amazon’s official SDK perform any better?

    Reply
    1. James Simpson

      Maybe I spoke too soon, because even now just text e-mails are taking 2.5-3s to send. This is one e-mail with one recipient. At that rate it will take a script execution time of over 8 hours just to send out to a list of 10,000 e-mails if I run a loop. This obviously is impossible. Are other people having such slow response times?

      Also, my server is in Dallas, so it isn’t just due to low latency by distance.

      Reply
      1. Dan

        There are a lot of variables that could affect this, including what exactly is running on your server (other programs, other users, etc), as well as issues on SES’s side. In high-latency scenarios like this, if it’s persistent, my advice is to check the AWS service health dashboard and see if there are any ongoing events that could affect Simple Email Service. If not, see if there are any other processes on your server slowing down network access or using too much CPU time.

        To answer your question about this PHP class vs the official SDK, neither will perform any better. (In fact, if you look at the code, they end up doing pretty much the same thing.) Using either class, sending a text-only e-mail should not be any faster than sending a text-and-HTML e-mail, except for the slightly increased time it takes to send the extra HTML data (but that should be in the millisecond range).

        Reply
        1. James Simpson

          It must be an issue with SES unfortunately. I’ve now tried it on a server with nothing else running, on a page that did nothing but send one SES e-mail, and the page took around 3 seconds to execute. I then tried doing the exact same thing with Postmark and it took 0.4s to execute. Not sure why Amazon would be that much slower.

          Reply
  44. Bryan

    @James- Same issue here. I am sending an HTML email to a test group of 3 emails. The page is in the “loading’ state for about 5 seconds before it sends them. I’m going to test that with 99, just using the same 3 emails 33 times each to gauge response time. A client of mine has about 2500 on her list, and she would like to use this as a solution, but I can’t have the page loading for an hour.

    @Dan.. isn’t there a way we could send the email to say another file or process, then let that file work in the background, and not have to sit and watch the current page send. I know I would probably click off the page before it’s done or forget to wait for it for sending 2k messages. Actually, the connection would probably time out, or my client’s web host would get mad if the page was loading for an hour.

    Too bad all that data isn’t sent to Amazon, and then they queued the emails and worried about the process time.

    Bryan

    Reply
    1. Dan

      Well… that *is* what’s happening, basically. Every time you’re making an API call, you’re asking Amazon to send an e-mail for you; according to their description, they stick it in a queue for sending.

      If you’re going to be sending large numbers of e-mails, I recommend that you do *not* do that while the user is waiting for a page load. A better solution would be to have a background process check for work every so often, for example a cron job running once every five minutes. The user could craft the e-mail appropriately, then click a button on your web interface; you store the data and flag the message for processing. The next time your cron job runs, you have it check for a pending task, and if it finds one, it marks the task as in-progress, sends the e-mails, and then marks the task as complete. Then you update the status display for your user.

      That’s a rough design, anyway, I’m sure you can figure out how to make it work 🙂

      Reply
  45. Sourabh

    Using this library how can I send 10000 mails?
    I am using loop for sending mails but it stuck after sending around 130 mails.

    I am using single recipient to send mails for every attempt. If I use array for TO list, one recipient can see others.

    If anyone have any options for this please reply also.

    Thanks

    Reply
    1. Dan

      There are a lot of reasons you might be having this problem. If you’re running the script through Apache, then Apache might be killing your script after a certain amount of time. I don’t recommend you send so many emails at once in a single page load in Apache.

      Reply
  46. Zladivliba

    Hey, great library ! It’s a pitty Amazon doesn’t provides a php library by default for each of their products, but thanks to you we’re able to try them out.

    I tried your lib and was able to use it in no time.

    Thanks a lot for providing theses tools. Oh, just one question : do you have plans integrating this into Zend framework ? I mean there’s been a lot of work done on their part to integrate Amz api, and I don’t think SES is build yet, so that could be a great integration for this lib.

    My, 2 cents,
    Z.

    Reply
    1. Dan

      Actually Amazon does provide an SDK for PHP for each of the services provided by AWS 🙂

      Sorry, I have no plans to integrate my class into any frameworks.

      Reply
    1. Dan

      It may work if you do this:

      $m->setMessageFromString(null, $html);

      But I have not tested it that way.

      Reply
  47. Brandon

    Phenomenal stuff! Very straightforward to get going.

    Any timeframe for development of sendrawemail? We really want to use dkim authentication.

    Thanks so much!

    Reply
  48. Jack

    I have my own bundle file that I use to verify SSL certificates. Is it possible to add support for defining that location?

    Reply
    1. Dan

      If you look at the function that calls curl_setopt a bunch of times (in the SESRequest class, if memory serves), you can add a line that specifies a certificate or directory containing certificates to verify against. From http://www.php.net/manual/en/function.curl-setopt.php:

      Alternate certificates to verify against can be specified with the CURLOPT_CAINFO option or a certificate directory can be specified with the CURLOPT_CAPATH option.

      You’ll have to experiment with it to see if it works with your custom bundle file.

      Reply
  49. shulato

    hi, i’m getting this error
    Warning: SimpleEmailService::verifyEmailAddress(): Sender – OptInRequired: The AWS Access Key Id needs a subscription for the service
    Request Id: 21ed072d-b273-11e0-aede-c37d1b4dea88
    in /home/mailer/public_html/includes/amazon.ses.php on line 363

    Reply
      1. shulato

        it’s working now. i just need to verify my payment method. do i need to verify all my setfrom email address? what is the maximum number of emails i can verify? can i control the message receive in setfrom email, like change where it came from?

        Reply
  50. JD

    This is a great class, I’ve been using it for several months now within a web app. Just trying to get it working from the command line now and I’m having trouble – anyone tried this and got it working?

    I’m trying to run a php script from crontab; the script does a bunch of stuff (which does work) but the sending of email via SES at the end of it doesn’t.

    The syslog indicates that the messages are being sent but they are definitely not being received! This suggests to me an environmental difference between web and cli but I can’t find any differences.

    Anyway, guidance would be greatly appreciated. Let me know if you need more info.

    Reply
    1. Dan

      Does the script work if you run it manually? (Not from a web browser, and not through cron, but running it manually on the command line.)

      Many servers have separate php.ini files for command-line php versus web-server php, so you might want to look in to that as well.

      Reply
      1. JD

        Running the script manually has the same result: runs ok but not receiving email. The class is returning a messageid and requestid in all cases, so not sure where it’s going wrong! Part of the script saves a file to S3 and that’s all fine. Also tried a test script that does nothing but try to send an email via SES – same result.

        Command line php and web server php are indeed using different ini files but they’re both the same. Ran phpinfo() on both to see what other differences there may be, but can’t see anything that would cause an issue. Pretty certain I’m missing something somewhere though 🙂

        Reply
        1. JD

          Got it: SES doesn’t seem to like the from and to addresses being the same anymore

          Reply
  51. Peter

    Hi,
    I am getting error for BCC
    Warning: SimpleEmailService::sendEmail(): M M in ses.php on line 357 .

    I am using
    $m->addBCC(‘peter@example.com’);

    addTo function works fine.

    Reply
    1. Peter

      Hi Dan,
      Kindly help me with my issue.
      I cant get bcc or cc to work. am i doing something wrong??
      Thanks

      Reply
          1. Phil

            $error is “Message failed validation”.
            I assume the reason is the Bcc (or others) are not validated email addresses then. Right?

            Reply
            1. Phil

              OK. Found the issue.
              I wrote $m->setFrom=… and setSubject=… instead of using them as functions.
              Dumb 🙂
              Now it works.

              Reply
  52. epriestley

    I have a patch to add optional exceptions (instead of trigger_error()) for errors, any chance you’d be interested including it?

    https://gist.github.com/1126313

    (Let me know if it doesn’t apply cleanly, I think my editor might have mucked with things.)

    Reply
  53. Steve

    Hi Dan:

    I am trying to add a custom X-header to emails I want to send using Amazon SES. Do you have an example of how to set the custom X-headers?

    I used the following in my php code to set the X-header. It sent the email but when I open the email I do not see the X-header that I had set.

    $result = $email->send_email($fromEmailAddress,
    array(‘ToAddresses’ => $toEmailAddress),
    array(
    ‘Subject.Data’ => $emailSubject,
    ‘Body.Html.Data’ => file_get_contents($emailBodyHtml)),
    array(‘X-EmailId’ => 101));

    Appreciate your help !!

    Thanks

    Steve

    Reply
    1. Dan

      Hi Steve,

      To set custom headers you have to use the raw message API, which unfortunately this class does not currently support.

      Reply
      1. Javier

        Hello Dan,

        I know this class does not support SendRawMail. Could you provide us a link/reference in how to send the POST of a custom header.

        Thanks in advance,

        Reply
        1. Dan

          Unfortunately, my class does not currently support doing this. You’ll either need to write the raw message support yourself, or use the official AWS PHP SDK.

          Reply
  54. Jason

    I am having an issue getting this running on a shared host, but is running fine on a local Mac.

    Warning: file_get_contents() [function.file-get-contents]: php_network_getaddresses: getaddrinfo failed: hostname nor servname provided, or not known in /some/path/ses.php on line 664

    any ideas on this one?

    this is a great class, thanks so much for taking the time to do this.

    Reply
    1. Jason

      this was a human error. be careful to change the URL or path if you are testing on both a local and remote host.

      thanks so much, this class has saved me so much time.

      Reply
  55. Pingback: Simple Email review, discussions, does it work, and ratings on Loadwp.com | Loadwp.com

  56. Jason

    Dan, I have a real question this time. I am trying to send to a list of three addresses in an array. I am attempting to do a foreach loop over the array and send a message to each of them. Each time I run it, only the last email in the list gets the message. I have tried to do it creating the $ses object inside and outside the loop with the same results.

    Here is an example:

    foreach($emailR as $to)
    {
    $ses = new SimpleEmailService(‘###’, ‘###’);

    $m = new SimpleEmailServiceMessage();
    $m->addTo($to);
    $m->setFrom(‘user@example’);
    $m->setSubject($subject);

    $m->setMessageFromString($text, $html);

    }

    I see a couple of references above to loops, but I can’t quite get it working. Thanks!

    Reply
    1. Jason

      Fixed (I had the last method outside the loop):

      $ses = new SimpleEmailService(‘###’, ‘###’);

      foreach($emailR as $to)
      {

      $m = new SimpleEmailServiceMessage();
      $m->addTo($to);
      $m->setFrom(‘user@example’);
      $m->setSubject($subject);

      $m->setMessageFromString($text, $html);

      $ses->sendEmail($m);

      }

      Reply
  57. CM

    hi dan, i am wondering if it would be easily possible to return the error message, such as whether or not the email is blacklisted or if you are over your quota so that the email addresses could be flag or ignored if the message was not sent.

    i am looking through the ses.php to see if i can get it working, but i figured it may be a nice feature for others as well.

    also, i have looked around, but is there a list of possible errors/responses we might get back so we know what to plan for?

    Reply
    1. CM

      i have gotten this to work by removing the
      //return false; on line 335

      and added

      $e = $rest->error;
      $theError = $e[‘Error’];
      $response[‘errorMessage’] = $theError[‘Message’];

      above return $response;

      do you see any issues with this? thanks.

      Reply
  58. andy

    I hava a question,I used every function ,the result is the same.

    [body] => CFSimpleXML Object
    (
    [@attributes] => Array
    (
    [ns] => http://ses.amazonaws.com/doc/2010-12-01/
    )

    [Error] => CFSimpleXML Object
    (
    [Type] => Sender
    [Code] => OptInRequired
    [Message] => The AWS Access Key Id needs a subscription for the service
    )

    [RequestId] => f72d1601-cee3-11e0-9ecc-1fa5af47a061
    )

    [status] => 403

    I leave part of result code ,I wish you can help me,thanks!

    Reply
  59. Tom

    Dan — thanks for a great library, its been very useful.

    Your thoughts on the following is appreciated:

    o How can I determine if an email has not been sent? i.e. because of throttling or exceeding quota?

    thanks!

    tom

    Reply
  60. Lucky Gupta

    I am getting this error on running the code. Please help to sort this out.

    Thanks in advance.

    require_once(‘ses.php’);
    $ses = new SimpleEmailService(‘AKIAJRRRAOQAWD6B2TQA’, ‘EPzfcddInMyuvFPuPXszZDoLA08BYDn8wYi8Wauc’);
    print_r(”);
    print_r($ses->verifyEmailAddress(‘abhitekindore@gmail.com’));
    print_r(”);

    Notice: Undefined property: SimpleEmailServiceRequest::$resource in D:\wamp\www\amazon\ses.php on line 491

    Warning: SimpleEmailService::verifyEmailAddress(): 60 SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in D:\wamp\www\amazon\ses.php on line 357

    Reply
    1. Dan

      You need to get php/curl’s SSL certificate verification set up properly on your machine.

      Alternatively, you could do this right after you create your SES object:

      $ses->enableVerifyHost(false);
      $ses->enableVerifyPeer(false);

      That disables SSL certificate validation for your SES service calls.

      Reply
      1. Andre

        Thanks Dan, this sorts out the problem of error messages when running user a Windows environment PHP setup!

        Reply
  61. Lucky

    Dan — Thanks for your prompt reply.

    I have another question to ask.

    I verified my personal email id. Now I want to send emails from another email id which refers to my domain for example admin@domain.com. I am not maintaining any email server for my domain. I mean I have not created any admin@domain.com email id. Is it possible?

    Thanks
    Lucky

    Reply
    1. Dan

      The “from” address must be verified, so you’ll need to use a valid e-mail address. You might try using an e-mail hosting service like Google Apps, if you don’t want to run a mail server yourself.

      Reply
  62. Ben Dodson

    Hi Dan,

    Thanks for the class – incredibly useful! The only problem I’m having is that I keep getting:

    "SimpleEmailService::sendEmail(): 6 Couldn't resolve host 'email.us-east-1.amazonaws.com'"

    This probably happens 1 in 5 times – is there any reason why this would be happening or any way to check if the email worked and then try again?

    Thanks,

    Ben

    Reply
    1. m elbou

      Just in case anyone is still having a problem like this, I had the same, and it was because mod_ssl was not enabled on my Apache2 server, enabling it like this a2enmod ssl on my Debian solved the problem for me.

      also make sure PHP curl extension is installed, if not, it can be installed like this on Debian/Ubuntu machines:
      [sudo] apt-get install php5-curl

      Thanks,

      M Elbou

      Reply
  63. nagasree

    when iam using ses->getSendStatistics() method it is not giving me the proper response all iam getting for Bounces,Complaints,Rejects emails as ‘0’ even if i have the mail that bounced..
    can any one please help me resolving the issue

    Reply
  64. Brendan

    Hi,
    Is it possible to use this code to send multiple emails from one request?
    I’ve been advised from SES Support that using BCC for bulk emaling is not a good idea as it will be treated as spam by many receiving mail servers.

    My idea was to use one PHP page to send an email with the following idea:
    $m->addTo(‘recipient-1@example.com’);
    $m->addTo(‘recipient-2@example.com’);
    $m->addTo(‘recipient-3@example.com’);

    However, there would hopefully be something that would define each email separately… that way your email addresses are hidden to all recipients.

    I’ve tried this with Perl using the sample scripts provided by AWS, but to no avail.
    I’ll bow to PHP experts here who may be able to help.

    Thanks!

    Brendan

    Reply
    1. Dan

      If you want to send a message to multiple people, but you want each of them to only see themselves in the To line, then you have to send multiple messages. There’s no way to do that in a single API call.

      (Your description, “that way your email addresses are hidden to all recipients”, is what BCC is for, so if you don’t want to use it, then sending individually-addressed messages is your only alternative.)

      Reply
  65. Geoff

    This seems like a great lib, only one problem: Download does not work for me (I’m not a newbie).
    Have attempted:
    – Firefox 3.6.22 on Ubuntu Linux
    – Chromium 12.0.742 on Ubuntu Linux
    – Firefox 5.0.1 on Windows XP
    – Firefox 7.0.1 on Windows XP
    – IE 8 on Windows XP

    In every case, the process is always the same:
    1. click your download link at the top of this page.
    2. SourceForge download page appears.
    3. after 5 seconds, when the download should start, a blank page appears.
    4. blank page has no source content.

    Note:
    – tried clicking the “direct link” link – also goes to blank page.
    – tried right-clicking on direct link and “save as”, saves a file of 0 bytes.
    – played with the URL, found an apache index of the files, the changelog and readme files have contents, but ses.php is always 0 bytes.
    – even wget on command-line saves a file of 0 bytes.

    Only you will know for sure, but it looks like a server-side problem (my guess is server is not serving the file for download, but executing it instead).

    Maybe you can package files in an archive or make an alternative location available?

    Eagerly awaiting your response (I really wanna try this library!)

    Reply
    1. Geoff

      Update: changed mirrors and it worked!

      The first mirror that SF assigned to me (unfortunately can’t tell you which one, it only displayed a logo, no name) was probably misconfigured to run php, even when served as a download.

      Hope this helps others who have this frustration.

      Reply
    1. Dan

      You’d need to use sendRawMessage to create a multipart message. Unfortunately this functionality is not implemented in my library.

      Reply
      1. todd

        Will you be adding this soon or should i just go ahead and start hacking 🙂

        Reply
        1. Dan

          I doubt I’ll be able to get to it anytime soon, but it shouldn’t be hard for you to hack it up 🙂

          Reply
    2. Doug

      Did you hack up the sendRawMessage feature?
      I’d love to use this class, but really need email attachments…

      Reply
  66. Yorch

    ¡Hello Dan!

    I have this message error:

    “Warning: SimpleEmailService::listVerifiedEmailAddresses(): 77 Problem with the SSL CA cert (path? access rights?) in /desarrollo/avisox/external/genericos/ses.php on line 357”

    How can I fix it?

    I’m pretty n00b in server topic’s

    thanks in advance

    Reply
      1. Dan

        I don’t know, looks like you may not have your ssl certificates set up properly on your machine. You’ll have to google to figure out what’s wrong.

        Reply
  67. asif hameed

    Hi,

    I am getting the following error. what is the reason of this error.

    Warning: SimpleEmailService::verifyEmailAddress(): Sender – RequestExpired: Request timestamp: Sun, 27 Nov 2011 11:34:46 UTC expired. It must be within 300 secs/ of server time. Request Id: a0636811-18fc-11e1-9fd8-35f83904a8c0 in /home/blue221/html/advertisers/amazon/inc/ses.php on line 363

    Reply
      1. asif hameed

        Hi Dan,

        Its really great effort that you has done, this script is working fine on my local machine.

        shall i tell my hosting service provider to change their clock to fix the above mentioned error ?

        Reply
  68. Sembisoft

    Excellent work, this wrapper works great! Looked around the internet for a while and this is by far the best I found. Thanks for all your time and effort.

    Reply
  69. Rob

    Thanks for this, it’s great. I must be a PHP noob, because I’m having a challenge figuring out how to work with the response(s).

    If I send a message, I get back the Array ( [MessageId] => 00000134c4e76989-f8afe9e0-ffda-4e59-8811-4480092faddd-000000 [RequestId] => a1c57c6a-3b1d-12e1-a333-f4772b496db4 ) as described. If I want to, say, insert these responses into a mySql table – how do I address the individual elements?

    Thanks

    Reply
    1. Dan

      If the response data is in a variable named $response, you’d do this:

      $messageId = $response['MessageId'];
      $requestId = $response['RequestId'];

      It’s just an array, like any other array in PHP.

      Reply
  70. Alexey

    Hi Dan

    This is my situation:
    i have a list of 15000 emails,and send rate 14emails/per second

    i did a loop and send each time 1 email.but speed about 1 email per second. What it’s can be?
    Or better add all emails togheter as $m->addTo()?
    Problem that i send unique link for each user in the email

    Thanks,Alexey

    Reply
    1. Dan

      Without seeing the code, it’s hard to say why your loop is only sending 1 email per second, but if you’re constructing the email message contents from scratch every time through the loop, especially if you do database lookups and such inside the loop, that could slow things down quite a bit. My suggestion would be to look through the code and see if there’s a way to reduce the amount of work done inside the loop.

      Reply
      1. Alexey

        example:

        $email_template = str_replace(‘[USER_UNSUBSCRIBE_INFO]’, $link_unsubscribe, $email_template);

        $m = new SimpleEmailServiceMessage();
        $m->addTo($email);
        $m->setFrom($fromfield);
        $m->setSubject($offer[’email_subject’]);
        $m->setMessageFromString(”, $email_template);
        $res = $con->sendEmail($m);

        if i off sending email – my script very very fast go by all emails

        Reply
        1. Dan

          This code sends only a single message, it does not send messages in a loop.

          If you want help finding issues with the code you’re running, you need to show me the code you’re running 😉

          Reply
  71. Philippe

    Very good wrapper, very usefull but I got a error when I sending the signature:

    Sender – SignatureDoesNotMatch: 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.

    Do I need to change something in my SES account for the signature to be accepted by this wrapper? My Secret Access key is valid, I check it many time so here my test code:

    getSendQuota());

    ?>

    but when I call it, I receive the error message. Any help will be appreciated.

    Thx

    Reply
    1. Dan

      There are many reasons this can happen. Without more information, all I can suggest the two following possibilities:

      * If you have multiple AWS Access Key and Secret Key pairs, make sure you’re using the right Secret Key for the Access Key you’re specifying.
      * Make sure your server’s clock is set correctly.

      Hope this helps!

      Reply
      1. Philippe

        Thanks for the reply, I try deleting my user and recreate it, valida the clock and now I got a new error:

        Encountered an error: Array

        Where the array is Code = 0 Message = Unexpected HTTP status

        Now I’m lost…

        Reply
        1. Dan

          Not sure, you’d have to add some debugging messages to the code that receives the response from the service, before it tries to parse the response code or XML.

          Reply
    2. Philippe

      It’s seem that I got a error sending my code:

      require_once(‘ses.php’);

      $from = “abc@something.com”;
      $to = “abc@something.com”;
      $subject = “Hello world for SES”;
      $body = “This is the message body.”;

      $host = “ssl://email-smtp.us-east-1.amazonaws.com”;
      $username = “ACCESSKEY”;
      $password = “SECRETKEY”;

      $ses = new SimpleEmailService($username, $password);

      $m = new SimpleEmailServiceMessage();
      $m->addTo($to);
      $m->setFrom($from);
      $m->setSubject($subject);
      $m->setMessageFromString($body);

      print_r($ses->sendEmail($m));

      And I they error, I don’t know the problem but it’s frustrating…

      Reply
        1. Philippe

          Thank you for your response. I change the ssl:// for https:// and I got:

          Couldn’t resolve host ‘https:’

          I really don’t know what I’m doing wrong. I’m doing this on my free time but man I start to loss hope…

          Reply
          1. Dan

            I just noticed two things:

            – You’re using the smtp endpoint; this library does not support that. (You’d use a regular mail agent if you wanted to use the SMTP endpoint, not this library.)
            – This library uses HTTPS by default, there is no need to specify an endpoint.

            Reply
            1. Philippe

              Thank you, that was the problem!!! The Host I take was from the SES tab in the AWS Console. Everything work, thank you very much, I was going crazy about that :).

              Best,

              Reply
  72. Christopher

    Dan,

    I’ve modified your code to do raw email messages in order to send attachments via the SES Web API. I can send it to you if you are interested. Not sure how useful it is now since SES now has SMTP support.

    – Christopher Mullins

    Reply
  73. Rami

    Hi Dan,

    Thanks for the great wrapper.
    I have a question on something that I may be missing.

    I created SMTP credentials using the AWS management console. I then downloaded the csv file with them and tried using the SMTP user name and SMTP password as the Key & secret, but get a SignatureDoesNotMatch error.

    Should I copy the user / password as is or am I supposed to first sign them or manipulate them somehow?
    Are there special packages that must be installed on the machine for this to work?

    Thanks!
    Rami

    This is the exact error I get:

    PHP Warning: SimpleEmailService::sendEmail(): Sender – SignatureDoesNotMatch: 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.

    Reply
    1. Dan

      My class doesn’t work with the SMTP credentials (nor the SMTP endpoint), you need to use your AWS Access Key and Secret Key.

      Reply
  74. Nitin Sharma

    Thanks Dan, it is really nice.

    It worked very well for us.

    Just wondering if you can help me out,
    In all the emails we are sending the from field shows “mailid@domain.com via email-bounces.amazonses.com”

    Is there any way in which we can change the email-bounces.amazonses.com part and display something else.

    thanks in advance

    Reply
    1. Dan

      Not all mail clients display that field directly. It’s basically an “on-behalf-of” header in the e-mail message; the “from” field is set to the from address you specified in the request.

      To more specifically answer your question, no, you can’t hide that field, but you don’t need to, and you shouldn’t.

      Reply
  75. Andre

    I’m sending about 500 emails out, each email unique. When the number reached more than about 30 emails, the server returns a FastCGI error. It is also very slow.

    What do i need to do to keep resources low? I define the $ses = new SimpleEmailService outside the loop then add the values inside the loop:

    $m->addTo($email_address);
    $m->setFrom(‘noreply@domain.com’);
    $m->setSubject($email_subject);
    $m->setMessageFromString(null, $email_body);

    And then send the email:

    $res = $ses->sendEmail($m);

    Do I have to define a new message each time using $m = new SimpleEmailServiceMessage() inside the loop?

    Reply
    1. Dan

      What’s the exact error you’re getting from FastCGI?

      If the script is timing out, then you’ll need to do either increase the timeout value on your webserver (or the fastcgi config, or php’s config, or wherever else might have a timeout value configured), or you’ll need to set up a more complicated system to process batches of e-mails asynchronously.

      Also keep in mind that SES rate-limits you, especially if your account is new, so your script needs to be aware that any given call to SES might fail, and you’ll need to throttle yourself and retry the failed e-mail.

      Reply
      1. Andre

        Hi

        It’s a shared hosting environment so I can’t change the timeout values. All I can do is find out why the code takes so long to send emails…

        The error is:

        FastCGI Error
        The FastCGI Handler was unable to process the request.
        Error Details:
        The FastCGI process exceeded configured activity timeout
        Error Number: 258 (0x80070102).
        Error Description: The wait operation timed out.
        HTTP Error 500 – Server Error.
        Internet Information Services (IIS)

        Reply
        1. Dan

          Yeah, the script is timing out.

          The problem is that it takes a while to build the message and make the API call each time through the loop. If it takes 50 milliseconds per message, then it takes 1500 milliseconds, or 1.5 seconds, to send 30 messages. (That time value is just a guess, I don’t know what the timeout value is set to on your service provider.)

          If you want to send more than a handful of messages at once, you’ll need a more complicated system. You’ll want to store a list of pending messages somewhere (a database, SQS, or SimpleDB for example), then have a background process (perhaps a cron job) slowly churn through the pending messages a chunk at a time.

          I realize it’s a non-trivial thing to do, but your other choice is to switch service providers to somewhere you can control the web server and PHP configuration. Amazon EC2’s t1.micros are pretty cheap, if you’re ok with managing your own web server 🙂

          Reply
          1. Andre

            Thanks Dan, you confirmed my suspicions. No, I’ll look at alternative methods of sending the email. I would like a simple PHP example of sending emails through Google Apps.

            Reply
            1. Dan

              You might also try a managed mailing list service like MailChimp. (MailChimp is free unless you’re sending a ton of emails… I think you get like 14,000 e-mails per month for free.)

              Reply
  76. Nick

    Hi

    Do you have correct example for send mail?

    I try but not work:

    verifyEmailAddress(‘my@mail.com’));

    $m = new SimpleEmailServiceMessage();
    $m->addTo(‘xxx@xxx.com’);
    $m->setFrom(‘my@mail.com’);
    $m->setSubject(‘Hello, world!’);
    $m->setMessageFromString(‘This is the message body.’);

    print_r($ses->sendEmail($m));

    ?>

    SimpleEmailService::verifyEmailAddress(): 7 couldn’t connect to host in ses.php on line 463

    Help me, please. I’m not profi PHP.

    Thank you

    Reply
      1. Dan

        There are a couple of reasons it could be marked as spam; if your “from” address is on a hosted service like gmail or hotmail, for example, those services’ SPF records do not list AWS as a valid sender for mail from that domain.

        I recommend you send using a “from” address on a domain you control, so that you can set your SPF records to list AWS as a valid sender for e-mail from the domain.

        Reply
  77. fraxxx

    Hello,

    first of all thank you so much for this post I clarified many things about “amazon SES”. Then I have one thing to ask. I should create a simple platform to send newsletters in php (I know there are many around open source, but I need to create an ad hoc) leaning to “amazon SES” and I wonder if
    GetSendStatistics you can use to find out if the email sent by a user has been opened by the recipient or not.

    Thank you in advance

    Reply
    1. Dan

      No, SES does not track whether the recipient has read your message. There are ways to do that yourself, but that’s far beyond the scope of what I can help you with here.

      Reply
  78. abdu

    Hi,

    the code doesn’t work for me. my php file is:

    require_once(‘ses.php’);
    $ses = new SimpleEmailService(‘my_key’, ‘my_secret’);
    print_r($ses->getSendQuota());

    this gives a blank page. i have uploaded the ses.php to same location. my php pages works on iis 7 on windows instance.

    i have checked phpinfo(). openssl and curl are enabled. what are the prerequisites needed.

    please help me on this

    Reply
    1. Dan

      What error messages show up in your web server’s error log?

      (You might try running the php file from the command line instead, which might make it easier to debug.)

      Reply
  79. Ryan Jansesn

    Hi Dan, thanks for this awesome script.
    How can I get statistics data ($ses->getSendStatistics()) from newest to oldest? And how can I only get 10 newest statistics data?

    Reply
  80. Andrew

    Dan –

    I have made modifications to allow for sending secure emails, emails with attachments and alternative text/html bodies.

    PM me if you want to marge this back into the main tree.

    Reply
  81. Vaibhav

    Great Work,

    Your Script is working fine with me.

    I would like to know, How to know weather mail is delivered or not? after using sendEmail()… getSendStatistics() will give all the details of the mail… Can i have any alternative way?

    Reply
    1. Dan

      Since e-mail is a delivery mechanism that does not guarantee delivery, SES cannot guarantee (or even verify) that a particular message has been delivered to the intended recipient.

      The only way to know for sure is for the user to tell you, either directly, via a read receipt or some other method, or indirectly, by embedding a tracking image in the message. That’s all up to you to take care of, though.

      Reply
  82. Radu

    Hy.

    First of all, great work! Nice and simple.

    I have implemented your class and got it up and running in no time.
    I had a small issue with the number of emails which I could send per second. Due to the fact that each time an email is sent a curl is called I could only send 1 email per 1.5sec, or so. I’ve made some changes in the class to use curl_multi, thus sending simultaneous curl calls. Now I’m sending as many emails per second as my limit allows me.

    Right now I’m facing the problem of retrieving the bounced and complaints. I want to store them in my db so I can have a reference. I read all the comments and it seems that Sean came up with a solution to set the replyTo address for each email sent with a specific id.

    I didn’t get if that can be done, b/c I read you can only set one replyTo. Is it one replyTo per eamil?

    If anybody found a better solution for retrieving the bounced and complaints please let me know.

    Good luck and again great job with this class!

    Reply
    1. Lionel

      Hi Radu,

      Can you show us what you changed in the class to use curl_multi? We are sending a lot of emails and are very interested by your solution.

      Best,
      Lionel

      Reply
  83. Pedro Mázala

    Hi, I got an error… What it means? :S

    Warning: SimpleEmailService::listVerifiedEmailAddresses(): 60 SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in …

    Thanks

    Reply
  84. Manny E.

    Hey there, i was wondering if you would be interested in getting some extra contributions from me for this class.
    i was thinking about expanding it a little, maybe adding some functionality, or a small UI for managing it with MySql tables…
    Let me know.
    Manny E.
    3w.

    P.S. thank you for this lovely class.
    Manny.

    Reply
  85. Mary

    This has made my day. Been struggling with the sdk and this really did just work! Fantastic – thanks so much.

    Mary

    Reply
  86. Manny E.

    Hey there.
    got a small issue when sending email, if the user choose to reply, it reply to his own email, is there something i am missing?

    Always a pleasure.
    Manny E.
    3w.

    Reply
    1. Dan

      You’ll want to set a reply-to address, like in my examples above:


      $m->addReplyTo('andy@example.com');

      Reply
  87. Hubert

    Hi Dan,

    Your script help me a lot, Thanks !
    I new in Amazon AWS & this is very helpful to send email from AWS.

    I just wondering, is it possible to get “Message” or “Return” value if email failed to send ?
    Maybe something like:

    if($ses)
    { // Do Insert DB code }

    But its not working, any suggestion ?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *