15

我看到了这篇文章,但我的略有不同:

带有多个 SMTP 服务器的 Rails ActionMailer

我允许用户使用他们自己的 SMTP 凭证发送邮件,所以它确实来自他们。

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

我怎样才能做到这一点?

4

6 回答 6

61

做另一个答案中描述的事情是不安全的;您在这里设置类变量,而不是实例化变量。如果你的 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}
于 2011-06-20T15:26:44.143 回答
12

这是我根据之前的答案和评论提出的解决方案。这使用了一个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
于 2013-02-01T20:15:48.660 回答
9

对于 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
于 2013-07-08T02:06:29.873 回答
4

由于 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 指南)

于 2018-10-22T13:05:27.723 回答
3

只需在每个发送操作之前设置 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 = ..
于 2010-04-18T20:31:39.657 回答
3

如果有人需要动态设置传递方法和 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
于 2015-02-02T10:40:38.697 回答