fix: email delivery in Email::SendOnEmailService (#217)

* fix: email delivery in Email::SendOnEmailService

* fix: handle nil response from email_reply in Email::SendOnEmailService
This commit is contained in:
Gabriel Jablonski 2026-02-18 16:23:13 -03:00 committed by GitHub
parent fdde54f1a2
commit f2635a69ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 4 deletions

View File

@ -35,9 +35,8 @@ class ConversationReplyMailer < ApplicationMailer
end end
def email_reply(message) def email_reply(message)
return unless smtp_config_set_or_development?
init_conversation_attributes(message.conversation) init_conversation_attributes(message.conversation)
return unless smtp_config_set_or_development? || email_oauth_enabled
@message = message @message = message
prepare_mail(true) prepare_mail(true)

View File

@ -5,10 +5,15 @@ class Email::SendOnEmailService < Base::SendOnChannelService
Channel::Email Channel::Email
end end
def perform_reply def perform_reply # rubocop:disable Metrics/AbcSize
return unless message.email_notifiable_message? return unless message.email_notifiable_message?
reply_mail = ConversationReplyMailer.with(account: message.account).email_reply(message).deliver_now mail = ConversationReplyMailer.with(account: message.account).email_reply(message)
raise "Email could not be prepared for message #{message.id}" if mail.nil?
reply_mail = mail.deliver_now
raise "Email delivery returned nil for message #{message.id}" if reply_mail.nil?
Rails.logger.info("Email message #{message.id} sent with source_id: #{reply_mail.message_id}") Rails.logger.info("Email message #{message.id} sent with source_id: #{reply_mail.message_id}")
message.update!(source_id: reply_mail.message_id) message.update!(source_id: reply_mail.message_id)
rescue StandardError => e rescue StandardError => e

View File

@ -57,6 +57,39 @@ describe Email::SendOnEmailService do
end end
end end
context 'when email_reply returns nil' do
let(:exception_tracker) { instance_double(ChatwootExceptionTracker, capture_exception: true) }
before do
allow(mailer_context).to receive(:email_reply).with(message).and_return(nil)
allow(ChatwootExceptionTracker).to receive(:new).and_return(exception_tracker)
end
it 'marks the message as failed with preparation error' do
service.perform
expect(message.reload.status).to eq('failed')
expect(message.reload.external_error).to include("Email could not be prepared for message #{message.id}")
end
end
context 'when deliver_now returns nil' do
let(:exception_tracker) { instance_double(ChatwootExceptionTracker, capture_exception: true) }
before do
allow(mailer_context).to receive(:email_reply).with(message).and_return(delivery)
allow(delivery).to receive(:deliver_now).and_return(nil)
allow(ChatwootExceptionTracker).to receive(:new).and_return(exception_tracker)
end
it 'marks the message as failed' do
service.perform
expect(message.reload.status).to eq('failed')
expect(message.reload.external_error).to include("Email delivery returned nil for message #{message.id}")
end
end
context 'when an error occurs' do context 'when an error occurs' do
let(:error_message) { 'SMTP connection failed' } let(:error_message) { 'SMTP connection failed' }
let(:error) { StandardError.new(error_message) } let(:error) { StandardError.new(error_message) }