#61
Jul 23, 2007

Sending Email

This is a brief guide to sending email in Rails. See how to configure the environment, generate a mailer, create a template, and deliver the mail.
Tags: mailing
Download (11.9 MB, 7:58)
alternative download for iPod & Apple TV (9.6 MB, 7:58)

Resources

# config/environments/development.rb
config.action_mailer.raise_delivery_errors = true

# set delivery method to :smtp, :sendmail or :test
config.action_mailer.delivery_method = :smtp

# these options are only needed if you choose smtp delivery
config.action_mailer.smtp_settings = {
  :address        => 'smtp.example.com',
  :port           => 25,
  :domain         => 'www.example.com',
  :authentication => :login,
  :user_name      => 'www',
  :password       => 'secret'
}

# users_controller.rb
UserMailer.deliver_registration_confirmation(@user)

# user_mailer.rb
def registration_confirmation(user)
  recipients  user.email
  from        "webmaster@example.com"
  subject     "Thank you for Registering"
  body        :user => user
end
<!-- registration_confirmation.rhtml -->
Hi <%= @user.name %>, ...

RSS Feed for Episode Comments 55 comments

1. chineseGuy Jul 23, 2007 at 00:46

Thanks


2. Jaffet Jul 23, 2007 at 01:02

Thank you.


3. Manuel Jul 23, 2007 at 02:19

Perfect introduction and right on time! This was my task for today. Thanks!


4. Ross Jul 23, 2007 at 02:25

Fantastic. The effort spent on all of your casts are greatly appreciated.


5. Mikel Lindsaar Jul 23, 2007 at 02:42

Ryan, you are scary :) This is the third time I thought "Hmm... I need to learn about X" and then I look at iTunes and your screen cast JUST DOWNLOADED WITH THE EXACT SUBJECT I WAS GOING TO LOOK AT!!!

Freeeeeeeeeeky.... but very, very, very cool :)

Thanks again

Mikel


6. gUI Jul 23, 2007 at 06:12

Clear, simple... as always !!!

Thanks a lot for your work.


7. dave Jul 23, 2007 at 13:37

Just curious. If you sent email via SMTP - that process actually sends the mail at the time of request and doesn't cue it up for later delivery correct? So if the SMTP server you're mailing thru takes forever to answer/deliver - you're user is stuck waiting as well?


8. Ryan Bates Jul 23, 2007 at 14:05

@dave, good question. I believe ActionMailer will open a socket to the mail server right there and send the email (using net/smtp). If the mail server takes a while to respond then it might hang. I don't know for sure though. The best thing to do is try it out and see.

It would be really cool if ActionMailer had a separate queue, that way if the smtp server is down or anything it would throw it in the queue for later delivery.


9. Martin Jul 23, 2007 at 15:03

@dave, @Ryan:

I'm not familiar with ActionMailer (I'm still new to Ruby/Rails), but any sane e-mail client (ActionMailer, in this case) will throw an error if the SMTP server you're trying to connect to is unavailable.

Messages are not delivered in real time. The client (ActionMailer) will hand the message over to the SMTP server, which in turn is responsible for delivering the message. The client's involvement ends there. The SMTP server will add the e-mail to it's queue and deliver it as soon as possible. If it can't (i.e. the receiving server is unavailable) it will stop trying after some time (usually a few days) and notify the sender by e-mail.

Short story: A broken mail server won't hang your application :)


10. dave Jul 23, 2007 at 17:04

@martin
I was referring to possibility of connection timeouts and the length it would take to connect to, transfer and complete the transaction between your rails app and the SMTP server you're trying to send mail thru. If your SMTP server isn't responding quickly, your user could experience a lag time.

Where as if you went with the sendmail option for actionmailer, sendmail, postfix, whatever your MTA is would accept the email, then try to send it out for you - adding it to a background process que, freeing up your app to continue on (in theory).

I think for me the sendmail option is a better one, but then you've gotta configure your MTA yourself (at least in my case on a VPS).

I'm far from close to launching my app, so for dev's sake, I'm sticking with SMTP option for now.

Thx Ryan!


11. dudzjosh Jul 23, 2007 at 19:23

Thanks Ryan,

Awesome tip, I've been using the instance variable technique for quite awhile now :D


12. Chuck Vose Jul 23, 2007 at 19:26

@dave, @Ryan:

