Как получить message_id для почты с помощью delivery_later(sidekiq)

Я хочу SMTP message_id сообщения с использованием delivery_later(sidekiq).

Я могу получить идентификатор в обратном объекте файла delivery_now, но не в поле delivery_later.

Message_id также отсутствует в возвращаемом значении функции mail() внутри my_action_mailer

  • когда я отправляю почту используя

sent_mail = some_mail().deliver_later

ответ является объектом задания sidekiq, который выглядит следующим образом:

#<ActionMailer::DeliveryJob:0x007fefa1454780 @arguments=["xxxxxxx", "xxxxxxx", "deliver_now", xxxxxxx], @job_id="69b13253-55f9-4db9-a10a-0e8e4b998584", @queue_name="mailers", @priority=nil, @executions=0, @provider_job_id="6f75131d0c485534322cd728">
  • когда я отправляю почту, используя -

sent_mail = some_mail().deliver_now

ответ - объектный объект, который выглядит следующим образом

<Mail::Message:xx, Multipart: true, Headers: <Date: xx>, <From: "xx" <xx@xx.com>>, <Reply-To: "xx" <xx@xx.com>>, <To: ["xx@xx.com"]>, <Message-ID: <5a7863381167a_ba183fdfebc3f928907cb@xx-xx-xx.xx.mail>>, <Subject: xx>, <Mime-Version: 1.0>, <Content-Type: multipart/mixed; boundary="--==_mimepart_xx"; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>

Если вы внимательно посмотрите на приведенный выше вывод, классом возврата является Mail::Message, и он содержит "Message-ID", что мне и нужно.

  • Кроме того, когда мы вызываем функцию mail() внутри моего почтового класса, он также возвращает объект Mail::Message, но этот объект не содержит Message-ID, возвращенного с SMTP-сервера.

Есть ли способ, которым я могу получить идентификатор сообщения с использованием delivery_later

3 ответа

Это стандартный способ обработки этого случая:

перезаписать ActionMailer::DeliveryJob, что-то вроде этого:

      class EmailDeliveryJob < ActionMailer::DeliveryJob
  def perform(mailer, mail_method, delivery_method, *args)
    response = mailer.constantize.public_send(mail_method, *args).send(delivery_method)

    # Use response.message_id as you want
  end
end

В вашем почтовом ящике

      class UserMailer < ApplicationMailer
  self.delivery_job = EmailDeliveryJob

  def welcome_email(user)
    mail to: user.email, subject: "Welcome!"
  end
end

У меня была такая же проблема, но я решил использовать вместо нее Mailgun HTTPS API, но внутри задания Sidekiq.

Так я называю работу MailgunJob.perform_later(stuff_to_send)

И в работе

response = RestClient.post "https://mailgun_path", data
result = JSON.parse(response.body)
message_id = result['id']

Может быть, вы можете использовать работу, а внутри работу использовать deliver_now?

Если вы нашли лучшее решение, можете ли вы написать его здесь?

Одним из способов было бы использование наблюдателя ActionMailer .

Во-первых, добавьте идентификатор записи в сообщение почтовой программы с заголовком или#metadataатрибут:

      class YourMailer < ApplicationMailer

  def your_email(record)
    self.message['X-Your-Record-Id'] = record.id
    # or metadata['record_id'] = record.id

    ...
  end
end

Создайте наблюдателя:

      # app/models/custom_observer.rb

class CustomObserver
  def self.delivered_email(m)
    return unless m.delivered?

    # Access m.message_id or any header you want e.g. m['X-Your-Record-Id']
    Record.find(m['X-Your-Record-Id'].to_s).update_column(:message_id, m.message_id)
  end
end

Зарегистрируйте наблюдателя:

      # config/initializers/action_mailer.rb

ActionMailer::Base.register_observer(CustomObserver)

И вы можете идти. Это работает с#deliverи по сравнению с созданием пользовательскогоActionMailer::MailDeliveryJob(работает только с#deliver_later).

Другие вопросы по тегам