lflores
lflores

Reputation: 3800

Send an email newsletter/survey in Rails

Could someone please help me understand how to send an email to all the users of my website? I know how to create an email if the user signs up or submits a contact form or performs some action. But, I can't figure out how to send an email without some action being performed.

In my config/environments/production.rb I have:

config.action_mailer.smtp_settings = {
  :address              => "smtp.mandrillapp.com",
  :port                 => 587,
  :domain               => "majorfinder.com",
  :user_name            => ENV["MANDRILL_USERNAME"],
  :password             => ENV["MANDRILL_PASSWORD"],
  :authentication       => :plain,
  :enable_starttls_auto => true
}

config.action_mailer.default_url_options = {
  :host => "majorfinder.com"
}

In my app/mailers/questions_mailer.rb I have:

class QuestionsMailer < ActionMailer::Base
  default from: "[email protected]"
  def interest_question(user)
    @user = user
mail(to: @user.email, subject: "My Subject")
  end

I have the txt and html version of my email created and placed in app/views/questions_mailer/email.html.erb / email.txt.erb.

What I'm missing is what do I put in my controller to make the email send. Is it something like:

QuestionsMailer.interest_question(@user).deliver

At the time of sending this I have around 300 users. Should I break this up into more than one batch (something like I found here: Sending emails based on intervals using Ruby on Rails)?

I don't know if this is important but I'm hosting on heroku and my database is postgresql.

Thank you so much for any help you can give me!

UPDATE: I followed @jefflunt's suggestion and create a rake task. Here's what mine looked like:

desc "Email to ask users what they're most interested in"
task :interests => :environment do
  User.all.each do |u|
    QuestionsMailer.interest_question(u).deliver
  end
end

And then I ran rake interests locally to make sure everything worked fine. Once I pushed all the changes up to heroku I ran heroku run rake interests and an email was sent to all the users.

Upvotes: 3

Views: 1136

Answers (1)

jefflunt
jefflunt

Reputation: 33954

Create a rake task that iterates through all the email addresses of active users on your site, constructing, and sending, one email per user.

Something like:

namespace :transactional_emails do
  desc "Email to ask users what they're interested in"
  task :interests => :environment do
    User.all.each |u| do
      QuestionsMailer.interest_question(u).deliver
    end
  end
end

I don't think it's important to send in batches unless the task completely soaks up your CPU or takes up more RAM than you can spare on your app server. It's unlikely to have more than a minor impact on your DB performance.

The loading of the :environment is likely required (it basically loads up your Rails app) so that your connection settings to your database, as well as your ActionMailer config from config/environments/production.rb is loaded as well. When you have your environment loaded in a rake task, most everything in your app should be accessible to you, including all models and such.

Some notes:

  1. Loading the environment means the startup time for your task will be longer than if it didn't load the environment, however it may not be an option to exclude your environment since that's where your SMTP settings are stored.
  2. With 300+ users, this task may take a while to run, so make sure to run that task in such a way that if it takes a long time to finish you are logging success/failure so you can restart the task somewhere in the middle of the list, in case the job gets killed or something otherwise interrupts the email delivery. What you don't want to do is have to re-send to the entire list if only 10% of your users didn't get the email the first time. I would recommend against the batch approach mostly because it adds complexity to your app with some kind of a periodic job, and unless you can measure real, detrimental impact to your app, it's not necessary to spread this work out over time. Most of the load on your app server when making a ton of SMTP connections is going to be the network connections out to your SMTP server - so probably not a big deal.
  3. rake tasks can accept command-line parameters if you'd prefer to pass a sub-list of your users, a custom subject line, or other useful information into the task. Let's say you somehow split your users up by User::active?, User.veteran? and User.recently_joined? whereby the .active? users were users that had logged in within the last 30 days, the .veteran? users were users that had been on your site for at least a year, and the recently_joined? users were people whose account creation happened within the last 30 days. Passing something in to the command line like:

    bundle exec rake user_email SEGMENT=veterans

...could be a way to conditionally send email to some sub-set of your entire user base.

Writing custom rake tasks is covered here.

Things to consider when sending a blast email in order to increase chances of avoiding spam filters can be read here.

Upvotes: 4

Related Questions