fix: call authorization_error! on IMAP auth failures (#13560)
## Notion document https://www.notion.so/chatwoot/Email-IMAP-Issue-30aa5f274c928062aa6bddc2e5877a63?showMoveTo=true&saveParent=true ## Description PLAIN IMAP channels (non-OAuth) were silently retrying failed authentication every minute, forever. When credentials are wrong/expired, Net::IMAP::NoResponseError was caught and logged but channel.authorization_error! was never called — so the Redis error counter never incremented, reauthorization_required? was never set, and admins were never notified. OAuth channels already had this handled correctly via the Reauthorizable concern. Additionally, Net::IMAP::ResponseParseError (raised by non-RFC-compliant IMAP servers) was falling through to the StandardError catch-all, flooding Estimated impact before fix: ~70–75 broken IMAP inboxes generating ~700k–750k wasted Sidekiq jobs/week. ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
committed by
GitHub
parent
9ca03c1af3
commit
7acd239c70
@@ -38,6 +38,14 @@ RSpec.describe Inboxes::FetchImapEmailsJob do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when channel is in backoff' do
|
||||
it 'does not fetch emails' do
|
||||
allow(imap_email_channel).to receive(:in_backoff?).and_return(true)
|
||||
expect(Imap::FetchEmailService).not_to receive(:new)
|
||||
described_class.perform_now(imap_email_channel)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the channel is regular imap' do
|
||||
it 'calls the imap fetch service' do
|
||||
fetch_service = double
|
||||
@@ -56,6 +64,17 @@ RSpec.describe Inboxes::FetchImapEmailsJob do
|
||||
described_class.perform_now(imap_email_channel, 4)
|
||||
expect(fetch_service).to have_received(:perform)
|
||||
end
|
||||
|
||||
it 'clears backoff after successful fetch' do
|
||||
fetch_service = double
|
||||
allow(Imap::FetchEmailService).to receive(:new).and_return(fetch_service)
|
||||
allow(fetch_service).to receive(:perform).and_return([])
|
||||
allow(imap_email_channel).to receive(:clear_backoff!)
|
||||
|
||||
described_class.perform_now(imap_email_channel)
|
||||
|
||||
expect(imap_email_channel).to have_received(:clear_backoff!)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the channel is Microsoft' do
|
||||
@@ -69,6 +88,37 @@ RSpec.describe Inboxes::FetchImapEmailsJob do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when authentication error is raised' do
|
||||
it 'calls authorization_error! on the channel' do
|
||||
allow(Imap::FetchEmailService).to receive(:new).and_raise(Imap::AuthenticationError)
|
||||
allow(imap_email_channel).to receive(:authorization_error!)
|
||||
|
||||
described_class.perform_now(imap_email_channel)
|
||||
|
||||
expect(imap_email_channel).to have_received(:authorization_error!)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a transient IMAP error is raised' do
|
||||
it 'calls apply_backoff! on the channel' do
|
||||
allow(Imap::FetchEmailService).to receive(:new).and_raise(EOFError)
|
||||
allow(imap_email_channel).to receive(:apply_backoff!)
|
||||
|
||||
described_class.perform_now(imap_email_channel)
|
||||
|
||||
expect(imap_email_channel).to have_received(:apply_backoff!)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when lock acquisition fails' do
|
||||
it 'does not raise an error' do
|
||||
lock_manager = instance_double(Redis::LockManager, lock: false)
|
||||
allow(Redis::LockManager).to receive(:new).and_return(lock_manager)
|
||||
|
||||
expect { described_class.perform_now(imap_email_channel) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'when IMAP OAuth errors out' do
|
||||
it 'marks the connection as requiring authorization' do
|
||||
error_response = double
|
||||
|
||||
Reference in New Issue
Block a user