55

In my Rails 3 project, I want to send some simple notification emails. I don't need to make a template for them or do any logic. I just want to fire them off from various places in the system.

If I were doing this in an arbitrary ruby script I would use pony. However, I'd like to still use the rails mail facilities and configuration, so that I get the same reliability and setup that I have for the rest of the mail in my system.

What's the most simple way to do this? Ideally there would be some method like

ActionMailer.send(:to => 'foo@example.com', :subject =>"the subject", :body =>"this is the body")
John Bachir
  • 22,495
  • 29
  • 154
  • 227

6 Answers6

123

The simplest way to send mail in rails 3 without a template is to call the mail method of ActionMailer::Base directly followed by the deliver method,

For ex, the following would send a plain text e-mail:

ActionMailer::Base.mail(
  from: "me@example.com",
  to: "you@example.com",
  subject: "test",
  body: "test"
).deliver

http://api.rubyonrails.org/classes/ActionMailer/Base.html#method-i-mail gives you all the header options and also ideas about the how to send a multipart/alternative email with text/plain and text/html parts directly.

Rimian
  • 36,864
  • 16
  • 117
  • 117
KMG
  • 1,246
  • 1
  • 9
  • 3
13

Rails 5 users may find the accepted answer (using format.text {...}) doesn't work; at least I was getting an exception because Rails was looking for a view.

Turns out there's a section in the Rails Guide called Sending Emails without Template Renderingand all one needs to do is supply :content_type and :body options to mail(). E.g.:

class UserMailer < ApplicationMailer
  def welcome_email
    mail(to: params[:user].email,
         body: params[:email_body],
         content_type: "text/html",
         subject: "Already rendered!")
  end
end
andyroberts
  • 3,458
  • 2
  • 37
  • 40
9

Here is little example from Rails Guides which uses render method. I didn't try it, but if it works as render in cotrollers, then you can just use:

render :text => "Your message"

or

render :text => my_message

Where my_message is a parameter.

You can just wrap it in a method which you can call from every place you want.

Updated Rails 3.2.8

In this version of Rails I had to do it like this:

def raw_email( email, subject, body )
  mail(
    :to => email,
    :subject => subject
  ) do |format|
    format.text { render :text => body }
  end
end
fguillen
  • 36,125
  • 23
  • 149
  • 210
klew
  • 14,837
  • 7
  • 47
  • 59
  • I considered this. It's pretty simple, but still requires making an `ActionMailer` model with a method. I was hoping there was maybe something even more simple, but if not this is the best choice. – John Bachir Feb 06 '11 at 22:25
  • Don't forget to add FROM header if you are sending mail to gmail. I've spent an hour figuring out why my mails aren't delivered and this was the reason. – remo Jan 28 '16 at 09:41
7

You can try something like this:

class Notifier < ActionMailer::Base
  def send_simple_message(options)
    mail(options.except(:body)) do |format|
      format.text { render :text => options[:body] }
    end.deliver
  end
end
John Bachir
  • 22,495
  • 29
  • 154
  • 227
John Douthat
  • 40,711
  • 10
  • 69
  • 66
3

Instead of using ActionMailer::Base like in KMG's answer, if you want to use your ApplicationMailer (which may have a default from address already), you can:

ApplicationMailer.new.mail(
  to: 'test@example.com',
  subject: 'subject',
  body: 'body'
).deliver
Richard
  • 141
  • 7
2

For people who land here and need to include ATTACHMENTS, this works:

mail = ActionMailer::Base.mail(
  from: 'tony@tigers.com',
  to: 'pooh@bears.com',
  subject: 'Interspecies cooperation',
  content_type: "text/html",
  body: 'Yo.'
)
mail.attachments["results.json"] = some_json_string_in_this_case
mail.deliver
WillHaslett
  • 668
  • 7
  • 13