ActiveMailer is not asynchronous so it does hang if the smtp is busy but not if it's denying requests. The popular example is sending mass emails through ActiveMailer using Mongrels as the app server (because Mongrel has a 60 second timeout).

The way around this is to either configure smtp to queue mails (the default for most MTAs), or to use something like ar_mailer by Eric Hodel if you don't control your MTA.

http://blog.segment7.net/articles/2006/08/15/ar_mailer


13. macovsky Jul 24, 2007 at 00:34

@Ryan,

is there a way to share usual helper methods for emails' views? or to define them at one place?


14. sfty Jul 24, 2007 at 07:18

TYVM!

ActionMailer was the next thing on my TODO list also. ;)

I guess the path of learning things in Rails is quite similar for many people.

Very interesting! :D


15. dave Jul 24, 2007 at 09:33

@ryan, what might be a helpful cast would be, how to send multi-part emails in Rails. Both plain text and HTML combined in one email.

Thx!


16. dave Jul 24, 2007 at 09:36

should have read the api docs before speaking. it's all right in there :-)


17. Ryan Bates Jul 24, 2007 at 09:48

@macovsky, good question. I believe you can create your own custom helper module (helpers/foo_helper.rb) and include that using "helper :foo" in the UserMailer class. This is very similar to how you would set up custom helper modules in a controller. Untested.


18. Carl Jul 24, 2007 at 13:15

Chuck, is it Mongrel that has the 60 sec timeout or Apache? I increased the timeout on Apache (I have several tasks for my app that can take a few hundred seconds, directory crawling, etc) and Mongrel seems to keep going until the task is done (but Apache may throw a "proxy mod error" if it goes too long, which is why I increased the time). And yes, its an internal website for logging people's work, so it's okay that it can take a long time on certain tasks, those tasks don't come up that often.


19. Adam Patterson Jul 24, 2007 at 17:39

The whole time I was wondering why you weren't using instance variables for the email, like in Acts As Authenticated, but you answered at the end.. I guess AAA is a bit out of date then?

Also, one thing I like about AAA is the user_observer where you can specify something like this

  def after_create(user)
    UserNotifier.deliver_signup_notification(user)
  end

Seems like a more modular approach so you dont have to put it in multiple controllers. Any thoughts on this?


20. Ryan Bates Jul 24, 2007 at 19:10

Using the observer is a neat trick, but I can imagine it backfiring. Let's say you set up a rake task to import a bunch of users from a csv file. Well, all of those will receive an email as the User model is created. In some cases this may be what you want, but I prefer to have more control over when an email is sent. I don't want to spam someone accidentally. The act of sending an email seems more like a controller action to me.


21. Bill Davis Jul 27, 2007 at 05:48

Great screencast!

I am left wondering, however, how you can extend this to send the user to an activation link. IOW they cant login till they click the link you send them in the email.

Is this really involved?


22. Ryan Bates Jul 27, 2007 at 08:41

@Bill, I would set up an ActivationsController to do this. You can have a link in the email point to this controller and the controller can activate that account. You would need to add a unique token column to the users controller so there's some way to identify it so it can't be guessed.


23. Diego Jul 29, 2007 at 20:31

Thanks for your work Ryan

you are great


24. Tyler Jul 31, 2007 at 08:34

Is there any reason why ActionMailer wouldn't send emails in development on localhost? I don't get any error messages and the development tail returns "Sent mail:" with the message details following.


25. Ryan Bates Jul 31, 2007 at 13:37

@Tyler, It's hard to say. Did you set raise_delivery_errors to true? If you're using SMTP then check the logs on the SMTP server (if you can). If you're using sendmail then it's probably not configured properly. You may want to ask this on railsforum.com


26. Diego Aug 05, 2007 at 00:01

is there a way to send email from script/console directly?


27. Diego Aug 05, 2007 at 13:29

what is the difference with ActionMailer and UserMailer?


28. Diego Aug 05, 2007 at 19:13

Oops, just forgot the UserMailer is the class that I've created and that inherits from ActionMailer.


29. Diego Aug 05, 2007 at 19:14

Great tutorial thought, I've already sent mail from script/console :)

Keep up the great work!


30. Diego Aug 08, 2007 at 00:54

is there a way to avoid the database part, i just want to send the mail directly without saving the mail into the database, is there a way to do this?


31. Ryan Bates Aug 08, 2007 at 07:27

