14 February 2011

AWS SES RequestExpired

SendGrid tells me I need a reseller account, and Postmark won't let me send newsletter-style messages; so it's time to try Amazon's Simple Email Service. All I need is a big machine that takes care of delivering mail, the rest is fluff.

I'm using drewblas/aws-ses. Somewhere between ActionMailer and AWS::SES, errors are swallowed and your application fails to let you know that emails aren't getting sent. By the time I had broken the "fetch mail" button on my mail client, it was time to run rails console on the server to figure out what was going on:

$ RAILS_ENV=staging rails console
Loading staging environment (Rails 3.0.3)
irb(main):001:0> require "aws/ses"
false
irb(main):003:0> ses = AWS::SES::Base.new :access_key_id => "your_access_key", :secret_access_key => "not_telling_you"
=> #<AWS::SES::Base:0x7fd3607d0308 etc... >
irb(main):003:0> ses.send_email :to => ['me@my.domain'], :source => 'test@other.domain', :subject => 'Testing', :text_body => 'Yes, testing!'
AWS::SES::ResponseError: AWS::SES Response Error: RequestExpiredRequest timestamp: Mon, 14 Feb 2011 10:13:32 GMT expired.  It must be within 300 secs/ of server time.

It turns out that my server's clock was racing into the future. I like how Slicehost moves fast, but I wasn't expecting observable relativistic effects. My server was 8 whole minutes ahead of the rest of the world. If I wasn't busy building my cool new site I could have used it to game the stock market or something wicked like that ...

Anyway, thanks to Code Ghar here's the solution:


$ date
Mon Feb 14 10:16:24 UTC 2011
$ sudo ntpdate pool.ntp.org
14 Feb 10:08:55 ntpdate[25724]: step time server 38.229.71.1 offset -639.622800 sec
$ date
Mon Feb 14 10:09:01 UTC 2011

Happy mailing!

10 comments:

  1. Just ran into the same problem - nice to find a solution as the first google result for "amazon ses RequestExpired".

    FWIW, I noticed this because we have the following to catch SES errors before they are swallowed:

    class Mail::Message
    def deliver_with_error_recording
    deliver_without_error_recording
    rescue AWS::SES::ResponseError => e
    # save e into send record
    end
    alias_method_chain :deliver, :error_recording
    end

    Which has proven helpful with some of Amazon SES' interesting errors.

    ReplyDelete
  2. THANKS :D same problem here, I was going nuts couldn't figure out the problem. silly silly hosting company!

    ReplyDelete
  3. This helps me to solve the time error very quickly...

    Thank you so much...

    ReplyDelete
  4. Just saved me a s*&#load of time , thank you very much :)

    ReplyDelete
  5. Thank you for posting this. Helped me to troubleshoot the same problem quickly.

    ReplyDelete
  6. This made my day, thanks.

    ReplyDelete
  7. Still relevant and helpful > 2 yrs later.. thanks for the help!

    ReplyDelete
  8. This saved me a lot of time troubleshooting what that error code means! Thanks a lot.

    ReplyDelete
  9. Yep, still relevant and helpful after years! Thanks for the post.

    ReplyDelete