RFC 2047: MIME Phần 3 — Mở rộng Tiêu đề Thư cho Văn bản Không phải ASCII
Tại Sao Tồn Tại
RFC 2045 và RFC 2046 giải quyết vấn đề truyền tải nội dung không phải ASCII trong phần thân tin nhắn bằng Content-Transfer-Encoding. Nhưng tiêu đề email — Subject, From display names, To display names, và các tiêu đề khác — được điều chỉnh bởi RFC 5322, giới hạn chúng ở 7-bit US-ASCII.
Điều này tạo ra vấn đề hiển nhiên: hàng tỷ người dùng email viết bằng các ngôn ngữ yêu cầu ký tự không phải ASCII. Nếu không có RFC 2047, bạn không thể gửi email với:
- Dòng Subject bằng Tiếng Trung, Tiếng Nhật, Tiếng Hàn, Tiếng Ả Rập, Tiếng Do Thái hoặc Tiếng Thái
- Tên hiển thị người gửi có ký tự có dấu (René, Müller, Björk)
- Bất kỳ trường tiêu đề nào chứa ký tự ngoài phạm vi ASCII
RFC 2047 xác định cú pháp encoded-word: một cách nhỏ gọn để nhúng văn bản không phải ASCII bên trong tiêu đề chỉ ASCII, có thể đọc được bởi bất kỳ ứng dụng thư MIME nào.
Cách Hoạt Động
Định Dạng Encoded-Word
Một encoded-word có cấu trúc như sau:
=?charset?encoding?encoded-text?=
Ba thành phần là:
| Thành Phần | Mục Đích | Giá Trị |
|---|---|---|
charset |
Bộ ký tự của văn bản gốc |
UTF-8, ISO-8859-1, ISO-2022-JP, v.v. |
encoding |
Cách mã hóa văn bản thành ASCII |
B (base64) hoặc Q (biến thể quoted-printable) |
encoded-text |
Biểu diễn mã hóa | Chỉ ký tự ASCII |
B Encoding (Base64)
Sử dụng mã hóa base64 tiêu chuẩn. Tốt nhất cho văn bản có nhiều ký tự không phải ASCII, như kịch bản CJK:
; Subject: "Meeting confirmation" in Japanese Subject: =?UTF-8?B?5Lya6K2w44Gu56K66KqN?= ; From display name in Chinese From: =?UTF-8?B?5byg5LiJ?= <zhang@example.com>
Q Encoding (Biến Thể Quoted-Printable)
Mã hóa quoted-printable được sửa đổi tối ưu hóa cho tiêu đề. Giống như QP phần thân, các byte không phải ASCII trở thành các cặp thập lục phân =XX. Sự khác biệt chính: dấu cách được mã hóa dưới dạng dấu gạch dưới (_):
; Subject: "Café menu" with accented e Subject: =?UTF-8?Q?Caf=C3=A9_menu?= ; From display name: "René Dupont" From: =?UTF-8?Q?Ren=C3=A9_Dupont?= <rene@example.com> ; Subject: "Gruße aus Berlin" (German greetings) Subject: =?UTF-8?Q?Gru=C3=9Fe_aus_Berlin?=
Mã hóa Q có thể đọc được hơn khi phần lớn văn bản là ASCII chỉ có một vài ký tự không phải ASCII. Mã hóa B nhỏ gọn hơn khi phần lớn ký tự là không phải ASCII.
Nơi Encoded-Words Có Thể Xuất Hiện
Encoded-words được phép ở các vị trí cụ thể trong tiêu đề:
-
Subject, Comments, Keywords: Ở bất kỳ đâu có text (để thay thế cho
atomhoặcquoted-string). - From, To, Cc, Bcc, Reply-To, Sender: Chỉ trong phần tên hiển thị, không bao giờ trong địa chỉ email.
- Content-Description: Được phép để mô tả các phần MIME.
Encoded-words không được phép bên trong quoted-strings, trong local-part hoặc domain của địa chỉ email, hoặc làm giá trị tham số trong tiêu đề có cấu trúc như Content-Type (sử dụng RFC 2231 cho điều đó).
Chi Tiết Kỹ Thuật Chính
Giới Hạn Độ Dài
Mỗi encoded-word không được vượt quá 75 ký tự. Nếu văn bản được mã hóa dài hơn, nó phải được chia thành nhiều encoded-words được phân tách bằng folding whitespace (CRLF + dấu cách hoặc tab):
; Long subject split across two encoded-words Subject: =?UTF-8?B?5LuK5pel44Gu5Lya6K2w44Gr44Gk44GE44Gm?= =?UTF-8?B?44GU5qGI5YaF44GE44Gf44GX44G+44GZ?=
Khi hai encoded-words kề nhau được phân tách chỉ bằng whitespace tuyến tính, whitespace giữa chúng sẽ bị bỏ qua trong quá trình giải mã. Điều này cho phép chia nhỏ văn bản dài một cách liền mạch trên nhiều encoded-words.
Lựa Chọn Charset
Luôn sử dụng UTF-8 cho tin nhắn mới. Các charset khác tồn tại vì lý do di sản:
| Charset | Trường Hợp Sử Dụng | Khuyến Nghị |
|---|---|---|
UTF-8 |
Bao gồm tất cả ký tự Unicode | Luôn sử dụng |
ISO-8859-1 |
Di sản Âu Châu Phía Tây | Không sử dụng trong tin nhắn mới |
ISO-2022-JP |
Mã hóa di sản Tiếng Nhật | Vẫn thấy từ một số ứng dụng thư Tiếng Nhật |
GB2312 |
Di sản Tiếng Trung Giản Thể | Không sử dụng trong tin nhắn mới |
Tương Tác với Folding Tiêu Đề
RFC 5322 giới hạn dòng tiêu đề ở 998 ký tự và khuyến nghị giữ chúng dưới 78. Encoded-words tương tác với folding: bạn có thể chia giữa các encoded-words tại ranh giới whitespace, nhưng bạn không bao giờ được chia giữa một encoded-word. Trình bao bọc =?...?= phải nằm trên một dòng duy nhất.
Quy Tắc Giải Mã
Khi ứng dụng thư gặp một encoded-word, nó:
- Trích xuất charset, loại mã hóa và văn bản được mã hóa từ trình bao bọc
=?charset?encoding?text?=. - Giải mã văn bản bằng base64 (B) hoặc quoted-printable (Q).
- Diễn giải các byte thu được theo charset được khai báo.
- Hiển thị văn bản Unicode được giải mã cho người dùng.
Nếu ứng dụng không nhận ra charset, nó sẽ hiển thị encoded-word nguyên vẹn thay vì hiển thị văn bản bị hỏng.
Ví Dụ
Một Tin Nhắn Hoàn Chỉnh với Tiêu Đề Được Mã Hóa
MIME-Version: 1.0 From: =?UTF-8?Q?Ren=C3=A9_Dupont?= <rene@example.fr> To: =?UTF-8?B?5bGx55Sw5aSq6YOO?= <yamada@example.jp> Subject: =?UTF-8?Q?Re:_R=C3=A9union_du_15_mars?= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Bonjour Taro, Confirmons la r=C3=A9union pour le 15 mars.
Lưu ý: tiêu đề sử dụng encoded-words RFC 2047 (=?...?=), trong khi phần thân sử dụng mã hóa quoted-printable thông thường (=XX mà không có trình bao bọc). Đây là các cơ chế khác nhau cho các phần khác nhau của tin nhắn.
So Sánh Mã Hóa
Cùng một văn bản — "München" — được mã hóa cả hai cách:
; Q encoding: readable, good for mostly-ASCII text =?UTF-8?Q?M=C3=BCnchen?= ; B encoding: compact but opaque =?UTF-8?B?TcO8bmNoZW4=?=
Lỗi Phổ Biến
-
Mã hóa chính địa chỉ email. Chỉ tên hiển thị có thể được mã hóa.
=?UTF-8?Q?user?=@example.comkhông hợp lệ và sẽ bị từ chối hoặc hiểu sai. Đối với địa chỉ email quốc tế, xem RFC 6531/6532. -
Thiếu dấu cách giữa encoded-words và văn bản thông thường. Một encoded-word phải được phân tách từ văn bản liền kề bằng whitespace.
Hello=?UTF-8?Q?World?=không đúng định dạng; nó phải làHello =?UTF-8?Q?World?=. -
Chia một encoded-word trên nhiều dòng. Toàn bộ token
=?...?=phải vừa trên một dòng. Nếu bạn cần fold, chia thành nhiều encoded-words tại ranh giới từ. -
Sử dụng RFC 2047 trong tham số Content-Type. Encoded-words không hợp lệ trong các tham số tiêu đề có cấu trúc như
filename=hoặcname=. Sử dụng mã hóa tham số RFC 2231 thay thế:filename*=UTF-8''R%C3%A9sum%C3%A9.pdf. - Vượt quá giới hạn 75 ký tự. Mỗi encoded-word phải là 75 ký tự hoặc ít hơn. Văn bản dài phải được chia thành nhiều encoded-words. Các encoded-words quá lớn có thể bị cắt ngắn im lặng bởi các máy chủ thư.
-
Mã hóa kép. Mã hóa văn bản đã được mã hóa tạo ra rác như
=?UTF-8?Q?=3D=3FUTF-8=3FQ=3F...?=. Đảm bảo pipeline mã hóa của bạn chạy đúng một lần.
Tác Động Khả Năng Giao Hàng
- Mã hóa không chính xác kích hoạt bộ lọc thư rác. Encoded-words không đúng định dạng trong dòng Subject là dấu cảnh báo. Bộ lọc thư rác đã thấy hàng chục năm mã hóa bị hỏng từ công cụ thư rác. Mã hóa sạch sẽ tuân thủ tiêu chuẩn báo hiệu phần mềm gửi hợp pháp.
-
Mã hóa tên hiển thị ảnh hưởng đến tín nhiệm. Nếu tên hiển thị From chứa ký tự không phải ASCII không được mã hóa đúng, người nhận thấy văn bản
=?UTF-8?Q?...?=thô thay vì tên có thể đọc được. Điều này trông đáng ngờ và làm giảm tỷ lệ mở. - Hiển thị dòng Subject là quan trọng cho sự tham gia. Dòng Subject bị làm hỏng do charset sai hoặc mã hóa bị hỏng có nghĩa là người nhận không thể đọc được. Email được bỏ qua hoặc báo cáo là thư rác.
- Luôn sử dụng UTF-8. Các charset di sản như ISO-8859-1 không thể biểu diễn tất cả các ký tự. Nếu một hệ thống trộn lẫn charset trên các tiêu đề khác nhau, ứng dụng có thể hiển thị một số ký tự đúng và các ký tự khác là mojibake. Chuẩn hóa UTF-8 ở mọi nơi.
- Kiểm tra trên các ứng dụng. Outlook, Gmail, Apple Mail và Thunderbird đều có hành vi giải mã RFC 2047 hơi khác nhau, đặc biệt xung quanh các trường hợp biên như encoded-words dài và mã hóa/không mã hóa hỗn hợp trong một tiêu đề.