Как получить 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
).