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`
# Pull Request Template
## Description
- Validates openai key while configuring hooks
- added backfill logic
Fixes # (issue)
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.
locally
<img width="1710" height="1234" alt="CleanShot 2026-04-15 at 16 15
02@2x"
src="https://github.com/user-attachments/assets/3d319fe0-19f9-4fd0-9308-74987daac2e1"
/>
<img width="2884" height="1136" alt="CleanShot 2026-05-11 at 19 22
53@2x"
src="https://github.com/user-attachments/assets/5eae8650-985b-4c4a-af42-35f7175ff52d"
/>
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Email inbox replies now work for Google and Microsoft OAuth inboxes even
when the self-hosted instance does not have global SMTP configured. This
keeps agent replies working for email channels that already have valid
inbox-level delivery settings.
fixes: chatwoot/chatwoot#13118closes: chatwoot/chatwoot#13118
## Why
Self-hosted email inbox replies were blocked by a global SMTP guard in
the `email_reply` path. For OAuth-backed email inboxes, outbound
delivery is configured at the inbox level, so the mailer returned early
and the reply flow failed before sending.
## What this change does
- Allows the `email_reply` path to proceed when the inbox has SMTP
configured
- Allows the `email_reply` path to proceed when the inbox has Google or
Microsoft OAuth delivery configured
- Renames the touched mailer helper predicates to `?` methods for
clarity
## Validation
- Configure a Google email inbox on a self-hosted instance without
global `SMTP_ADDRESS`
- Reply from Chatwoot to an existing email conversation
- Confirm the reply is sent through the inbox OAuth SMTP configuration
- Run `bundle exec rspec
spec/mailers/conversation_reply_mailer_spec.rb:595`
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Upgrade rails to 7.2.2 so that we can proceed with the rails 8 upgrade
afterwards
# Changelog
- `.circleci/config.yml` — align CI DB setup with GitHub Actions
(`db:create` + `db:schema:load`) to avoid trigger-dependent prep steps.
- `.rubocop.yml` — add `rubocop-rspec_rails` and disable new cops that
don't match existing spec style.
- `AGENTS.md` — document that specs should run without `.env` (rename
temporarily when present).
- `Gemfile` — upgrade to Rails 7.2, switch Azure storage gem, pin
`commonmarker`, bump `sidekiq-cron`, add `rubocop-rspec_rails`, and
relax some gem pins.
- `Gemfile.lock` — dependency lockfile updates from the Rails 7.2 and
gem changes.
- `app/controllers/api/v1/accounts/integrations/linear_controller.rb` —
stringify params before passing to the Linear service to keep key types
stable.
- `app/controllers/super_admin/instance_statuses_controller.rb` — use
`MigrationContext` API for migration status in Rails 7.2.
- `app/models/installation_config.rb` — add commentary on YAML
serialization and future JSONB migration (no behavior change).
- `app/models/integrations/hook.rb` — ensure hook type is set on create
only and guard against missing app.
- `app/models/user.rb` — update enum syntax for Rails 7.2 deprecation,
serialize OTP backup codes with JSON, and use Ruby `alias`.
- `app/services/crm/leadsquared/setup_service.rb` — stringify hook
settings keys before merge to keep JSON shape consistent.
- `app/services/macros/execution_service.rb` — remove macro-specific
assignee activity workaround; rely on standard assignment handlers.
- `config/application.rb` — load Rails 7.2 defaults.
- `config/storage.yml` — update Azure Active Storage service name to
`AzureBlob`.
- `db/migrate/20230515051424_update_article_image_keys.rb` — use
credentials `secret_key_base` with fallback to legacy secrets.
- `docker/Dockerfile` — add `yaml-dev` and `pkgconf` packages for native
extensions (Ruby 3.4 / psych).
- `lib/seeders/reports/message_creator.rb` — add parentheses for clarity
in range calculation.
- `package.json` — pin Vite version and bump `vite-plugin-ruby`.
- `pnpm-lock.yaml` — lockfile changes from JS dependency updates.
- `spec/builders/v2/report_builder_spec.rb` — disable transactional
fixtures; truncate tables per example via Rails `truncate_tables` so
after_commit callbacks run with clean isolation; keep builder spec
metadata minimal.
- `spec/builders/v2/reports/label_summary_builder_spec.rb` — disable
transactional fixtures + truncate tables via Rails `truncate_tables`;
revert to real `resolved!`/`open!`/`resolved!` flow for multiple
resolution events; align date range to `Time.zone` to avoid offset gaps;
keep builder spec metadata minimal.
- `spec/controllers/api/v1/accounts/macros_controller_spec.rb` — assert
`assignee_id` instead of activity message to avoid transaction-timing
flakes.
- `spec/services/telegram/incoming_message_service_spec.rb` — reference
the contact tied to the created conversation instead of
`Contact.all.first` to avoid order-dependent failures when other specs
leave data behind.
-
`spec/mailers/administrator_notifications/shared/smtp_config_shared.rb`
— use `with_modified_env` instead of stubbing mailer internals.
- `spec/services/account/sign_up_email_validation_service_spec.rb` —
compare error `class.name` for parallel/reload-safe assertions.
Previously, email replies were handled inside workers. There was no
execution logs. This meant if emails silently failed (as reported by a
customer), we had no way to trace where the issue happened, the only
assumption was “no error = mail sent.”
By moving email handling into jobs, we now have proper execution logs
for each attempt. This makes it easier to debug delivery issues and
would have better visibility when investigating customer reports.
Fixes
https://linear.app/chatwoot/issue/CW-5538/emails-are-not-sentdelivered-to-the-contact
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
## Summary
- update the admin notification base mailer spec to ignore ordering when
verifying administrator email addresses
- extend the channel and integrations admin notification mailer specs to
cover multiple administrators without relying on recipient order
------
https://chatgpt.com/codex/tasks/task_e_68cc7457cf788326a765f116ceab1732
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
# Pull Request Template
## Description
Fixes
[CW-4620](https://linear.app/chatwoot/issue/CW-4620/rethinking-custom-domains-in-chatwoot)
<img width="642" height="187" alt="Screenshot 2025-07-29 at 8 17 44 PM"
src="https://github.com/user-attachments/assets/ad2f5dac-4b27-4dce-93ca-6cbba74443fb"
/>
## Type of change
- [x] New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
## Checklist:
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
As part of PR [#11622](https://github.com/chatwoot/chatwoot/pull/11622),
we intentionally hide CSAT survey URLs from agents in the dashboard to
avoid exposing those links internally. However, email replies being
external communications to contacts should still include the survey
URLs.
We missed handling that specific case for email channels. All other
external channels like WhatsApp, Instagram, Telegram, etc., were already
working correctly and continue to include the survey URLs as intended.
---------
Co-authored-by: Pranav <pranav@chatwoot.com>
- Automate the deletion of accounts that have requested deletion via
account settings.
- Add a Sidekiq job that runs daily to find accounts that have requested
deletion and have passed the 7-day window.
- This job deletes the account and then soft-deletes users if they do
not belong to any other account.
- This job also sends an email to the Chatwoot instance admin for
compliance purposes.
- The Chatwoot instance admin's email is configurable via the
`CHATWOOT_INSTANCE_ADMIN_EMAIL` global config.
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Add ability to send files as attachments instead of links
Fixes: https://github.com/chatwoot/chatwoot/issues/1074
## Changes
- `emaily_reply` : We will attach the small attachments as attachments
and large ones as links
- `reply_with_summary`, `conversation_transcript`,
`reply_with_out_summary` : We will change the attachment format to the
following instead of the previous `View the attachment here`
```
Attachments:
file_name
file_name2
```
---------
ref: https://github.com/chatwoot/chatwoot/pull/10318/files -> for fixing
: https://github.com/chatwoot/chatwoot/pull/9655#issuecomment-2183962550
---------
Co-authored-by: Marco Marinho <marcomarinho12@gmail.com>
Co-authored-by: Pranav <pranavrajs@gmail.com>
## Description
Add account delete option in the user account settings.
Fixes#1555
## Type of change
- [ ] New feature (non-breaking change which adds functionality)


## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own 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
---------
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Sojan Jose <sojan.official@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This PR adds the following changes
1. Add `Imap::GoogleFetchEmailService` and
`Google::RefreshOauthTokenService`. The
`Google::RefreshOauthTokenService` uses
`OmniAuth::Strategies::GoogleOauth2` which is already added as a packge
2. Update `Inboxes::FetchImapEmailsJob` to handle Google inboxes
3. Add SMTP settings for Google in `ConversationReplyMailerHelper` to
allow sending emails
## Preview
#### Incoming emails

#### Outgoing email

---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This pull request enhances the export contacts feature by adding a confirmation step before exporting. Previously, clicking the export button would trigger the export action without confirmation.
Additionally, it ensures that only the intended recipient receives the export email, addressing the previous behaviour where all administrators received it.
Fixes: #8504
Co-authored-by: Sojan Jose <sojan@pepalo.com>
This PR addresses several items listed in our rubocop_todo by implementing the necessary corrections and enhancements. As a result, we are now able to remove the rubocop_todo file entirely, streamlining our codebase and ensuring adherence to our coding standards.
fixes: https://linear.app/chatwoot/issue/CW-1806/chore-rubocop-audit
- Ensure existing contact information is updated on data import
- Refactor the existing job to make it more readable
- Fixes issues with import files in the wrong encoding
fixes: #7307
We have display_name and the actual name for an agent. display_name is used in all public facing parts. The https://github.com/chatwoot/chatwoot/pull/7232/files PR missed this and used actual name instead.
This PR fixes it.
- Adds the backend APIs required for Microsoft Email Channels
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
Co-authored-by: Sojan <sojan@pepalo.com>
Users can change their email from profile settings. They will be logged out immediately. Users can log in again with the updated email without verifying the same. This is a security problem.
So this change enforce the user to reconfirm the email after changing it. Users can log in with the updated email only after the confirmation.
Fixes: https://huntr.dev/bounties/7afd04b4-232e-4907-8a3c-acf8bd4b5b22/
This change allows the user to configure both IMAP and SMTP for an email inbox. IMAP enables the user to see emails in Chatwoot. And user can use SMTP to reply to an email conversation.
Users can use the default settings to send and receive emails for email inboxes if both IMAP and SMTP are disabled.
Fixes#2520