Topic: Problems using ar_mailer (mass mailing in rails)

For sending out bulk emails I have used the ar_mailer in rails. I created an email.rb in my app/models

class Email < ActionMailer::ARMailer
    def newsletter(mail_info)
        # Email header info MUST be added here
        @recipients = "xxx@gmail.com"
        @from = mail_info["to_address"]
        @subject = "Newsletter"
        @headers["reply-to"] = "xxx@yy.com"
        content_type "text/html"

        # Email body substitutions go here
        @body["mail_info"] = mail_info
    end
end


From my controller I pass the mail as
Email.deliver_newsletter(mail_info)

I have changed the config/environment.rb file to contain the line
ActionMailer::Base.delivery_method = :activerecord

While running the application I am getting an error
undefined method `create' for Email:Class

The mail is getting created as I checked the error log but before adding the contents to the emails table it is throwing the error.
Am I missing something here?
My emails table script just in case!
CREATE TABLE `emails` (
  `id` int(11) NOT NULL auto_increment,
  `from` varchar(256) default NULL,
  `to` varchar(256) default NULL,
  `last_send_attempt` int(11) default '0',
  `mail` longtext,
  `created_on` datetime default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Any help would be appreciated.
Thanks in advance.

Re: Problems using ar_mailer (mass mailing in rails)

As luck would have it, I just got done implementing ar_mailer functionality into an app I'm working on.

Your problem is that ar_mailer, by default, uses the Email class to interact with the email table it creates to store emails. So it's trying to use your Email < ActionMailer::ARMailer class to interact with the database and it's trying to call methods that are defined in ActiveRecord::Base.

It's a simple fix really. The easiest thing to do is just let ar_mailer work the way it wants to and rename your classes. You first should have a basic ActiveRecord class named email to interact with the email database table.

like so:

class Email < ActiveRecord::Base
# no need for any methods in here
# this is just the model to interact with the emails table
# and it gets all the methods it needs via ActiveRecord::Base
end

and then you'd create a separate model that inherit from ActionMailer::ARMailer (named something other than Email) with your email methods like so:

class NewsletterSender < ActionMailer::ARMailer
  def newsletter(mail_info)
    # Email header info MUST be added here
    @recipients = "xxx@gmail.com"
    @from = mail_info["to_address"]
    @subject = "Newsletter"
    @headers["reply-to"] = "xxx@yy.com"
    content_type "text/html"

    # Email body substitutions go here
    @body["mail_info"] = mail_info
  end
end


hope that makes sense.

.phil.

Re: Problems using ar_mailer (mass mailing in rails)

Hey thanks Phil that worked and saved my neck!. Any ways thanks for your prompt reply. One quick question though. Can I have part of my application send emails queued in the table emails and the other have sent mails directly.
Since I configured my environment.rb to

ActionMailer::Base.delivery_method = :activerecord

The methods that I send emails directly gives out an error stating undefined method as I have changed the environment.rb
from :smtp to :activerecord to send the queued mails

. Thanks in advance.

Re: Problems using ar_mailer (mass mailing in rails)

I just realized I posted a reply in my original thread instead of this one. So here's what I wrote over there.

-------

Well, I haven't tried it myself, but in theory I think it should be possible.

Glancing at the ar_mailer documentation (http://seattlerb.rubyforge.org/ar_mailer/), the ActionMailer::ARSendmail class exposes a public instance method named deliver which accepts a collection of email objects as it's only argument and then sends those emails using the SMTP settings you've set in your environment file. Basically, when you run the ar_sendmail command (either from cron or the command line or whatever) it I'm pretty sure it eventually calls the deliver method to do its dirty work.

So, you could have a callback (i.e. after_create) that would call the deliver method manually only on the emails you want to send immediately. Make sense? Be sure to send a collection of emails (even if the collection is only one email long) to the method, because that's what it expects -- it uses methods like Array#shift which will throw an error if called on something other than some sort of collection.

Anyway, I haven't actually tried this, I'm just theorizing here, so your mileage may vary. Let me know what you figure out, and if I get some free time I may dig a bit deeper and test what I've just suggested to you. Also, check out the documentation to see if it's of any help.

Re: Problems using ar_mailer (mass mailing in rails)

So should it be something like

@email = NewsletterSender.deliver_newsletter(mail_info)
ActionMailer::ARSendmail.run.deliver(@email)

This doesn't work and throws an exception
 NameError in AtpController#document_customization
uninitialized constant ActionMailer::ARSendmail

Can you please give me an example of how to use it. Thanks in advance.

And apart from that can you give me an example code of writing the cron job that executes a rake file?
I am using /lib/tasks/send_queued_emails.rake.

desc "Send queued emails"
task :send_queued_emails =>  :environment do
  Dir.chdir(RAILS_ROOT) # change working directory to rails app root soar_sendmail will work correctly
  ActionMailer::ARSendmail.run(['-o'])
end

Can any one tell me what is to come in the RAILS_ROOT is it my rails application name? and how to run the rake from the command prompt.
Please excuse me being so beginner. Thanks in advance.

Re: Problems using ar_mailer (mass mailing in rails)

Okay, here's the deal. I got to thinking about this, and there's very little reason to even use ar_mailer the times you don't want to. You should just fall back on ActionMailer to do it for you.

Here's what I mean.

ar_mailer saves messages to the database when you call, for instance, MyMailer.deliver_xxx. The only reason ar_mailer takes control is because your server settings tell it to when you set ActionMailer::Base.delivery_method = :activerecord. So, all you have to do to send email without saving it to the database first is temporarily change the delivery method.

# grab what the delivery_method is currently set to so you can change
# it back when your done and not ruffle any feathers
original_method = ActionMailer::Base.delivery_method

# set the delivery_method to :smtp or whatever other option you want to use
ActionMailer::Base.delivery_method = :smtp

# deliver that message of yours
NewsletterSender.deliver_my_message

# and put everything back like you found it so no one gets mad
ActionMailer::Base.delivery_method = original_method


That ought to work just fine, but I do wonder how brittle it would be...

The other option is to go about it similarly to how I first suggested. You would first have to create a collection of emails and then send that to the deliver method of ARSendmail. Try this:

class NewsletterSender < ActionMailer::ARMailer
  def newsletter(mail_info)
     # Email header info MUST be added here
     @recipients = "xxx@gmail.com"
     @from = mail_info["to_address"]
     @subject = "Newsletter"
     @headers["reply-to"] = "xxx@yy.com"
     content_type "text/html"
 
     # Email body substitutions go here
     @body["mail_info"] = mail_info
   end

  def self.get_some_emails(mail)
    emails =[]
    mail.destinations.each do |destination|
      emails << @@email_class.new( :mail => mail.encoded, :to => destination,
                           :from => mail.from.first )
      end
    return emails
  end


Okay, that get_some_emails method is just a tiny variation on the ARMailer#perform_delivery_activerecord method, so it uses the @@email_class variable defined in ARMailer, so this method should be in your class that inherits from ActionMailer::ARMailer to have access to that variable. Anyway, here's how you would send an email immediately, skipping the database.

# compile your TMail objects
tmails = NewsletterSender.create_newsletter

# this will return an array of Email objects which can
# then be sent to the ARSendmail deliver method
emails = NewsletterSender.get_some_emails

# deliver those puppies
# note that deliver is an instance method so we must first
# instantiante an ARMailer object and then we can call deliver on it
ActionMailer::ARMailer.new.deliver(emails)


a lot of typing there, so I wouldn't be surprised if there's a typo in there somewhere, but I think you get the idea. Let me know if that helps.

Re: Problems using ar_mailer (mass mailing in rails)

Hey thanks man . I used the first option mentioned by you and it really worked well. Thanks a ton man.

Re: Problems using ar_mailer (mass mailing in rails)

Hi every body,

I'm trying to user ar_mailer with gmail, I have followed the  instructions given in this posts  and got the following error :

Unhandled exception 530 5.7.0 Must issue a STARTTLS command first a2sm2577290pyi
(Net::SMTPAuthenticationError):
        c:/ruby/lib/ruby/1.8/net/smtp.rb:577:in `auth_plain'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:571:in `__send__'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:571:in `authenticate'
        c:/ruby/lib/ruby/1.8/net/smtp.rb:411:in `do_start'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/smtp_tls.rb:29:in `send'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/smtp_tls.rb:29:in `start'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/smtp_tls.rb:19:in `start'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/action_mailer/ar_sendmail.rb:362:in `deliver'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/action_mailer/ar_sendmail.rb:443:in `run'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/action_mailer/ar_sendmail.rb:440:in `loop'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/action_mailer/ar_sendmail.rb:440:in `run'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/lib/action_mailer/ar_sendmail.rb:311:in `run'
        c:/ruby/lib/ruby/gems/1.8/gems/ar_mailer-1.2.0/bin/ar_sendmail:5
        c:/ruby/bin/ar_sendmail:18:in `load'
        c:/ruby/bin/ar_sendmail:18


