chatwoot/spec
Sojan Jose 8e42307bdc
fix: improve email inbox IMAP and SMTP compatibility (#14589)
Fetch IMAP message content using `BODY.PEEK[]` instead of `RFC822` to
avoid provider-specific parser failures while preserving unread state.
This also applies the existing SMTP timeout configuration to custom SMTP
email-channel replies, so provider SMTP responses have enough time to
complete.

Fixes: https://github.com/chatwoot/chatwoot/issues/12762

## Why

Some IMAP providers can return responses for `FETCH RFC822` that Ruby
`net-imap` fails to parse with:

`Net::IMAP::ResponseParseError: unexpected RPAR (expected ATOM or NIL)`

We reproduced this with iCloud IMAP. Authentication, `INBOX` selection,
and header fetches worked, but fetching full message content with
`RFC822` failed before Chatwoot received a `Mail::Message`.

The same mailbox successfully returned full message content when fetched
with `BODY.PEEK[]`.

> During end-to-end iCloud validation, inbound fetch worked after the
IMAP change, but outbound replies through the custom SMTP settings could
still fail with a socket read timeout. The OAuth SMTP path already used
explicit SMTP timeout values; the custom SMTP path was relying on mailer
defaults instead.

## What this change does

- Replaces the full message fetch from `RFC822` to `BODY.PEEK[]`
- Reads the returned message content from `BODY[]`, which is how
`net-imap` exposes the response attribute
- Keeps the existing `BODY.PEEK[HEADER]` header-fetch behavior unchanged
- Applies `SMTP_OPEN_TIMEOUT` and `SMTP_READ_TIMEOUT` to custom SMTP
email-channel replies
- Defaults custom SMTP reply delivery to `open_timeout: 15` and
`read_timeout: 30`
- Updates IMAP service specs for standard and Microsoft IMAP fetch flows
- Updates mailer specs for custom SMTP timeout settings

`BODY.PEEK[]` is preferable here because it fetches the full message
content without marking messages as read.

## Validation

- Configured a local email inbox against iCloud IMAP and SMTP
- Confirmed `FETCH RFC822` reproduces `Net::IMAP::ResponseParseError:
unexpected RPAR (expected ATOM or NIL)`
- Confirmed `BODY[]` and `BODY.PEEK[]` fetch the same mailbox
successfully
- Confirmed Chatwoot imports iCloud messages after the IMAP change
- Sent two outbound replies from the Chatwoot UI through iCloud SMTP
after applying the timeout settings
- Confirmed both UI-created outbound messages were marked `sent`, had
iCloud SMTP `source_id` values, and had no `external_error`
- Ran `bundle exec rspec spec/services/imap/fetch_email_service_spec.rb
spec/services/imap/microsoft_fetch_email_service_spec.rb`
- Ran `bundle exec rspec spec/mailers/conversation_reply_mailer_spec.rb`
2026-06-03 15:56:54 +05:30
..
actions fix: Skip redundant contact saves in ContactIdentifyAction (#13778) 2026-03-11 21:40:38 -07:00
assets fix: standardize contact company field on company_name (#14099) 2026-04-27 18:43:26 +05:30
builders feat(whatsapp): Add support for voice messages (#14606) 2026-06-02 15:33:32 +04:00
channels fix: Move contact events to account stream rather than individual user stream (#11082) 2025-03-13 17:46:48 -07:00
config feat: add GuideJar embed support in HC (#13944) 2026-03-30 14:19:02 +05:30
configs chore: Enable the new Rubocop rules (#7122) 2023-05-19 14:37:10 +05:30
controllers fix(microsoft): prevent OAuth admin consent loop (#13962) 2026-06-03 12:05:25 +05:30
dispatchers Non blocking event dispatch (#652) 2020-03-29 19:18:30 +05:30
drops feat: Add the support for custom attributes in message variables (#8511) 2023-12-08 14:13:35 -08:00
enterprise fix(contacts): align contact export permissions (#14601) 2026-06-01 13:58:57 +05:30
factories feat: Ability to specify the authentication type for imap server (#12306) 2026-05-08 16:40:15 +05:30
finders feat(rollup): report builder abstraction [2/3] (#13798) 2026-04-20 11:15:48 +05:30
fixtures fix(mailbox): render inline images without Content-Disposition (#11949) 2026-05-06 18:56:31 +05:30
helpers feat: Implemented search results page functionality (#11086) 2026-06-02 15:19:23 +05:30
integration Fix url in emails, add frontendURL helper (#19) 2019-08-25 19:59:28 +05:30
jobs feat: show processing status for one-off campaigns (#14592) 2026-06-01 16:47:17 +05:30
lib feat: inline images in website and email channels (#14516) 2026-06-03 15:05:17 +05:30
listeners revert: restore conversation unread count feature flag (#14623) 2026-06-02 21:11:48 +05:30
mailboxes fix(mailbox): render inline images without Content-Disposition (#11949) 2026-05-06 18:56:31 +05:30
mailers fix: improve email inbox IMAP and SMTP compatibility (#14589) 2026-06-03 15:56:54 +05:30
models revert: restore conversation unread count feature flag (#14623) 2026-06-02 21:11:48 +05:30
policies chore: Enforce custom role permissions on conversation access (#12583) 2025-10-22 20:23:37 -07:00
presenters fix: index email subject from conversation for outbound messages (#14122) 2026-04-22 20:36:35 +05:30
requests/api/v1 feat: allow disabling 2FA with a backup code (#14102) 2026-04-28 10:09:41 +07:00
services fix: improve email inbox IMAP and SMTP compatibility (#14589) 2026-06-03 15:56:54 +05:30
support feat: base layer for unread counts (store, counter and builder) (1/3)[CW-6851] (#14368) 2026-05-20 14:26:21 +05:30
swagger feat: validate OpenAPI spec using Skooma (#13623) 2026-03-10 18:33:55 -07:00
coverage_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30
rails_helper.rb feat: base layer for unread counts (store, counter and builder) (1/3)[CW-6851] (#14368) 2026-05-20 14:26:21 +05:30
spec_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30
test_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30