Rails ActionMailer with multiple SMTP servers

2019-01-21 19:41发布

I have a need to use two different smtp servers in a Rails application. It appears that the way ActionMailer is constructed, it is not possible to have different smtp_settings for a subclass. I could reload the smtp settings for each mailer class whenever a message is being sent, but that messes up the ExceptionNotifier plugin which is outside my control (unless I mess with it too). Does anyone have a solution/plugin for something like this?

Ideally I would like to have

class UserMailer < ActionMailer::Base; end

and then set in environment.rb

ActionMailer::Base.smtp_settings = standard_smtp_settings
UserMailer.smtp_settings = user_smtp_settings

Thus, most of my mailers including ExceptionNotifier would pickup the default settings, but the UserMailer would use a paid relay service.

11条回答
爷的心禁止访问
2楼-- · 2019-01-21 20:13

Solution for Rails 4.2+:

config/secrets.yml:

production:
  gmail_smtp:
    :authentication: "plain"
    :address: "smtp.gmail.com"
    :port: 587
    :domain: "zzz.com"
    :user_name: "zzz@zzz.com"
    :password: "zzz"
    :enable_starttls_auto: true
  mandrill_smtp:
    :authentication: "plain"
    :address: "smtp.mandrillapp.com"
    :port: 587
    :domain: "zzz.com"
    :user_name: "zzz@zzz.com"
    :password: "zzz"
    :enable_starttls_auto: true
  mailgun_smtp:
    :authentication: "plain"
    :address: "smtp.mailgun.org"
    :port: 587
    :domain: "zzz.com"
    :user_name: "zzz@zzz.com"
    :password: "zzz"
    :enable_starttls_auto: true

config/environments/production.rb:

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = Rails.application.secrets.gmail_smtp

app/mailers/application_mailer.rb:

class ApplicationMailer < ActionMailer::Base
  default from: '"ZZZ" <zzz@zzz.com>'

  private

  def gmail_delivery
    mail.delivery_method.settings = Rails.application.secrets.gmail_smtp
  end

  def mandrill_delivery
    mail.delivery_method.settings = Rails.application.secrets.mandrill_smtp
  end

  def mailgun_delivery
    mail.delivery_method.settings = Rails.application.secrets.mailgun_smtp
  end
end

app/mailers/user_mailer.rb:

class UserMailer < ApplicationMailer
  # after_action :gmail_delivery, only: [:notify_user]
  after_action :mandrill_delivery, only: [:newsletter]
  after_action :mailgun_delivery, only: [:newsletter2]

  def newsletter(user_id); '...' end # this will be sent through mandrill smtp
  def newsletter2(user_id); '...' end # this will be sent through mailgun smtp
  def notify_user(user_id); '...' end # this will be sent through gmail smtp
end
查看更多
Evening l夕情丶
3楼-- · 2019-01-21 20:15

When I wanted a quick test in the console (Rails 5) I did the following:

settings = { username: "" } # etc
mailer = MyMailer.some_method
mailer.delivery_method.settings.merge!(settings)
mailer.deliver
查看更多
霸刀☆藐视天下
4楼-- · 2019-01-21 20:16

https://github.com/AnthonyCaliendo/action_mailer_callbacks

I found this plugin helped solve the problem for me pretty easily (as in < 5 mins). I simply change the @@smtp_settings for a particular mailer in the before_deliver and then change it back to the defaults in the after_deliver. Using this approach, I only have to add the callbacks to mailers that need @@smtp_settings different than the default.

class CustomMailer < ActionMailer::Base

  before_deliver do |mail|
    self.smtp_settings = custom_settings
  end

  after_deliver do |mail|
    self.smtp_settings = default_settings
  end

  def some_message
    subject "blah"
    recipients "blah@blah.com"
    from "ruby.ninja@ninjaness.com"
    body "You can haz Ninja rb skillz!"
    attachment some_doc
  end

end
查看更多
疯言疯语
5楼-- · 2019-01-21 20:18

For anybody approaching this issue with later versions (3+) of Rails, try this

http://guides.rubyonrails.org/action_mailer_basics.html#sending-emails-with-dynamic-delivery-options

查看更多
Anthone
6楼-- · 2019-01-21 20:20

I'm afraid it's not doable natively.
But you can trick it a bit by modifying the @@smtp_settings variable in the model.

There's an article on Oreilly which explains it pretty well even though they code is not clean at all. http://broadcast.oreilly.com/2009/03/using-multiple-smtp-accounts-w.html

查看更多
登录 后发表回答