Question

I'm using the Cloudmailin addon to receive e-mail from my Heroku app. However, Cloudmailin has not been able to deliver - or, rather, it gets 500 from Heroku every time (so the address is correct).

The error in Heroku logs is

Started POST "/incoming_mails" for 109.107.35.53 at 2013-02-27 08:54:22 +0000
2013-02-27T08:54:23+00:00 app[web.1]: Entering the controller! Controlling the e-mail!
2013-02-27T08:54:23+00:00 app[web.1]: 
2013-02-27T08:54:23+00:00 app[web.1]: NoMethodError (undefined method `[]' for nil:NilClass):
2013-02-27T08:54:23+00:00 app[web.1]:   app/controllers/incoming_mails_controller.rb:7:in `create'

My routing is correct; the "Entering the controller! Controlling the e-mail!" comes from the puts at the beginning of the class, so the class definitely gets entered.

# routes.rb
post '/incoming_mails' => 'incoming_mails#create'

The file itself looks like this:

# /app/controllers/incoming_mails_controller.rb
class IncomingMailsController < ApplicationController
  skip_before_filter :verify_authenticity_token

  def create
    puts "Entering the controller! Controlling the e-mail!"
    Rails.logger.info params[:headers][:subject]
    Rails.logger.info params[:plain]
    Rails.logger.info params[:html]

    if User.all.map(&:email).include? params[:envelope][:from] # check if user is registered
      @thought = Thought.new
      @thought.body = params[:plain].split("\n").first
      @thought.user = User.where(:email => params[:envelope][:from])
      @thought.date = DateTime.now

      if @thought.save
        render :text => 'Success', :status => 200
      else
        render :text => 'Internal failure', :status => 501
      end
    else
      render :text => 'Unknown user', :status => 404 # 404 would reject the mail
    end
  end
end

User and Thought are database resources used elsewhere without a problem. The saving procedure is the same that works in scaffolding-generated Thought controller. The params and Rails.logger logic I copied from a Cloudmailin Rails 3 example.

I'm really confused - where am I going wrong? I'd really appreciate any pointers.

Was it helpful?

Solution

It turns out, this is why you shouldn't code while sleep-deprived. The problem was simple: there is no such thing as params[:envelope][:from], there is only params[:from]). My assumption that :from would be a sub-element of :envelope was probably formed by looking at the pattern in the second "Cloudmailin in Rails on Heroku" example, where a code used to log subject is Rails.logger.log params[:envelope][:subject].

I realized this was the error after reading the API documentation for 'original' Cloudmailin format. It was exceptionally silly of me not to have found / looked for this resource in the first place.

After fixing this, the code still didn't work, because User.where(:email => params[:from]) only returned a Relation object, while User object was expected. The error in Heroku logs was the following:

 ActiveRecord::AssociationTypeMismatch (User(#29025160) expected,
 got ActiveRecord::Relation(#12334440)):

Since there can only be one user with some e-mail, the fix User.where(:email => params[:from]).first has no side-effects and results in correct behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top