To sum up here's what I have done :

* install ar_mailer 1.2

* create a model :

class Email < ActiveRecord::Base 
end

* create a mail notifier :
class UserNotifier < ActionMailer::ARMailer

  def send_to_friends(user, name, recipient, message)
    @recipients  = "#{recipient}"
    @from        = "#{user.email}"
    @sent_on     = Time.now
    @body[:url] = "http://#{SITE_URL}"
    @body[:recipient] = "#{recipient}"
    @body[:user] = user
    @body[:message] = "#{message}"
    @body[:name] = "#{name}"
  end

end


* in environment.rb :
require 'action_mailer/ar_mailer'

* in config/environments/development.rb :
require "smtp_tls"

ActionMailer::Base.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :authentication => :plain,
    :domain => "xxx.com",
    :user_name => "xxx@gmail.com",
    :password => 'xxx'
}

ActionMailer::Base.delivery_method = :activerecord


* add a template :

Hi <%= @recipient %> !

<% if !@message.nil? or @message.blank? -%>
<% if !@name.nil?  -%>
  <% @sender = "#{@name}(#{@user[:email]})"-%>
<% else -%>
<% @sender = "#{@user[:login]}(#{@user[:email]})"-%>
<% end-%>   
<%= @sender-%> have send you the following message :

