Files
leadchat/app/models/concerns/account_settings_schema.rb
Tanmay Deep Sharma 722e68eecb fix: validate support_email format and handle parse errors in mailer (#13958)
## Description

ConversationReplyMailer#parse_email calls
Mail::Address.new(email_string).address without error handling. When an
account's support_email contains a non-email string (e.g., "Smith
Smith"), the mail gem raises Mail::Field::IncompleteParseError, crashing
conversation transcript emails.

This has caused 1,056 errors on Sentry (EXTERNAL-CHATINC-JX) since Feb
25, all from a single account that has a name stored in the
support_email field instead of a valid email address.

Closes
https://linear.app/chatwoot/issue/CW-6687/mailfieldincompleteparseerror-mailaddresslist-can-not-parse-orsmith

## Type of change

Please delete options that are not relevant.

- [ ] 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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
2026-04-13 19:06:06 +07:00

48 lines
1.8 KiB
Ruby

module AccountSettingsSchema
extend ActiveSupport::Concern
SETTINGS_PARAMS_SCHEMA = {
'type': 'object',
'properties':
{
'auto_resolve_after': { 'type': %w[integer null], 'minimum': 10, 'maximum': 1_439_856 },
'auto_resolve_message': { 'type': %w[string null] },
'auto_resolve_ignore_waiting': { 'type': %w[boolean null] },
'audio_transcriptions': { 'type': %w[boolean null] },
'auto_resolve_label': { 'type': %w[string null] },
'keep_pending_on_bot_failure': { 'type': %w[boolean null] },
'captain_auto_resolve_mode': { 'type': %w[string null], 'enum': ['evaluated', 'legacy', 'disabled', nil] },
'conversation_required_attributes': {
'type': %w[array null],
'items': { 'type': 'string' }
},
'captain_models': {
'type': %w[object null],
'properties': {
'editor': { 'type': %w[string null] },
'assistant': { 'type': %w[string null] },
'copilot': { 'type': %w[string null] },
'label_suggestion': { 'type': %w[string null] },
'audio_transcription': { 'type': %w[string null] },
'help_center_search': { 'type': %w[string null] }
},
'additionalProperties': false
},
'captain_features': {
'type': %w[object null],
'properties': {
'editor': { 'type': %w[boolean null] },
'assistant': { 'type': %w[boolean null] },
'copilot': { 'type': %w[boolean null] },
'label_suggestion': { 'type': %w[boolean null] },
'audio_transcription': { 'type': %w[boolean null] },
'help_center_search': { 'type': %w[boolean null] }
},
'additionalProperties': false
}
},
'required': [],
'additionalProperties': true
}.to_json.freeze
end