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

时间:2010-04-18 15:34:12

标签: ruby-on-rails smtp actionmailer

我看过这篇文章,但我的情况略有不同:

Rails ActionMailer with multiple SMTP servers

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

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

我该怎么做?

6 个答案:

答案 0 :(得分:58)

执行其他答案中描述的内容并不安全;你在这里设置类变量,而不是实例变量。如果您的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}

答案 1 :(得分:12)

这是我根据之前的答案和评论提出的解决方案。这使用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

答案 2 :(得分: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

答案 3 :(得分: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 = ..

答案 4 :(得分:3)

如果某人需要动态设置传递方法和smtp凭据,您可以使用Mail::Message instance method将传递方法与其变量一起设置,以便我的addapted 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

答案 5 :(得分:0)

从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

请参见Sending Emails with Dynamic Delivery Options (Rails Guides)