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

Tim*_* T. 14 smtp ruby-on-rails actionmailer

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

Rails ActionMailer具有多个SMTP服务器

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

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

我怎样才能做到这一点?

jca*_*ert 58

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

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

msg = MyMailer.some_message
msg.delivery_method.settings.merge!(@user.mail_settings)
msg.deliver
Run Code Online (Sandbox Code Playgroud)

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

{:user_name=>username, :password=>password}
Run Code Online (Sandbox Code Playgroud)

  • @AdityaSanghi提到的pull请求已合并到Rails 4+中,但在早期版本中不会修补. (8认同)
  • 请帮助将此PR合并到rails中.(https://github.com/rails/rails/pull/7397)这正是OP正在考虑的问题. (6认同)

Mit*_*tch 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
Run Code Online (Sandbox Code Playgroud)


Adi*_*ghi 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
Run Code Online (Sandbox Code Playgroud)


San*_*o L 7

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

\n\n
class UserMailer < ApplicationMailer\n  def welcome_email\n    @user = params[:user]\n    @url  = user_url(@user)\n    delivery_options = { user_name: params[:company].smtp_user,\n                         password: params[:company].smtp_password,\n                         address: params[:company].smtp_host }\n    mail(to: @user.email,\n         subject: "Please see the Terms and Conditions attached",\n         delivery_method_options: delivery_options)\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n


sim*_*rmy 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 = ..
Run Code Online (Sandbox Code Playgroud)

  • 同意,您应该将 jcalvert 的答案重新标记为正确 - 所选答案是危险的 (3认同)
  • 所以我刚刚丢失了之前的答案,所以用更短的笔记再试一次。您只需在这些调用中设置 ActionMailer 类变量。通常它们是在配置中定义的,但您可以随时更改它们。在您的情况下,您希望在需要调用的每个 ActionMailer 子类的 Deliver_XXX 方法之前设置它们。 (2认同)