Flylib.com

Books Software

 
 
 

Recipe 9.5. Sending Email from a Rails Application


Recipe 9.5. Sending Email from a Rails Application

Problem

Contributed by: Dae San Hwang

You want to create and send email from your Rails application.

Let's say a new customer has just filled out a registration form at your web site. You want the complete_registration action in RegistrationController to save the customer's registration information to the database and to send the welcome email.

Solution

This solution uses the CustomerMailer class from Section 9.2."

Sending email using Action Mailer is a two-step process. First, you create a mail object by calling a class method of the mailer class whose name starts with create_ . Then you use the class method deliver of the mailer class to actually send the email off to the SMTP server.

app/controllers/registration_controller.rb :

class RegistrationController < ApplicationController

  def complete_registration
    new_user = User.create(params[:user])

    mail = CustomerMailer.create_welcome_message(new_user.name, new_user.email)
    CustomerMailer.deliver(mail)
  end
end

Discussion

Action Mailer internally uses the TMail library, written by Minero Aoki, to create and process emails. For example, the mail variable in the complete_registration action is a TMail::Mail object.

See Also

  • TMail Project home page at http://i.loveruby.net/en/projects/tmail

  • Section 9.2"

  • Section 9.3"



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