Inbound emails containing null bytes could fail while Chatwoot persisted the incoming message, causing IMAP sync to drop and repeatedly retry the same malformed email. This strips null bytes at the inbound mailbox message persistence boundary so the rest of the email can be saved normally. Fixes https://linear.app/chatwoot/issue/CW-7165/argumenterror-string-contains-null-byte-argumenterror Sentry: https://chatwoot-p3.sentry.io/issues/7405946944/ ## Test - [x] added specs - [x] manually tested the logic on prod for the inbox(email) which was throwing the error ## What changed - Sanitizes null bytes only while building attributes for inbound mailbox message persistence. - Uses the sanitized source ID for both duplicate lookup and message creation. - Adds regression coverage for the mailbox message creation path. --------- Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com> Co-authored-by: Sony Mathew <sony@chatwoot.com>
35 lines
962 B
Ruby
35 lines
962 B
Ruby
module MailboxSanitizer
|
|
NULL_BYTE = "\u0000".freeze
|
|
|
|
private
|
|
|
|
def sanitized_message_attributes(source_id)
|
|
{
|
|
account_id: @conversation.account_id,
|
|
sender: @conversation.contact,
|
|
content: sanitize_mailbox_value(mail_content)&.truncate(150_000),
|
|
inbox_id: @conversation.inbox_id,
|
|
message_type: 'incoming',
|
|
content_type: 'incoming_email',
|
|
source_id: source_id,
|
|
content_attributes: sanitized_content_attributes
|
|
}
|
|
end
|
|
|
|
def sanitized_content_attributes
|
|
sanitize_mailbox_value(
|
|
email: processed_mail.serialized_data,
|
|
cc_email: processed_mail.cc,
|
|
bcc_email: processed_mail.bcc
|
|
)
|
|
end
|
|
|
|
def sanitize_mailbox_value(value)
|
|
return value.delete(NULL_BYTE) if value.is_a?(String)
|
|
return value.map { |item| sanitize_mailbox_value(item) } if value.is_a?(Array)
|
|
return value.transform_values { |item| sanitize_mailbox_value(item) } if value.is_a?(Hash)
|
|
|
|
value
|
|
end
|
|
end
|