Built.io Blog

Changing SMTP Settings at Runtime in Your Rails App

,

Suppose you have multiple clients using your rails application, and you want to give your client the ability to set custom SMTP settings in the application while still defaulting to the original email settings when the custom SMTP setting fails.

You can do this by changing the settings of the ActionMailer, but as the settings are class level changes, they will cause an application wide change. This might also create issues when parallel calls will be received by your server. So how do you implement this properly?

I faced a similar issue, and found a workaround for this situation. I created a class in my initializers, which will act as the secondary mailer, if the SMTP settings are set by the client. Below is the code for that library:

<code>class MailSender
    def self.send_mail(smtp_settings, user, mail_subject, mail_body)
        options = {
            :address              => smtp_settings["address"],
            :domain               => smtp_settings["domain"],
            :port                 => smtp_settings["port"].to_i,
            :user_name            => smtp_settings["user_name"],
            :password             => smtp_settings["password"],
            :authentication       => smtp_settings["authentication"],
            :enable_starttls_auto => true,
            :openssl_verify_mode  => 'none'
        }
        Mail.defaults do

            delivery_method :smtp, options
        end

        mail = Mail.new do
            from      smtp_settings["user_name"]
            to        "#{user[:email]}"
            subject   mail_subject
            html_part do
                content_type 'text/html; charset=UTF-8'
                body mail_body
            end
        end

        mail.deliver!
    end
end
</code>

NOTE: Mail gem was utilized in the above code.

In the model where you delay your send email call, make the following changes:

<code>class User < ActiveRecord::Base
    before_create :send_activation_email

    def send_activation_email
        #.... Collect all your data
        send_mail(mail_template, settings, mail_body)
    end

    def send_mail(mail_template, settings, mail_body)
        smtp_settings = settings.smtp_settings

        if smtp_settings.blank?
            UserMailer.delay.activation_instructions(self, mail_template, mail_body)
        else
            MailSender.delay.send_mail(smtp_settings, self, mail_template["subject"], mail_body)
        end
    end
end
</code>

That's all! This allows you to send emails from dynamic SMTP servers whenever you like.

You can find the above code on GitHub.

Subscribe to our blog