我看到了这篇文章,但我的略有不同:
带有多个 SMTP 服务器的 Rails ActionMailer
我允许用户使用他们自己的 SMTP 凭证发送邮件,所以它确实来自他们。
但它们将从 Rails 应用程序发送,这意味着对于每个用户,我需要使用他们自己的 SMTP 服务器发送他们的电子邮件。
我怎样才能做到这一点?
我看到了这篇文章,但我的略有不同:
带有多个 SMTP 服务器的 Rails ActionMailer
我允许用户使用他们自己的 SMTP 凭证发送邮件,所以它确实来自他们。
但它们将从 Rails 应用程序发送,这意味着对于每个用户,我需要使用他们自己的 SMTP 服务器发送他们的电子邮件。
我怎样才能做到这一点?
做另一个答案中描述的事情是不安全的;您在这里设置类变量,而不是实例化变量。如果你的 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
由于 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
只需在每个发送操作之前设置 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 = ..
如果有人需要动态设置传递方法和 smtp 凭据,你可以使用 Mail::Message 实例方法来设置传递方法及其变量,所以我添加的Aditya Sanghi版本是:
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