@Diego, yep. You can create a model object which doesn't inherit from ActiveRecord and just use that. However, validation will be quite a bit trickier.

Even if you don't need to store the data in the database, I prefer to anyway. This way I have a backup of every user input in case the email isn't delivered properly.


32. Diego Aug 18, 2007 at 00:52

yeah i think is a good idea too, thanks ryan :)


33. Daniel Sep 15, 2007 at 05:11

Thanks for your source code, it saved me a lot of time! Well, if I want to use the code snippet in production, I only have to copy the code into the production.rb or is the environment.rb a better place?


34. Ryan Bates Sep 15, 2007 at 08:31

You can place it in environment.rb, but it will then be shared across all environments. Likely you want to customize how the mailing is going to happen between environments so I recommend placing it in production.rb.


35. lark Feb 19, 2008 at 16:09

I am using sendmail to allow users visiting my site to send emails. This works fine with my configuration except when the recipients have a yahoo address. Yahoo seems to put my mail into the spam folder. Has anyone else encountered this?


36. Dave Mar 05, 2008 at 12:31

i think what would have been helpful after having done all this setup is to show how to test if the setup is correct via script/console.

the way this is presented, it seems to asume that you have all this work done on having users, and what i would want to do first is test if the setup was correct. are there a few commands that will get to that?

also, in some cases i have seen things defined as this:

ActionMailer::Base.smtp_settings = {
  :address => "your smtp server",
  :port => smtp-port,
  :domain => 'your domain'
}

verses the way that you did it here... is this a newer way to do setup?


37. Hari May 09, 2008 at 11:58

I have setup ActionMailer to send mails via Gmail.

Here are the settings:

config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => "587",
:domain => "example.com",
:authentication => :plain,
:user_name => "admin@example.com",
:password => "secret"
}
The "admin" username has an email account setup with a name of "Mailer
Account"

How do I set the From: header so that the user's inbox shows the name on
the account that the mail is sent from instead of the username "admin"
that shows up currently.

How do I get this to happen?

Thanks in advance


38. John May 29, 2008 at 05:56

Dave,

You might need to associate the email you want to display with the email account you're using to authenticate.

Gmail is probably not allowing you to change your "from" because it doesn't recognize the specified email as yours.


39. Ank Jul 02, 2008 at 06:18

Hi,
  Thanks for the screencast. The problem i am facing is that in the smtp settings you can have only one setting. e.g if I sometimes want to send a mail from gmail and another time from yahoo I have to change the settings in the production.rb or development.rb. How can i configure it, so i can use both the settings of yahoo and gmail(or any other) depending on from where the user wishes to send his mail.
Thank you.


40. Ahmed Abulnasr Nov 04, 2008 at 04:02

thank you so much ...
it's GREAT :-D


41. Ben Nov 17, 2008 at 08:12

Hi,

Thanks for the tutorial.

Played around with ActionMailer and I got it to work from the console and by running script/server.

We're running passenger (mod_rails) and I can't seem to send mail with it. I'm sending via smtp.

Any suggestions?


42. Tim Dec 05, 2008 at 16:16

I'm not clear on what the user_name and pass are the user/pass TO. Can you explain?


43. jim jones Jan 07, 2009 at 09:31

Is it possible to set keys in the hash: config.action_mailer.smtp_settings

dynamically? I'd like to set the :user_name just before an email is sent. Can that be done?

Thanks.


44. fred smith Apr 05, 2009 at 18:58

I'd be interested in learning how to set the email settings dynamically too.


45. rohandey May 04, 2009 at 03:53

Is there is any update on the comment number 48, even I want to change the mail configuration at runtime.


46. TIm Inman Jun 19, 2009 at 09:37

Hey Ryan,

Thanks for another great podcast. I was successful setting up a mailer on my user model, but when I tried to apply my learning to set up a mailer on another model I got stuck.

My problem: the Feedback model data isn't getting passed to the view, resulting in a nil error.

Would you have a look at my code and tell me if you see anything I'm missing?"

http://pastie.org/517714


47. inbreed Jul 01, 2009 at 06:57

Is anyone of you able to send a email contending html, plain and attachment? (all 3 parts in 1 email)
and if so, how?


48. pravin Jul 07, 2009 at 00:53

i tried this example but gave me error like

530 5.7.0 Must issue a STARTTLS command first. g25sm12608420wag.43

