How to send emails with multiple, dynamic smtp using Actionmailer/Ruby on Rails

后端 未结 6 1502
不知归路
不知归路 2020-12-04 18:40

I saw this post but mine is slightly different:

Rails ActionMailer with multiple SMTP servers

I am allowing the users to send mail using their own SMTP crede

相关标签:
6条回答
  • 2020-12-04 19:14

    Just set the ActionMailer::Base configuration values before each send action.

    smtp_config = user.smtp_configuration
    
    ActionMailer::Base.username = smtp_config.username
    ActionMailer::Base.password = smtp_config.password
    ActionMailer::Base.server = ..
    ActionMailer::Base.port = ..
    ActionMailer::Base.authentication = ..
    
    0 讨论(0)
  • 2020-12-04 19:18

    Doing what is described in the other answer is not safe; you are setting class variables here, not instanced variables. If your Rails container is forking, you can do this, but now your application is depending on an implementation detail of the container. If you're not forking a new Ruby process, then you can have a race condition here.

    You should have a model that is extending ActionMailer::Base, and when you call a method, it will return a Mail::Message object. That is your instance object and is where you should change your settings. The settings are also just a hash, so you can inline it.

    msg = MyMailer.some_message
    msg.delivery_method.settings.merge!(@user.mail_settings)
    msg.deliver
    

    Where in the above mail_settings returns some hash with appropriate keys IE

    {:user_name=>username, :password=>password}
    
    0 讨论(0)
  • 2020-12-04 19:32

    in case somebody needs to set delivery method dynamically together with smtp credentials, u can use Mail::Message instance method to set delivery method together with it's variables so my addapted Aditya Sanghi version is:

    class MainMailer < ActionMailer::Base
      WHATEVER_CONDITION = true # example only f.e. @ser
    
      include AbstractController::Callbacks
      after_filter :set_delivery_options
    
      private
      def set_delivery_options
        settings = {
        :address => 'smtp.mandrillapp.com', # intentionally
        :port => 587, # intentionally
        :domain => 'your_domain', #insetad of localhost.localdomain'
        :user_name => 'smtp_username',
        :password => 'smtp_password',
        :authentication => 'PLAIN' # or smthing else
    }
        if WHATEVER_CONDITION
          message.delivery_method(:smtp, settings)
        end
      end
    end
    
    0 讨论(0)
  • 2020-12-04 19:34

    For Rails 3.2.x

    You can include AbstractController::Callbacks in your mailer class and the do a "after_filter :set_delivery_options" inside the mailer.

    The set_delivery_options method would have access to instance variables setup by you in your mailer action and you can access the mail object as "message".

    class MyNailer < ActionMailer::Base
      include AbstractController::Callbacks
      after_filter :set_delivery_options
    
      def nail_it(user)
        @user = user
        mail :subject => "you nailed it"
      end
    
      private
    
      def set_delivery_options
        message.delivery_method.settings.merge!(@user.company.smtp_creds)
      end
    end
    
    0 讨论(0)
  • 2020-12-04 19:35

    Here is a solution that I came up with based on the previous answers and comments. This uses an ActionMailer interceptor class.

    class UserMailer < ActionMailer::Base
      default from: proc{ @user.mail_settings[:from_address] }      
    
      class DynamicSettingsInterceptor
         def self.delivering_email(message)
           message.delivery_method.settings.merge!(@user.mail_settings)
         end
       end
       register_interceptor DynamicSettingsInterceptor
    end
    
    0 讨论(0)
  • 2020-12-04 19:37

    Since Rails 4+ it works to give the credentials directly via the delivery_method_options parameter:

    class UserMailer < ApplicationMailer
      def welcome_email
        @user = params[:user]
        @url  = user_url(@user)
        delivery_options = { user_name: params[:company].smtp_user,
                             password: params[:company].smtp_password,
                             address: params[:company].smtp_host }
        mail(to: @user.email,
             subject: "Please see the Terms and Conditions attached",
             delivery_method_options: delivery_options)
      end
    end
    

    See Sending Emails with Dynamic Delivery Options (Rails Guides)

    0 讨论(0)
提交回复
热议问题