From 84242aae7b3c273f82df3aacee144c46cc1095e2 Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Fri, 3 Apr 2026 12:03:12 -0300 Subject: [PATCH] release v4.12.0-fazer-ai.44 (#253) * fix(whatsapp): use payload filename for documents to avoid Content-Disposition parsing issues When receiving documents via the WhatsApp Cloud API, filenames with spaces or special characters were mangled due to the Down gem's case-sensitive Content-Disposition header parsing. Now uses the filename from the WhatsApp message payload when available, falling back to Content-Disposition for other attachment types. * fix: scope payload filename preference to document messages only * fix: revert document-only scope, apply payload filename for all attachment types --- .../whatsapp/incoming_message_base_service.rb | 2 +- ...ing_message_whatsapp_cloud_service_spec.rb | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/app/services/whatsapp/incoming_message_base_service.rb b/app/services/whatsapp/incoming_message_base_service.rb index 930ab00b4..fcd81bc28 100644 --- a/app/services/whatsapp/incoming_message_base_service.rb +++ b/app/services/whatsapp/incoming_message_base_service.rb @@ -171,7 +171,7 @@ class Whatsapp::IncomingMessageBaseService # rubocop:disable Metrics/ClassLength file_type: file_content_type(message_type), file: { io: attachment_file, - filename: attachment_file.original_filename, + filename: attachment_payload[:filename].presence || attachment_file.original_filename, content_type: attachment_file.content_type }, meta: ({ is_recorded_audio: true } if attachment_payload[:voice]) diff --git a/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb b/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb index 4ad948bf3..e1d4d25a0 100644 --- a/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb @@ -107,6 +107,52 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do end end + context 'when document attachment has filename with spaces' do + let(:document_params) do + { + phone_number: whatsapp_channel.phone_number, + object: 'whatsapp_business_account', + entry: [{ + changes: [{ + value: { + contacts: [{ profile: { name: 'Sojan Jose' }, wa_id: '2423423243' }], + messages: [{ + from: '2423423243', + document: { + id: 'b1c68f38-8734-4ad3-b4a1-ef0c10d683', + mime_type: 'application/pdf', + sha256: '29ed500fa64eb55fc19dc4124acb300e5dcca0f822a301ae99944db', + filename: 'Sample File Ação.pdf', + caption: 'Check this document' + }, + timestamp: '1664799904', type: 'document' + }] + } + }] + }] + }.with_indifferent_access + end + + it 'uses the filename from the message payload instead of Content-Disposition' do + stub_media_url_request + stub_request(:get, 'https://chatwoot-assets.local/sample.png').to_return( + status: 200, + body: File.read('spec/assets/attachment.pdf'), + headers: { + 'content-type' => 'application/pdf', + 'content-disposition' => + "attachment; filename=Sample_File_Ao.pdf; filename*=utf-8''Sample%20File%20A%C3%A7%C3%A3o.pdf" + } + ) + + described_class.new(inbox: whatsapp_channel.inbox, params: document_params).perform + + attachment = whatsapp_channel.inbox.messages.first.attachments.first + expect(attachment).to be_present + expect(attachment.file.filename.to_s).to eq('Sample File Ação.pdf') + end + end + context 'when dispatching provider events' do let(:message_params) do {