please give me some solution


49. Fabian Jul 15, 2009 at 06:39

@pravin if your running ruby 1.8.7 you can get past the STARTTLS error put the line

:enable_starttls_auto => true,

in your ActionMailer::Base.smtp_settings hash.


50. 白牙 Oct 18, 2009 at 03:22

good video..thx


51. Pratik Khadloya Nov 07, 2009 at 20:45

To connect to gmail, use the plugin
http://github.com/collectiveidea/action_mailer_optional_tls
It has been updated to support Ruby 1.8.6 and 1.8.7 both.


52. mehdi karamnejad Feb 08, 2010 at 23:31

it is short and sweet! nice!


53. faucet Mar 12, 2010 at 19:26

Thanks to your guide, very nice!


54. aashish Mar 17, 2010 at 04:39

if i dont have a domain then how to send email


55. Rohit Menon Apr 09, 2010 at 15:10

Could you give a screencast on receiving email using Rails ? or could you point me to a good resource on the web where I could get this information. Thanks.


56. rehearsal dinner May 13, 2010 at 02:09

That sounds very interesting, but don't freak out. How trustworthy is this person? If he\she just click fwd entered your name and sent it then it would be a mistery, but the more likely sernario is that he\she hit fwd, edited the text of the email to include his\her address in the "To" line then sent it to you.


57. Happy Visitor May 22, 2010 at 14:14

Thanks... I was missing deliver_ in front of method calls.


58. Louis Vuitton Audra Black M40048 Jul 16, 2010 at 07:42

I was actually looking for this resource a few weeks back. Thanks for sharing with us your wisdom.This will absolutely going to help me in my projects .


59. Here is the newest coupon code for a free sample of <a href="http://www.maccosmeticsretail.com">MAC Cosmetics</a> Zoom Lash mascara with any purchase. You will also get free shipping on your order. Just enter promotional code LASH510 at checkout at http:/ Jul 19, 2010 at 02:29

Here is the newest coupon code for a free sample of <a href="http://www.maccosmeticsretail.com">MAC Cosmetics</a> Zoom Lash mascara with any purchase. You will also get free shipping on your order. Just enter promotional code LASH510 at checkout at http://www.maccosmeticsretail.com. Keep in mind that these offers expire after a period of time.


60. mac Jul 19, 2010 at 02:30

Here is the newest coupon code for a free sample of <a href="http://www.maccosmeticsretail.com">MAC Cosmetics</a> Zoom Lash mascara

with any purchase. You will also get free shipping on your order. Just enter promotional code LASH510 at checkout at

http://www.maccosmeticsretail.com. Keep in mind that these offers expire after a period of time.


61. asics shose Jul 28, 2010 at 00:13

with any purchase. You will also get free shipping on your order. Just enter promotional code LASH510 at checkout at


62. sanejenny Aug 03, 2010 at 08:36

The winner are really happy for their second times of winning the trophy. It really a new record for them and for this competition.


63. free directory list Aug 11, 2010 at 22:20

Ryan, could you show the view that is calling this template?


64. 90x workout Aug 12, 2010 at 09:27

I am not much into reading, but somehow I got to read nice information on your site. Simple to understand and helpful. We will look forward for your future updates.Thanks!


65. Air Jordan Force 4 Aug 16, 2010 at 00:38

will also get free shipping on your order. Thanks to your guide, very nice!


66. error fix Aug 16, 2010 at 04:41

i would want to do first is test if the setup was correct. are there a few commands that will get to that?


67. jimmy choo wedges Aug 25, 2010 at 00:23

it's a good application. Thanks


68. louis vuitton shoes Aug 26, 2010 at 21:17

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


69. snow boots Aug 31, 2010 at 01:07

If you sent email via SMTP - that process actually sends the mail at the time of request and doesn't cue it up for later delivery correct? So if the SMTP server you're mailing thru takes forever to answer/deliver .


70. levis belts Sep 01, 2010 at 20:56

Intimately, the post is actually the best on this laudable topic. I harmonize with your conclusions and will eagerly look forward to your future updates. Saying thanks will not just be adequate, for the fantastic lucidity in your writing.


71. breitling watches uk Sep 02, 2010 at 07:51

So far I have tried using a Privileges table that holds a user_id, role_id and account_id, but I can't find a way to find out if the current user within the current account belongs to a certain role.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source