如何使用Actionmailer / Ruby on Rails发送具有多个动态smtp的电子邮件

我看过这个post但是我的略有不同:

Rails ActionMailer具有多个SMTP服务器

我允许用户使用自己的SMTP凭据发送邮件,因此它实际上来自他们。

但它们将从Rails应用程序发送,这意味着每个用户需要使用自己的SMTP服务器发送电子邮件。

我怎样才能做到这一点?

只需在每个发送操作之前设置ActionMailer :: Base配置值。

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 = .. 

做其他答案中描述的内容并不安全; 你在这里设置类变量,而不是实例变量。 如果您的Rails容器正在分叉,您可以执行此操作,但现在您的应用程序依赖于容器的实现细节。 如果你没有分配新的Ruby进程,那么你可以在这里遇到竞争条件。

你应该有一个扩展ActionMailer :: Base的模型,当你调用一个方法时,它将返回一个Mail :: Message对象。 这是您的实例对象,您应该更改设置。 设置也只是一个哈希值,因此您可以内联它。

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

在上面的mail_settings中返回一些带有适当键IE的哈希值

 {:user_name=>username, :password=>password} 

这是我根据之前的答案和评论提出的解决方案。 这使用ActionMailer拦截器类 。

 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 

对于Rails 3.2.x

您可以在邮件程序类中包含AbstractController :: Callbacks,并在邮件程序中执行“after_filter:set_delivery_options”。

set_delivery_options方法可以访问您在邮件程序操作中设置的实例变量,并且您可以将邮件对象作为“消息”进行访问。

 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 

如果有人需要与smtp凭证一起动态设置传递方法,你可以使用Mail :: Message实例方法设置传递方法和它的变量,所以我的addapted Aditya Sanghi版本是:

 class MainMailer < ActionMailer::Base WHATEVER_CONDITION = true # example only fe @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 

从Rails 4+开始,它可以直接通过delivery_method_options参数提供凭据:

 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 

请参阅使用动态传送选项发送电子邮件(Rails指南)