开发者

ActionMailer settings incorrectly differing between development and production

The Error

I've got my ActionMailer setup and working perfectly in development. I can call UserMailer.welcome(user).deliver, and the email reaches its destination. However, when I push my code into production and call the same deliver method, suddenly I get an error:

Errno::ECONNREFUSED: Connection refused - connect(2)
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:546:in `initialize'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:546:in `open'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:546:in `tcp_socket'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:555:in `block in do_start'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/timeout.rb:58:in `timeout'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/timeout.rb:89:in `timeout'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:555:in `do_start'
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/net/smtp.rb:525:in `start'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/gems/mail-2.3.0/lib/mail/network/delivery_methods/smtp.rb:128:in `deliver!'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/gems/mail-2.3.0/lib/mail/message.rb:1989:in `do_delivery'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/gems/mail-2.3.0/lib/mail/message.rb:230:in `block in deliver'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/actionmailer/lib/action_mailer/base.rb:414:in `block in deliver_mail'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/activesupport/lib/active_support/notifications.rb:55:in `block in instrument'
    from /webapps/myapp/production/shared/b开发者_Go百科undle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/activesupport/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/activesupport/lib/active_support/notifications.rb:55:in `instrument'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/actionmailer/lib/action_mailer/base.rb:412:in `deliver_mail'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/gems/mail-2.3.0/lib/mail/message.rb:230:in `deliver'
    from (irb):10
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/railties/lib/rails/commands/console.rb:45:in `start'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/railties/lib/rails/commands/console.rb:8:in `start'
    from /webapps/myapp/production/shared/bundle/ruby/1.9.1/bundler/gems/rails-5680a51dcbaf/railties/lib/rails/commands.rb:40:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

The Problem Thus Far

Probably the most valuable info I can offer is that the actual delivery_method data on the Message object is incorrect in production. In development, when I call UserMailer.welcome(user).delivery_method, the (formatted) output is:

#<Mail::SMTP:0x000001042c4a20 @settings={
  :address=>"smtp.gmail.com",
  :port=>587,
  :domain=>"foobar.com",
  :user_name=>"example@foobar.com",
  :password=>"MY_PASSWORD",
  :authentication=>"plain",
  :enable_starttls_auto=>true,
  :openssl_verify_mode=>nil}>

This clearly matches the settings I've defined in mailers.yml. In production, when I make the same call, the output is:

#<Mail::SMTP:0xbfb2c18 @settings={
  :address=>"localhost",
  :port=>25,
  :domain=>"localhost.localdomain",
  :user_name=>nil,
  :password=>nil,
  :authentication=>nil,
  :enable_starttls_auto=>true,
  :openssl_verify_mode=>nil}>

This just appears to be the defaults as defined on line 22 of ActionMailer::DeliveryMethods instead of my own settings from mailers.yml.

Relevant Code

As far as I can tell, my environments should have ActionMailer setup the same.

config/environment.rb:

Myapp::Application.config.action_mailer.delivery_method = :smtp
Myapp::Application.config.action_mailer.smtp_settings = YAML.load_file(
    Rails.root.join('config', 'mailers.yml'))[Rails.env].to_options

config/mailers.yml:

default: &default
  address:              smtp.gmail.com
  port:                 587
  domain:               foobar.com
  user_name:            example@foobar.com
  password:             MY_PASSWORD
  authentication:       plain
  enable_starttls_auto: true

development:
  <<: *default

production:
  <<: *default

config/environments/development.rb:

Myapp::Application.configure do
  # ...
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }
  config.action_mailer.interceptors = ['MailInterceptor']
  # ...
end

config/environments/production.rb:

Myapp::Application.configure do
  # ...
  config.action_mailer.default_url_options = { :host => 'foobar.com' }
  # ...
end

Note that I've also tried commenting out the two extra lines in development.rb (and tried adding them into production.rb) with no change -- I still get the same error in production, but not development.

Also, although I don't think it's relevant, I'll include MailIntercepter that I reference in development.rb (it's just to redirect all mail to my email address instead of test users' email addresses):

class MailInterceptor
  def self.delivering_email(message)
    message.subject = "[#{message.to}] #{message.subject}"
    message.to = "example+catcher@foobar.com"
  end
end


Figured it out, though it seems to go against what I thought was supposed to be the standard approach to Rails 3.1 config.

Changed this line:

Myapp::Application.config.action_mailer.smtp_settings = YAML.load_file(
    Rails.root.join('config', 'mailers.yml'))[Rails.env].try(:to_options)

To this:

ActionMailer::Base.smtp_settings = YAML.load_file(
    Rails.root.join('config', 'mailers.yml'))[Rails.env].try(:to_options)

Still not sure why the former works in development but not production, but the latter now works for me in production, so it's what I'm going with for now.


By any chance do you have your environment.rb set up like:

Myapp::Application.initialize!
Myapp::Application.configure do { }

If so, swap these two lines. I had nearly the same issue (mailer config worked in dev, not in other environments) and that was the problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