From c041fde3a2d745b9b69d73df8726c687cf351164 Mon Sep 17 00:00:00 2001 From: Rorrick <34399621+Rorrick@users.noreply.github.com> Date: Fri, 12 Jun 2026 08:21:42 +0200 Subject: [PATCH] fix: Preserve original filenames for WhatsApp cloud attachments (#14168) ## Summary Preserves the original filename provided in the WhatsApp Cloud attachment payload when downloading media files. ## Problem Files containing accented or special characters could be saved with malformed names or incorrect extensions due to relying on remote download metadata. ## Changes Made - Uses attachment_payload[:filename] when present - Creates a tempfile using the original filename and extension - Preserves content type metadata - Falls back to existing behavior when no filename is provided ## Notes This should improve attachment downloads for filenames containing accented characters. Related to #10973 --------- Co-authored-by: Rorrick Smith Co-authored-by: Muhsin Keloth Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- ...incoming_message_whatsapp_cloud_service.rb | 11 +++++- ...ing_message_whatsapp_cloud_service_spec.rb | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb b/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb index 164c3ac12..f836a63c3 100644 --- a/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb +++ b/app/services/whatsapp/incoming_message_whatsapp_cloud_service.rb @@ -13,8 +13,17 @@ class Whatsapp::IncomingMessageWhatsappCloudService < Whatsapp::IncomingMessageB inbox.channel.media_url(attachment_payload[:id]), headers: inbox.channel.api_headers ) + # This url response will be failure if the access token has expired. inbox.channel.authorization_error! if url_response.unauthorized? - Down.download(url_response.parsed_response['url'], headers: inbox.channel.api_headers) if url_response.success? + + return unless url_response.success? + + downloaded_file = Down.download(url_response.parsed_response['url'], headers: inbox.channel.api_headers) + # WhatsApp Cloud sends the original filename in the payload; preserve it so accented + # names keep their correct extension instead of relying on the mangled remote metadata. + filename = attachment_payload[:filename] + downloaded_file.define_singleton_method(:original_filename) { filename } if filename.present? + downloaded_file end end 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 70c29c092..1bbd6d8f4 100644 --- a/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb +++ b/spec/services/whatsapp/incoming_message_whatsapp_cloud_service_spec.rb @@ -59,6 +59,41 @@ describe Whatsapp::IncomingMessageWhatsappCloudService do end end + context 'when document attachment includes an accented filename' 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', + filename: 'Currículum café.pdf', + caption: 'My résumé' + }, + timestamp: '1664799904', type: 'document' + }] + } + }] + }] + }.with_indifferent_access + end + + it 'preserves the original filename from the payload' do + stub_media_url_request + stub_sample_png_request + described_class.new(inbox: whatsapp_channel.inbox, params: document_params).perform + + attachment = whatsapp_channel.inbox.messages.first.attachments.first + expect(attachment.file.filename.to_s).to eq('Currículum café.pdf') + end + end + context 'when invalid attachment message params' do let(:error_params) do {