fix: Prepend UTF-8 BOM to contact CSV export for non-ASCII character support (#14123)

## Description

Spreadsheet applications such as Microsoft Excel do not auto-detect
UTF-8 encoding when opening CSV files. This causes non-ASCII characters
(Arabic, Japanese, Chinese, Korean, etc.) to appear garbled in the
exported contacts CSV.

This PR prepends the UTF-8 Byte Order Mark (`EF BB BF`) to the CSV
output in `Account::ContactsExportJob`, which signals to spreadsheet
applications that the file is UTF-8 encoded.

Fixes: #13998
This commit is contained in:
Kenta Ishizaki
2026-04-24 18:06:25 +05:30
committed by GitHub
parent 9a89e1f522
commit c5fb8d73cc
2 changed files with 13 additions and 1 deletions
+6 -1
View File
@@ -42,8 +42,13 @@ class Account::ContactsExportJob < ApplicationJob
def attach_export_file(csv_data)
return if csv_data.blank?
# Prepend UTF-8 BOM so that spreadsheet applications (e.g. Excel)
# correctly recognise the file encoding for non-ASCII characters
# such as Arabic, Japanese, and Chinese.
bom = "\xEF\xBB\xBF"
@account.contacts_export.attach(
io: StringIO.new(csv_data),
io: StringIO.new("#{bom}#{csv_data}"),
filename: "#{@account.name}_#{@account.id}_contacts.csv",
content_type: 'text/csv'
)
@@ -85,6 +85,13 @@ RSpec.describe Account::ContactsExportJob do
expect(phone_numbers).to include('+910808080818', '+910808080808')
end
it 'prepends UTF-8 BOM to the exported CSV for spreadsheet compatibility' do
described_class.perform_now(account.id, user.id, [], {})
raw = account.contacts_export.download
expect(raw.bytes[0..2]).to eq([0xEF, 0xBB, 0xBF])
end
it 'returns all resolved contacts as results when filter is not prvoided' do
create(:contact, account: account, email: nil, phone_number: nil)
described_class.perform_now(account.id, user.id, %w[id name email column_not_present], {})