"<%= @message-%>"
<% end -%>


* and finally call the send method in one  of my controllers:

 
UserNotifier.deliver_send_to_friends(current_user, params[:mail][:name], recipient, params[:mail][:message])

peburrows do you have any idea what's wrong ?

Tnaks so much in advance.

Addam

PS : I have also modified the file /lib/smtp_tls.rb such as indicated in http://blog.pomozov.info/posts/how-to-s … ilcom.html and works great without ar_mailer

Last edited by addam (2007-06-23 01:05:21)

Re: Problems using ar_mailer (mass mailing in rails)

Hi again !

I finally find the source of the previous error : the tls configuration I'm using is different of the one used by ar_mailer, ar_mailer is looking for an option : tls in the server sitting
(

ActionMailer::Base.smtp_settings[:tls]=true

).

I installed the plugin : ActionMailer TLS and added the option :tls=> true to my smtp server setting and the error is no longer here... mails sent like a charm


Great day everybody

Addam

Last edited by addam (2007-06-23 01:06:28)

Re: Problems using ar_mailer (mass mailing in rails)

I was having this exact problem and this solution worked great, it's now saving emails. One thing though where do I trap errors for empty email fields from a form?

Last edited by cherring (2007-12-11 00:01:08)

Re: Problems using ar_mailer (mass mailing in rails)

Hey everybody, great discussion, and excellent solution peburrows. I attempted using it in my app, but the only way I can seem to get ar_mailer to queue all of my emails (around a thousand of'em) is to add everyone to the BCC list and call the deliver_mailing(recipients) method *once* # where recipients gets converted to the bcc list #

I hate doing this, and I figure there will be spam issues, or server rejection issues. If i try to loop over all of the email addresses though, and do a deliver_mailing(recipient) on each one, eventually it dies on itself with the following error:

-----------
undefined method `perform_delivery_activerecord' for #<ExceptionNotifier:0x2aaab1aa9110>
[RAILS_ROOT]/vendor/rails/actionmailer/lib/action_mailer/base.rb:469:in `__send__'
-----------

Anyone have any ideas or best practices as to actually delivering these to a ton of people? Every doc or tutorial I've come across skips that part sad