Rails ActionMailer with multiple SMTP servers

前端 未结 11 1051
一整个雨季
一整个雨季 2020-12-13 06:19

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_settin

相关标签:
11条回答
  • 2020-12-13 07:12

    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
    
    0 讨论(0)
  • 2020-12-13 07:14

    Based on the Oreilly article, I came up with the solution I wrote about here: http://transfs.com/devblog/2009/12/03/custom-smtp-settings-for-a-specific-actionmailer-subclass

    Here's the relevant code:

    class MailerWithCustomSmtp < ActionMailer::Base
      SMTP_SETTINGS = {
        :address => "smtp.gmail.com",
        :port => 587,
        :authentication => :plain,
        :user_name => "custom_account@transfs.com",
        :password => 'password',
      }
    
      def awesome_email(bidder, options={})
         with_custom_smtp_settings do
            subject       'Awesome Email D00D!'
            recipients    'someone@test.com'
            from          'custom_reply_to@transfs.com'
            body          'Hope this works...'
         end
      end
    
      # Override the deliver! method so that we can reset our custom smtp server settings
      def deliver!(mail = @mail)
        out = super
        reset_smtp_settings if @_temp_smtp_settings
        out
      end
    
      private
    
      def with_custom_smtp_settings(&block)
        @_temp_smtp_settings = @@smtp_settings
        @@smtp_settings = SMTP_SETTINGS
        yield
      end
    
      def reset_smtp_settings
        @@smtp_settings = @_temp_smtp_settings
        @_temp_smtp_settings = nil
      end
    end
    
    0 讨论(0)
  • 2020-12-13 07:15

    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

    0 讨论(0)
  • 2020-12-13 07:17

    Here's another solution, which, while it looks ridiculous, I think is a little bit cleaner and easier to reuse in different AM::Base classes:

        module FTTUtilities
          module ActionMailer
            module ClassMethods
              def smtp_settings
                dict = YAML.load_file(RAILS_ROOT + "/config/custom_mailers.yml")[self.name.underscore]
                @custom_smtp_settings ||= HashWithIndifferentAccess.new(dict)
              end
            end
    
            module InstanceMethods
              def smtp_settings
                self.class.smtp_settings
              end
            end
          end
        end
    

    example Mailer:

        class CustomMailer < ActionMailer::Base
            extend FTTUtilites::ActionMailer::ClassMethods
            include FTTUtilites::ActionMailer::InstanceMethods
        end
    
    0 讨论(0)
  • 2020-12-13 07:22

    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
    
    0 讨论(0)
提交回复
热议问题