How to: Individualized mass email with ActiveMailer - separate thread?

Hi,

We are building a rails application that's sort of a CRM + room/course booking. Among other things, it provides a centralized database of all the people the company has been in contact with.

We want to provide the possibility of sending customized email messages to groups of contacts, for example a newsletter to 500 people starting with "Hi [:name:]". The naive approach we're using is basically placing the following code in the controller:

email.people.each do |p|   # This generates a custom email for that person, with fields such as [:name:]   # filled with the person's name   raw_email = PeopleMailer.create_general_email(email, p, sent_at)   raw_email.set_content_type("text/html")   begin     PeopleMailer.deliver(raw_email)   rescue Exception => e     email.log += "\n" + format_time(Time.now) + "\n" + e.message + "\n"   end end

The problem is that generating the 500 individual emails takes a significant amount of time, which causes the browser to time out. What we want, is to give the user a response immidiately, and then process the sending of the email in the background.

How to go about this? I've seen the note about mass mailing on http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer, but I couldn't figure out whether it would work in situations where I want to send a customized email to each recipient.

I tried doing something like

Thread.start do   # everything as before end

...but the thread seems to quit as soon as the controller action is finished rendering, and no emails are sent.

Kind regards,

Erik

You may want to take a look at backgroundrb:

http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/b94003dc7ccc45f6/46a7b29d5e2d5d53

let me know what you find, as I'm doing the same thing right now (with about 200 users, and I'm doing it the naive way, which works, but I've been wanting to transition to a background process as well).

Mike

I don't know about running processes in the background, since our mailing list goes out from a cron job, but we do individualize emails, mainly for the point of putting in an "Unsubscribe" link for each user. Also, we found it was best to send the emails in slices of 50. That way the SMTP Session doesn't get way too big, but it cuts way down on sending time. Not sure if it's on the script side or the email server that slows it down(I think it's the email server because it's not caching the emails but I guess either way they have to sit around for a short while), but this sends about 6 emails/second. For 500 emails, that's...just under a minute and a half.

Here's the code:

This is in our main method in the model, Emailer.send_daily_announcements

@users.each_slice(50) do |recipient_group|           # Create an SMTP connection for this group of users       Net::SMTP.start('smtp.server.here', 25) do |smtp|               # Send the email to each user in this group         for recipient in recipient_group                                begin                         # Output each recipient - TESTING ONLY
            puts "Sending email to: #{recipient.email}"                       # Create the email message from our template             email = Emailer.create_daily_announcement(recipient, @other_variables)

            # Send out each email             smtp.sendmail email.encoded, email.from, email.to                     rescue Exception => e             exceptions[recipient] = e             logger.warn("EXCEPTION: EMAILER.ANNOUNCEMENTS:" + e)             puts e                         smtp.finish             smtp.start           end                   end               end           end

And our email creation method:

def daily_announcement(user, other_variables)

    # Email header info     @recipients = user.email     @from = "us"     @subject = "Daily Announcements"     @content_type = "text/html"         @body["user"] = user     @body["todays_events"] = todays_events     @body["other_stuff"] = other_stuff

  end

underbjerg wrote: