Using an ActiveRecord class method within an ActionMailer object

This is a little convoluted and I'm new to Rails, so please bear with me...

My application needs to receive both SMS and emails. I have a controller that has a sms_in method, which receives SMS messages via a HTTP POST request from an SMS gateway. That controller then calls the IncomingMessage.process(args) method to go through a number of validations and create the incoming message in the database as well as various other database entries that are required with each incoming message. This works fine.

However, I'm having trouble getting it to work for emails. In my MailProcessor (ActionMailer) receive method, I'm trying to pass similar arguments to the IncomingMessage.process(args) class method. However, for some reason this isn't working...I can't seem to call a class method for an ActiveRecord object from within the ActionMailer object, and I have no idea why!

Any help would be greatly appreciated! -Gavin

This is a little convoluted and I'm new to Rails, so please bear with me...

My application needs to receive both SMS and emails. I have a controller that has a sms_in method, which receives SMS messages via a HTTP POST request from an SMS gateway. That controller then calls the IncomingMessage.process(args) method to go through a number of validations and create the incoming message in the database as well as various other database entries that are required with each incoming message. This works fine.

However, I'm having trouble getting it to work for emails. In my MailProcessor (ActionMailer) receive method, I'm trying to pass similar arguments to the IncomingMessage.process(args) class method. However, for some reason this isn't working...I can't seem to call a class method for an ActiveRecord object from within the ActionMailer object, and I have no idea why!

That should work. Show what you're doing (and describe what you
actually mean by "isn't working")

Fred

I'm using the Fetcher plugin which daemonizes polling the server for emails. When it pulls in an email, it passes it (the Net::Imap object) to the receive method of MailProcessor < ActionMailer::Base. The receive method then calls the process_message class method of IncomingMessage < ActiveRecord::Base, which should store the incoming message to the database as well as do a number of other things. However, this method does not seem to be getting executed for incoming emails. On the other hand, when this method is called from the controller containing the sms_in action, the message gets processed/ stored correctly. These are the methods in question:

class MailProcessor < ActionMailer::Base def receive(mail)       IncomingMessage.process_message({ :sender => mail.from,               :subject => mail.subject,               :channel => "email",               :person_search_field => "email",               :date => mail.date,               :body => mail.body,               :delivery_point => mail.to }) end

class MessengerController < ApplicationController   def sms_in     @incoming_message, @opt_or_feedback_object,@processing_notes =     IncomingMessage.process_message({ :sender => params[:smsfrom],               :subject => params[:smsmsg],               :channel => "sms",               :gateway_id => params[:smsid],               :person_search_field => "mobile_phone",               :date => params[:smsdate],               :carrier => params[:network],               :delivery_point => params[:smsto] })   end

class IncomingMessage < ActiveRecord::Base protected   def self.process_message(msg_hash)     @incoming_message = create_incoming_message      #more code to process the message...I didn't paste it here because it calls      #a number of other class methods and they would be too much to paste   end

  def self.create_incoming_message     IncomingMessage.create(:subject => @msg_hash[:subject],       :person_id => "#{@person.id}",       :body => @msg_hash[:body],       :channel => @msg_hash[:channel],       :gateway_id => @msg_hash[:gateway_id],       :carrier => @msg_hash[:carrier],       :date => @msg_hash[:date],       :delivery_point_id => @delivery_point_id)   end

Anybody know why this isn't working for me?

Well you haven't said exactly what is happening, eg if you put a breakpoint in create_incoming_message is it hit? have you tried stepping through the code and seeing when it fails? Could it be that creation of the incoming_message fails because of validation? Do you really mean to be creating class instance variables ?

Fred

When you ask if I really mean to be creating class instance variables, I assume you're referring to @incoming_message, @opt_or_feedback_object, @processing_notes = IncomingMessage.process_message()...correct? The reason I set class instance variables is because the view for this action needs to display details from the incoming message, the object created from the the incoming message, and the notes that are generated during processing (including the validation results mostly). I didn't paste the last line of the IncomingMessage.process_message() method above, but FYI it is "return @incoming_message,@opt_or_feedback_object,@processed_msg_array[0]".

No, the reason is not that it's failing because of validations within the IncomingMessage.process_message() method, because the terminal window shows now SQL being executed, and also there are items persisted to the DB regardless of whether validation succeeds or fails. I took your tip and used breakpoints to see what's happening here (this is my first Rails app and I stupidly didn't think to look into the Rails debug tools). When a SMS comes in, the breakpoint at the start of the IncomingMessage.process_message() method is hit. However, when an email comes in, not breakpoints are hit, regardless of where they are. I.e. in the MailProcesser.receive() method, I put the following 2 lines: 1 puts "debug" 2 debugger The terminal window where I executed the script displays "debug", but processing does not stop at the breakpoint.

This might help...it's the fetcher script that is daemonized (and I can post more of the code from the Fetcher plugin if you think that it'd be helpful):

#!/usr/bin/env ruby require File.dirname(__FILE__) + '/../config/environment.rb'

class MailFetcherDaemon < Daemon::Base

  @config = YAML.load_file("#{RAILS_ROOT}/config/mail.yml")   @config = @config[RAILS_ENV].to_options

  @sleep_time = @config.delete(:sleep_time) || 60   def self.start     puts "Starting MailFetcherDaemon"     @fetcher = Fetcher.create({:receiver => MailProcessor}.merge(@config))

    loop do       @fetcher.fetch       sleep(@sleep_time)     end   end

  def self.stop     puts "Stopping MailFetcherDaemon"   end

end

MailFetcherDaemon.daemonize

Thanks for your help! -Gavin

What SMS gateway are you using if you don't mind me asking? Is it open source or are you paying per message?

We are using a shared shortcode provided by another company, so nope it's not open source. As far as I'm aware, open source SMS gateways such as Kannel still require that you have a shortcode leased and registered with the various carriers, which is really expensive. There's really doesn't seem to be any way to avoid a per-message cost for outgoing messages (many mobile gateway providers don't charge for incoming messages).

David wrote:

I have installed and am using SMS-Fu: http://brendanlim.com/2008/2/28/send-text-messages-from-rails-with-sms-fu, which appears to be free to send sms messages. Maybe there is a limit with this, I am not sure, I read somewhere 500 max in any given 3 day period but maybe it varies for different carriers? What I would really like is to be able to receive SMS for free, but it doesnt look like its in the cards.