使用 HTTP 协议(​​MailGun API)在 Rails 中发送电子邮件

Sending emails in Rails using HTTP protocol(MailGun API)

我正在尝试使用 MailGun ruby sdk(https://github.com/mailgun/mailgun-ruby/blob/master/docs/MessageBuilder.md) 使用 MailGun 的批量发送 API 发送电子邮件。截至目前,我在继承自 ActionMailer 的 class 中拥有此方法。

class BatchMailer < ApplicationMailer
  def send_batch_email(mail, recipients)

    # First, instantiate the Mailgun Client with your API key
    mg_client = Mailgun::Client.new("your-api-key")

    # Create a Batch Message object, pass in the client and your domain.
    mb_obj = Mailgun::BatchMessage.new(mg_client, "example.com")

    # Define the from address.
    mb_obj.from("me@example.com", {"first" => "Ruby", "last" => "SDK"});

    # Define the subject.
    mb_obj.subject("A message from the Ruby SDK using Message Builder!");

    # Define the body of the message.
    mb_obj.body_text("This is the text body of the message!");


    # Loop through all of your recipients
    mb_obj.add_recipient(:to, "john.doe@example.com", {"first" => "John", "last" => "Doe"});
    mb_obj.add_recipient(:to, "jane.doe@example.com", {"first" => "Jane", "last" => "Doe"});
    mb_obj.add_recipient(:to, "bob.doe@example.com", {"first" => "Bob", "last" => "Doe"});
    ...
    mb_obj.add_recipient(:to, "sally.doe@example.com", {"first" => "Sally", "last" => "Doe"});

    # Call finalize to get a list of message ids and totals.
    message_ids = mb_obj.finalize
    # {'id1234@example.com' => 1000, 'id5678@example.com' => 15}
  end
end

将不使用 actionmailer 发送电子邮件的方法保留在邮件程序中是否是正确的方法?

ActionMailer 方法 returns 邮件对象,但是在尝试为使用 API 发送电子邮件的方法编写规范时,我无法获得响应,因为没有邮件对象(ActionMailer 消息对象)。将此方法保存在哪里以及如何对其进行测试?

Is this a correct way to keep the method that doesn't use actionmailer to send emails inside mailer?

在这种情况下没有理由使用 Mailer。只需使用一个服务对象(一个普通的 ruby 对象或 PORO)。它可能看起来像:

class BatchMailerService

  attr_accessor *%w(
    mail 
    recipients
    recipient
  ).freeze

  delegate *%w(
    from
    subject
    body_text
    add_recipient
    finalize
  ), to: :mb_obj

  delegate *%w(
    address 
    first_name 
    last_name
  ), to: :recipient, prefix: true

    class << self 

      def call(mail, recipients)
        new(mail, recipients).call
      end

    end # Class Methods

  #==============================================================================================
  # Instance Methods
  #==============================================================================================

    def initialize(mail, recipients)
      @mail, @recipients = mail, recipients
    end

    def call
      setup_mail
      add_recipients
      message_ids = finalize
    end

  private 

    def mg_client
      @mg_client ||= Mailgun::Client.new(ENV["your-api-key"])
    end

    def mb_obj
      @mb_obj ||= Mailgun::BatchMessage.new(mg_client, "example.com")
    end

    def setup_mail
      from("me@example.com", {"first" => "Ruby", "last" => "SDK"})
      subject("A message from the Ruby SDK using Message Builder!")
      body_text("This is the text body of the message!")
    end

    def add_recipients
      recipients.each do |recipient|
        @recipient = recipient
        add_recipient(
          :to, 
          recipient_address, 
          {
            first:  recipient_first_name,
            last:   recipient_last_name
          }
        )
      end
    end

end

你会使用这样的东西:

BatchMailerService.call(mail, recipients)

(当然,假设您有名为 mailrecipients 的变量)。

Where to keep this method?

您可以将该文件放在 app/services/batch_mailer_service.rb

How can it be tested?

你是什么意思?如何测试服务取决于您的成功标准。您可以测试 mb_obj 是否收到 finalize 调用(可能使用类似 expect().to receive 的方法)。您可以测试 message_ids 是否包含正确的信息(可能使用类似 expect().to include 的内容)。这有点取决于。