5
votes

Spent yesterday and this morning trying to figure out what's going on. I've got a simple Rails 5 app successfully sending emails using sendgrid from the development rails console but attempting the same thing in heroku deployed production rails console doesn't send email but generates the following error:

Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25
from (irb):1

More details:

  • ruby 2.3.3
  • rails 5.1.3
  • gem 'sendgrid-ruby', '~> 5.0'

config/environment.rb

# Load the Rails application.
require_relative 'application'                                

# Initialize the Rails application.                           
Rails.application.initialize!                                 

Invoicer::Application.configure do 
  # Setup the mailer config                                   
  config.action_mailer.delivery_method = :smtp                
  config.action_mailer.perform_deliveries = true              
  config.action_mailer.smtp_settings = {
    :user_name => ENV['SENDGRID_USERNAME'],                   
    :password => ENV['SENDGRID_PASSWORD'],                    
    :domain => '[myapp].herokuapp.com',
    :address => 'smtp.sendgrid.net',                          
    :port => 587,
    :authentication => :plain,                                
    :enable_starttls_auto => true    
  }
end

config/environments/development.rb

The only email related not commented code is:

# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false

config.action_mailer.perform_caching = false

config/environments/production.rb

The only email related line not commented is:

config.action_mailer.perform_caching = false

In development on my local machine an email is generated.

In Development Rails Console:

>> ActionMailer::Base.delivery_method
=> :smtp
>> InvoiceMailer.invoice_email(Customer.first).delivery_method
  Customer Load (0.6ms)  SELECT  "customers".* FROM "customers" ORDER BY "customers"."id" ASC LIMIT $1  [["LIMIT", 1]]
  Rendering invoice_mailer/invoice_email.html.erb within layouts/mailer
  Rendered invoice_mailer/invoice_email.html.erb within layouts/mailer (0.0ms)
  Rendering invoice_mailer/invoice_email.text.erb within layouts/mailer
  Rendered invoice_mailer/invoice_email.text.erb within layouts/mailer (0.0ms)
InvoiceMailer#invoice_email: processed outbound mail in 17.6ms
=> #<Mail::SMTP:0x007f939b607b48 @settings=    {:address=>"smtp.sendgrid.net", :port=>587, :domain=>"fm-    invoicer.herokuapp.com", :user_name=>"[email protected]", :password=>"ms9nps8r7677", :authentication=>:plain, :enable_starttls_auto=>true, :openssl_verify_mode=>nil, :ssl=>nil, :tls=>nil}>

Heroku production no email is sent and I get an error.

In the heroku rails console

