March 29th 2011

Testing inbound mail with the mail gem

The mail gem has become the underlying library of Action Mailer with Rails 3, replacing TMail, but it's also capable of receiving email from a POP3 or IMAP account. I couldn't find any documentation for testing the retrieval, so I figured it out from the source - here's how you can test your inbound mail processing.

Instead of the POP and IMAP retrievers, you need to use the TestRetriever. To set it up, you'll just have to configure the retriever_method to :test, like this:

Mail.defaults do
  retriever_method :test

The "inbound mail" you'll be fetching is coming from the class method Mail::TestRetriever.emails, which is a plain array and is supposed to be fed with Mail instances which you'll obviosuly need to create either manually or by reading in a previously dumped email in the eml Format:

manual_mail = do
  from ""
  to ""
  subject "Fancy Test Mail"
  body "Oi!"

dumped_mail ='/path/to/message.eml')

Then, just add the mail to your inbound email collection:

Mail::TestRetriever.emails << manual_mail
Mail::TestRetriever.emails << dumped_mail

Calling Mail.all should now yield the test mails, so your mail processing code should process them as expected. Of course you could also use ActionMailer to generate your test messages: MyMailer.some_mail returns a plain Mail message instance.

Putting it together

You'll probably also want to reset the test email collection in a teardown method, so a basic test/unit test for inbound mail processing might look somewhat like this:

class InboundMailTest < Test::Unit::TestCase
  def setup
    Mail.defaults { retriever_method :test }
  def teardown
    Mail::TestRetriever.emails = []
  def test_inbound_mail
    # This class being your inbound mail processor.
    # Implementation left as an excercise to the reader ;)
    assert MyMailProcessor.process
    # more assertions that test the results of your mail processing...
    # Read in email from a prepared fixture file in eml format and push it to the 
    # inbound mail q
    def receive_mail(fixture_name)
      Mail::TestRetriever.emails <<"fixtures/mails/#{fixture_name}.eml")
Written by Christoph Olszowka
blog comments powered by Disqus