Note: This page may be out of date with current API
but the initial setup and example have been modified to reflect the use of methods versus instance variables.
My updated tutorial for sending emails, tested with 2.0
How to send email with Ruby on Rails
ActionMailer is a Rails service-layer package for creating email messages.
Create a stub file using the generator:
ruby script/generate mailer Notifier
A file is created in your app/models directory named notifier.rb:
class Notifier < ActionMailer::Base
end
There are a few confusing things to learn with Action Mailer that took a while to figure out.
Let’s assume we’re sending an email to a new user to our website to thank them for signing up, and that user is an object coming from an Active Record that has already been created.
Add the following method to your Notifier:
def signup_thanks( user )
# Email header info MUST be added here
recipients user.email
from "accounts@mywebsite.com"
subject “Thank you for registering with our website”
# Email body substitutions go here
body :user=> user
endAnd the following snippet to the controller in your application that needs to send an email:
def show_page_after_account_creation
...
Notifier.deliver_signup_thanks(user)
...
endThe body of the email comes from a .rhtml file in app/views/notifier – In this example; app/views/notifier/signup_thanks.rhtml:
(Note: You might have to end the name with _en.rhtml, i.e.signup_thanks_en.rhtml, if you use localization)
Dear <%= @user.first_name %> <%= @user.last_name %>,
Thanks for signing up with My Website!
Your account will allow you to do blah, blah, blah.
It is possible to use helpers to your email templates simply by adding
helper :application
to your mailer model. (read the article)
The mail configuration should be set in your environment. See the API documentation for configuration options. To have your configuration available for all server environments put it in /config/environment.rb, otherwise place it in config/environments/production.rb or config/environments/development.rb.
Make sure ActionMailer is removed from this line in environment.rb:
config.frameworks -= [ :action_web_service, :action_mailer ]
The default method for sending mail is SMTP. ActionMailer can also use sendmail, and for initial testing and development you probably want to switch to that. Stick this in your environment.rb: (After the Rails::Initializer.run do |config| block)
ActionMailer::Base.delivery_method = :sendmail
You may also turn exception raising on and off. The documentation does not state which is the default, so just to be sure, you can turn on exceptions like so:
ActionMailer::Base.raise_delivery_errors = true
A sample configuration setting using the default smtp delivery method would look something like this:
# Include your app's configuration here:
ActionMailer::Base.smtp_settings = {
:address => "smtp.postoffice.net",
:port => 25,
:domain => "www.mywebsite.com",
:user_name => "me@postoffice.net",
:password => “mypass”,
:authentication => :login
}
:domain is the name sent to the SMTP server during the handshake. It will be used to form the first “Received:” header, which spam filters usually check.
If your SMTP server uses “pop before smtp” authentication, check PopBeforeSMTPForActionMailer
You need to restart WEBrick or Apache to reload changes to to your environment.
Note for TextDrive users: On TextDrive, the default settings work, so no explicit configuration is needed. Leave the server_settings as their defaults (ie. don’t set anything).
Instead of calling deliver_XX_mail (whatever your method is called) call create_XX_mail... it returns a TMail object
mail = Mailer.create_my_mail(params)
after that, you can set the mime type and append attachments:
mail.set_content_type('multipart', blah blah)
mail.parts << my_attachment
( Excuse me, but what is 'blah blah' supposed to be?mail.set_content_type(‘multipart’, ‘mixed’) ?
(And is my_attachment just _any_ binary file, or is there some missing encoding process involved?)
then call
Mailer.deliver(mail)
where Mailer is the name of your class that extends ActionMailer::base.
Gem rails added attachment handling
# attachments
def signup_notification(recipient)
recipients recipient.email_address_with_name
subject "New account information"
from "system@example.com"
attachment :content_type => "image/jpeg",
:filename => "another-image.jpg"
:body => File.read("an-image.jpg")
end
attachment "application/pdf" do |a|
a.body = generate_your_pdf_here()
end
You will probably want to specify the filename of the attachment, and also send it along with a text message:
def new_user(user)
@recipients = user.email
@from = <a href="mailto:info@mysite.com">info@mysite.com</a>
@subject = "Welcome to My Site"
body = {}
body['first_name'] = user.first_name
part :content_type => "text/plain",
:body => render_message('new_user', body)
attachment "application/pdf" do |a|
a.disposition = "attachment"
a.filename= "myfilenamethatmightbedifferent.pdf"
a.body = File.read(RAILS_ROOT + "/path/to/myfile.pdf")
end
end
I don’t know if this is the simplest or latest way to do this, but it works for me. Also note that the ‘body’ variable in the example is not the usual ’@body’ instance variable; it is a hash passed to render_message() function. I use this variable in the example to demonstrate the relationship to the standard way of sending an email.
If you encounter a smtp server that requires TLS, then you cannot send emails directly using ActionMailer. But you can still send emails by using a lightweight substitute for sendmail such as msmtp to act as mediatory between ActionMailer and the SMTP server. Here is what I did to get ActionMailer up and running:
account provider
host <smtp.your-host.com>
auth on
port <port_num>
user <username>
password <password>
tls on
*tls_trust_file <directory>ThawtePremiumServerCA_b64.txt*
tls_starttls on
auto_from on
account default : provider
ActionMailer::Base.delivery_method = :msmtp
module ActionMailer
class Base
def perform_delivery_msmtp(mail)
IO.popen("/usr/local/bin/msmtp -t -C /path/to/your/.msmtprc -a provider --", "w") do |sm|
sm.puts(mail.encoded.gsub(/\r/, ''))
sm.flush
end
if $? != 0
# why >> 8? because this is posix and exit code is in bits 8-16
logger.error("failed to send mail errno #{$? >> 8}")
end
end
end
end
Another way to do this is outlined http://stephenchu.blogspot.com/2006/06/how-to-use-gmail-smtp-server-to-send.html
Along the same lines is http://blog.pomozov.info/posts/how-to-send-actionmailer-mails-to-gmailcom.html but it seems a little easier to follow. Be sure to scroll down to the updated version.
class AdminMailer < ActionMailer::Base
def message(recipient, subject, body)
@from = "admin@expresstrans.com"
@recipients, @subject, @body = recipient, subject, body
end
end
Mass mailing
When you want to send a mail to a large number of recipients, you shouldn’t do it purely with ActiveMailer as it opens an SMTP connection for each mail sent. You can find a script to do just that at Mass mailing with ActiveMailer,
*Can someone give more info for mass mailing? The link is not very helpful as far as a step by step process.. (do you HAVE to send mails from the command line? What if you want to send mails from a form on your site? How does that work?)
Hi All I am getting error code 69 while using msmtp please help me to come out of this my email id is aashutosh.tiwari@in.v2solutions.com
can somebody help me by telling how to get a smtp server
Screencast:
How to send emails with pdf attachments in Rails2.0