$ heroku run rails c
Loading production environment (Rails 5.1.3)
irb(main):001:0> InvoiceMailer.invoice_email(Customer.first).deliver
D, [2017-09-03T14:59:53.803069 #4] DEBUG -- :Customer Load (7.2ms)      SELECT  "customers".* FROM "customers" ORDER BY "customers"."id" ASC LIMIT     $1  [["LIMIT", 1]]
I, [2017-09-03T14:59:53.863967 #4]  INFO -- :Rendering     invoice_mailer/invoice_email.html.erb within layouts/mailer
I, [2017-09-03T14:59:53.864680 #4]  INFO -- :Rendered invoice_mailer/invoice_email.html.erb within layouts/mailer (0.6ms)
I, [2017-09-03T14:59:53.865742 #4]  INFO -- :Rendering invoice_mailer/invoice_email.text.erb within layouts/mailer
I, [2017-09-03T14:59:53.866329 #4]  INFO -- :Rendered invoice_mailer/invoice_email.text.erb within layouts/mailer (0.4ms)
D, [2017-09-03T14:59:54.087932 #4] DEBUG -- : InvoiceMailer#invoice_email: processed outbound mail in 232.7ms
I, [2017-09-03T14:59:54.101584 #4]  INFO -- : Sent mail to [email protected] (13.4ms)
D, [2017-09-03T14:59:54.102047 #4] DEBUG -- : Date: Sun, 03 Sep 2017 14:59:54 +0000
From: [email protected]
To: [email protected]
Message-ID: <59ac18ea16bd6_451d0d888799@f74404ed-7ea9-41ff-9b05-715d2a185bf4.mail>
Subject: XXXXX Website Monthly Invoice - August-2017
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_59ac18ea151a7_451d0d8886dd";
 charset=UTF-8
Content-Transfer-Encoding: 7bit


----==_mimepart_59ac18ea151a7_451d0d8886dd
Content-Type: text/plain; 
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Dear XXX

Attached please find your monthly invoice.

Best,
XXX
CrazyJ Media ;-)


----==_mimepart_59ac18ea151a7_451d0d8886dd
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style>
      /* Email styles need to be inline */
    </style>
  </head>

  <body>
    <!DOCTYPE html>
<html>
  <head>
    <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
  </head>
  <body>
    <p>Dear XXX,</p>
    <p>Attached please find the latest monthly invoice.</p>
    <p>Best,<br>XXX<br>Crazy J Media</p>
  </body>
</html>

  </body>
</html>

----==_mimepart_59ac18ea151a7_451d0d8886dd--

Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 25
    from (irb):1

Also in Heroku Rails Console:

irb(main):001:0> ActionMailer::Base.delivery_method
=> :smtp
irb(main):002:0>     InvoiceMailer.invoice_email(Customer.first).delivery_method
D, [2017-09-13T22:42:58.951166 #4] DEBUG -- :   Customer Load (2.8ms)      SELECT  "customers".* FROM "customers" ORDER BY "customers"."id" ASC LIMIT     $1  [["LIMIT", 1]]
I, [2017-09-13T22:42:59.037206 #4]  INFO -- :   Rendering     invoice_mailer/invoice_email.html.erb within layouts/mailer
I, [2017-09-13T22:42:59.038316 #4]  INFO -- :   Rendered     invoice_mailer/invoice_email.html.erb within layouts/mailer (0.9ms)
I, [2017-09-13T22:42:59.039720 #4]  INFO -- :   Rendering  invoice_mailer/invoice_email.text.erb within layouts/mailer
I, [2017-09-13T22:42:59.040359 #4]  INFO -- :   Rendered invoice_mailer/invoice_email.text.erb within layouts/mailer (0.5ms)
D, [2017-09-13T22:42:59.413839 #4] DEBUG -- :     InvoiceMailer#invoice_email: processed outbound mail in 405.7ms
=> #<Mail::SMTP:0x0000000575c678 @settings={:address=>"localhost",   :port=>25, :domain=>"localhost.localdomain", :user_name=>nil, :password=>nil, :authentication=>nil, :enable_starttls_auto=>true, :openssl_verify_mode=>nil, :ssl=>nil, :tls=>nil}>

Anyone have any ideas? I've studied Heroku's sendgrid ruby docs as well as several SO questions and answers like this one but to no avail. I've restarted my heroku server and my sendgrid account linked to this app is working and recording email sent from development.

Much positive karma being sent in advance to anyone with any insight!

2
Ok just to make sure, you set the sendgrid variables in your heroku dashboard? - Rockwell Rice
Pretty sure, @RockwellRice. The heroku sendgrid add-on is associated with that app, has stored username and pw credentials. I'm able to access my app's sendgrid dashboard though the app's heroku dashboard. - BenU
Did you add config.action_mailer.default_url_options = { :host => 'localhost:3000' } in dev and config.action_mailer.default_url_options = { :host => 'myapp.herokuapp.com' } in production? It's just a wild guess though. - Kruupös
You can run ActionMailer::Base.delivery_method and ActionMailer::Base.smtp_settings to verify your settings. If they are ok, inspect settings on email instance InvoiceMailer.invoice_email(Customer.first).delivery_method. And you can update your question with the results. - Michał Młoźniak
Thanks, @MichałMłoźniak, I've updated my question with that info. Will try the other suggestions now, too. - BenU

2 Answers

3
votes

The error shows that it's configured to send email using the SMTP server at localhost port 25, which would indicate that your config isn't being used!

When Rails.application.initialize! runs in production, ActionMailer is eager-loaded and configured with the settings it has been given at that moment. In your case it looks like that means it's using default values, as your own config isn't set until later.

You can resolve this by simply setting the config before initializing the app; either re-order your environment.rb so that config happens first, or move the ActionMailer config to application.rb or an environment-specific config (environments/production.rb, for example).

1
votes

Probably you should move the Action Mailer configs to config/environments/production.rb and/or check if nothing is overriding your settings inside this file.