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 <rorrick@bulksms.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Rorrick
2026-06-12 10:21:42 +04:00
committed by GitHub
co-authored by Rorrick Smith Muhsin Keloth Muhsin Claude Opus 4.8 Copilot Autofix powered by AI
parent c6a38e2fc6
commit c041fde3a2
2 changed files with 45 additions and 1 deletions
@@ -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
@@ -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
{