29 Commits
Author SHA1 Message Date
6a9c44476e feat(super-admin): Add push diagnostics tool (#14105)
We're getting many customer reports saying "I'm not getting
notifications." We can't always identify the root cause since there are
multiple points of failure. Added a **Push Diagnostics** tool in Super
Admin to help us investigate mobile/web push issues.

Here's how it works:

- Look up a user by email/ID → see all their registered subscriptions
with device info (iOS/Android, brand, model), token freshness, and
last-updated time
- Send a customizable test push and read the raw FCM/web-push/relay
response to see if the customer is receiving push notifications—if not,
it will show proper errors.
- Delete broken subscriptions so the mobile app re-registers on next
launch
<img width="3816" height="1974" alt="CleanShot 2026-04-20 at 12 56
56@2x"
src="https://github.com/user-attachments/assets/08ecab6f-7ec3-44b3-a114-5e6eb8cf0879"
/>

Fixes https://linear.app/chatwoot/issue/CW-6892/push-diagnostics-tool

---------

Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 15:55:12 +04:00
f2cb23d6e9 fix: handle Socket::ResolutionError in browser push notifications (#13957)
## Linear Ticket

https://linear.app/chatwoot/issue/CW-6707/socketresolutionerror-failed-to-open-tcp-connection-to-permanently

https://linear.app/chatwoot/issue/CW-6707/socketresolutionerror-failed-to-open-tcp-connection-to-permanently#comment-14e0f9ff

## Description

Browser push notifications fail with Socket::ResolutionError when the
push subscription endpoint's domain can't be resolved via DNS (e.g.,
defunct push service, transient DNS failure). This error wasn't handled
in handle_browser_push_error, so it fell through to the catch-all else
branch and got reported to Sentry on every notification attempt — 1,637
times in the last 7 days.
The dead subscription was never cleaned up or the error suppressed, so
every subsequent notification for the affected user triggered the same
Sentry alert.
Added Socket::ResolutionError to the existing transient network error
handler alongside Errno::ECONNRESET, Net::OpenTimeout, and
Net::ReadTimeout. The error is logged but not reported to Sentry, and
the subscription is kept intact in case it's a temporary DNS blip.

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

- Verified that Socket::ResolutionError is a subclass of StandardError
and matches the when clause

## 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

Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
2026-04-01 16:55:49 +05:30
Sivin VargheseandGitHub 23786bcb52 chore: mark conversation notifications as read on visit (#13906) 2026-03-26 14:01:26 +05:30
Vishnu NarayananandGitHub c884cdefde feat: add per-account daily rate limit for outbound emails (#13411)
Introduce a daily cap on non-channel outbound emails to prevent abuse.

Fixes https://linear.app/chatwoot/issue/CW-6418/ses-incident-jan-28

## Type of change

- [x] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing
functionality not to work as expected)

## Summary
- Adds a Redis-based daily counter to rate limit outbound emails per
account, preventing email abuse
- Covers continuity emails (WebWidget/API), conversation transcripts,
and agent notifications
  - Email channel replies are excluded (paid feature, not abusable)
- Adds account suspension check in `ConversationReplyMailer` to block
already-queued emails for suspended accounts

  ## Limit Resolution Hierarchy
1. Per-account override (`account.limits['emails']`) — SuperAdmin
configurable
2. Enterprise plan-based (`ACCOUNT_EMAILS_PLAN_LIMITS`
InstallationConfig)
3. Global default (`ACCOUNT_EMAILS_LIMIT` InstallationConfig, default:
100)
  4. Fallback (`ChatwootApp.max_limit` — effectively unlimited)

  ## Enforcement Points
  | Path | Where | Behavior |
  |------|-------|----------|
| WebWidget/API continuity |
`SendEmailNotificationService#should_send_email_notification?` |
Silently skipped |
| Widget transcript | `Widget::ConversationsController#transcript` |
Returns 429 |
| API transcript | `ConversationsController#transcript` | Returns 429 |
| Agent notifications | `Notification::EmailNotificationService#perform`
| Silently skipped |
  | Email channel replies | Not rate limited | Paid feature |
| Suspended accounts | `ConversationReplyMailer` | Blocked at mailer
level |
2026-02-03 02:06:51 +05:30
Muhsin KelothandGitHub ee9f1d7adb chore: Handle WebPush rate limiting in push notification service (#12184)
Implemented a rescue block for WebPush::TooManyRequests that logs
warnings during rate limiting events. This captures user email and
account ID for better traceability. We will implement a proper
throttling mechanism after identifying patterns across accounts.
2025-08-13 13:32:22 +05:30
Sojan JoseandGitHub e97489f534 chore: Disable email notifications for unconfirmed users (#10964)
- disable email notifications if the user hasn't confirmed the email yet, as there is potential chance for the emails to bounce
2025-02-24 12:14:40 -08:00
PranavandGitHub f7f687ce53 fix: Update notification payload (#9666)
- Fix notification payload to avoid argument error.
2024-06-21 17:28:48 -07:00
PranavandGitHub ee2844877c fix: Add catch for additional webpush errors (#9662)
Webpush gem throws errors such as `WebPush::ExpiredSubscription`,
`WebPush::InvalidSubscription`, `WebPush::Unauthorized`. We handled only
ExpiredSubscription.

If the SDK threw any other errors, it would pause sending the
notification to all other devices for that user. This change would
update the logic to remove the expired subscription and handle the rest
of the errors gracefully.

Fixes
https://linear.app/chatwoot/issue/CW-3399/webpushinvalidsubscription-host-fcmgoogleapiscom-nethttpnotfound-404
2024-06-21 14:58:36 -07:00
Muhsin KelothandGitHub 9046730206 feat: FCM HTTP v1 API changes (#9629)
Fixes https://linear.app/chatwoot/issue/CW-3210/legacy-firebase-changes
2024-06-18 10:38:06 +05:30
Muhsin KelothandGitHub ef90b7a3d8 feat: Revamp the notification title and content (#8988) 2024-03-06 20:51:56 +05:30
Muhsin KelothandGitHub 6b0d1d77d3 fix: Email notifications (#8502) 2023-12-06 15:50:23 +05:30
Sojan JoseandGitHub 38aee8d9ea chore: Switch to web-push gem (#6390)
- The previous gem, `webpush` was last updated a while ago. Also, with the recent ruby upgrade, we needed a fix for zaru/webpush#106. Hence switching to the `web-push` gem where the issues are fixed.
2023-02-03 18:55:22 +05:30
Pranav Raj SandGitHub 4b1bb65c92 chore: Add notification ID to tag to make it unique (#5227) 2022-08-09 00:09:11 +05:30
Sojan JoseandGitHub 4187428729 chore: Update dependencies to the latest versions (#5033) 2022-07-15 09:51:59 +07:00
Vishnu NarayananandGitHub 8155024b6a feat: fix logging levels (#4314)
https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/Logger.html

Fixes https://github.com/chatwoot/chatwoot/issues/4313
2022-03-28 18:14:30 +05:30
6cfd7d3836 feat: autogenerate vapid keys for push notifications (#3128)
* feat: Autogenerate push notification keys
* add vapid service class and remove pushkey model
* add spec for vapid service
* unset vapid env keys
* Unset VAPID_PRIVATE_KEY env variable

Co-authored-by: Sojan Jose <sojan@chatwoot.com>
Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com>
2021-11-09 21:36:32 +05:30
A. VerdeandGitHub 81708f92a8 chore: Fcm notification priority (#3319) 2021-11-08 11:32:07 +05:30
Sojan JoseandGitHub 9c4ce9af35 chore: Strip unnecessary data from push payload (#2924) 2021-09-09 13:59:42 +05:30
Pranav Raj SandGitHub ed317c5bb3 feat: Use relay server for self-hosted mobile push notifications (#2757) 2021-08-17 01:44:16 +05:30
467b45b427 feat: Improved password security policy (#2345)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
2021-06-07 17:26:08 +05:30
Sojan JoseandGitHub 3ade7d4445 chore: Fix push message tag error (#1768) 2021-02-16 00:15:45 +05:30
31c07771e8 feat: Notification on new messages in conversation (#1204)
fixes: #895
fixes: #1118
fixes: #1075

Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
2020-09-10 19:19:15 +05:30
Sojan JoseandGitHub a04ca24def feat: Customisable Email Templates (#1095) 2020-08-06 15:21:06 +05:30
Sojan JoseandGitHub 04f6460afb Chore: Fix failing sidekiq events for contact create (#966) 2020-06-16 19:39:57 +05:30
b0bbd757b5 Chore: FCM Notification Improvements (#957)
Co-authored-by: Pranav Raj Sreepuram <pranavrajs@gmail.com>
2020-06-15 13:36:56 +05:30
Sojan JoseandGitHub 8b022311c0 Chore: FCM Push Fixes (#934) 2020-06-09 17:42:18 +05:30
Sojan JoseandGitHub a13a474c23 Chore: Firebase Cloud Messaging Support (#858) 2020-06-05 00:15:50 +05:30
e9131ea558 Feature: Add web push notification permission in frontend (#766)
Add webpush notification permission in frontend

Co-authored-by: Sojan <sojan@pepalo.com>
2020-05-06 00:10:56 +05:30
96da27f1f6 Feature: User Notification Objects (#752)
Co-authored-by: Pranav Raj S <pranavrajs@gmail.com>
2020-05-01 14:53:43 +05:30