Recipe 9.6. Receiving Email with Action Mailer


Problem

Contributed by: Christian Romney and Diego Scataglini

You want to receive and process email from within your Rails application.

Solution

Action Mailer makes it simple to process incoming mail. The real trick is getting the mail to your Rails application. For this recipe, you'll need an empty Rails application and your database connectivity preconfigured. Be warned that this recipe requires a little system administration, so make certain you've got shell access into the server, and sufficient permissions to run your Rails application and install software.

If it's not already installed, download, compile, and install getmail. New versions of getmail are released periodically; make sure to get the latest version from http://pyropus.ca/software/getmail.

$ wget http://pyropus.ca/software/getmail/old-versions/getmail-4.6.4.tar.gz $ tar xvzf getmail-4.6.4.tar.gz $ cd getmail-4.6.4 $ ./configure $ make  $ sudo make install             

Next, create or modify a getmailrc file in the .getmail directory under your home folder. Create the directory if it doesn't already exist. Here are the contents of the getmailrc file; replace the server, username, password, and paths with values appropriate for your system:

~/.getmail/getmailrc:

[retriever] type = MultidropPOP3Retriever server = pop3.example.com username = yourUserName password = secret envelope_recipient = x-envelope-to:1 [destination] type = MultiDestination destinations = ("[maildir]", "[rails]") [maildir] type = Maildir path = /users/home/yourUserName/Maildir/ [rails] type = MDA_external path = /usr/bin/env arguments = ("RAILS_ENV=production",   "sh", "-c",   "cd /path/to/your/app; /usr/local/bin/ruby   script/runner 'Importer.receive(STDIN.read)'") [options] # delete messages on server delete = On

Now, create a crontab that invokes getmail every five minutes:

$ crontab -e             

0,5,10,15,20,25,30,35,40,45,50,55 * * * * "getmail"

We'll create a backup of copy of every email in a Maildir folder just in case the Rails importer fails for any reason:

$ mkdir ~/Maildir ~/Maildir/tmp ~/Maildir/new ~/Maildir/cur             

With the infrastructure bits completed, you can finally turn your attention to the Rails application. All you need is an Action Mailer class that will handle the import:

$ ruby script/generate mailer Importer             

class Importer < ActionMailer::Base    def self.receive(email)      # Do something interesting with the email here   end end  

Discussion

The solution uses getmail, an open source fetchmail replacement written in Python that is extremely reliable. It supports external MDA (program) delivery, POP3, IMAP4, Maildir, Mboxrd, domain/multidrop mailboxes, mail filtering and many, many other features.

In the retriever part of getmailrc we used MultidropPOP3Retriever. This is if you want to fetch emails for multiple email addresses and you create a catchall POP3 account (e.g.,*@example.com).

If you have a single email account to fetch, alter the type line in gmailrc file as follows:

[retriever] type = SimplePOP3Retriever

In this solution, getmail fetches the email messages and delivers them to two recipients. The first delivery creates a backup copy of all emails fetched in a Maildir folder, while the second delivery runs the Rails script/runner, which calls the Importer class. From the moment the Importer class receives the email, you can process it as you would with a normal text or email file. The beauty of using Action Mailer is that the email is parsed for you, and you can access all its properties in a object-oriented way. For example, assuming you've got a Feedback model defined, you can save the salient parts of the incoming mail to your database:

class Importer < ActionMailer::Base    def self.receive(email)      # Save the received email in our database using     # the Mail ActiveRecord Model     Feedback.create(:subject => email.subject,                  :body => email.body,                  :sender => email.from,                 :received_at => Time.now)    end end

Don't forget that many more things can be delivered through email than just text. Images, MMS, and SMS from a mobile phone can all be delivered through email. For a real-life example, check out the code of Markaboo, an open source project written in Rails that accepts input from emails, SMS, and MMS (http://markaboo.rubyforge.org).

See Also

  • Getmail's site, http://pyropus.ca/software/getmail

  • Find out how to receive email from the Rails wiki, http://wiki.rubyonrails.com/rails/pages/HowToReceiveEmailsWithActionMailer




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net