MIME协议规定首部必须只包含ASCII字符,但有时我们不得不需要包含一些非ASCII的字符,例如,SMTP中邮件的标题Subject就常常是非ASCII编码的字符。这时候就需要引入Encoded-Word,或者称之为扩展编码。
Encoded-Word的格式如下:
=?charset?encoding?data?=
其中:
- charset指定字符集,如UTF-8。
- encoding指定二进制编码方式,即用ASCII字符表示二进制的方式,取值范围为Q或者B,Q代表Q-encoding(这个不太清楚),而B代表常见的Base64。
- data指定使用encoding编码后的二进制数据。
栗子
假设现在要使用SMTP协议发送的邮件标题原定为:
Subject: 你好世界
由于不允许首部出现非ASCII字符,那么需要将“你好世界”需要转换为Encoded-Word形式。假设使用字符集为UTF-8,那么可以从以下的流水线里计算编码后的结果:
- 将“你好世界”使用根据UTF-8字符集转换为二进制,结果为12个字节(十六进制表示):0xE4 0xBD 0xA0 0xE5 0xA5 0xBD 0xE4 0xB8 0x96 0xE7 0x95 0x8C
- 将上面12字节的二进制使用Base64编码,得到结果:5L2g5aW95LiW55WM
- 返回结果:=?UTF-8?B?5L2g5aW95LiW55WM?=
因此,可以将原标题转换为下列合法的形式:
Subject: =?UTF-8?B?5L2g5aW95LiW55WM?=
收件方显示的标题即为“你好世界”。
实例代码
这里给出计算Encoded-Word的C#示例:
/// <summary>
/// 对字符串以指定的字符集进行基于Base64的扩展首部编码。
/// </summary>
/// <param name="data">需要编码的字符串。</param>
/// <param name="e">指定的字符集,默认为UTF8。</param>
/// <returns>编码后的字符串。</returns>
string Base64ExtendedWordEncode(string data, Encoding e = null)
{
if (data == null) return "";
if (e == null) e = Encoding.UTF8;
byte[] buffer = e.GetBytes(data);
return "=?" + e.HeaderName.ToUpper() + "?B?" + Convert.ToBase64String(buffer) + "?=";
}