将 XML 文件作为附件通过电子邮件发送时对 Content-Transfer-Encoding 感到困惑
Confused about Content-Transfer-Encoding when emailing an XML file as an attachment
我有一个 UTF-8 编码的 XML 文件,它作为附件通过电子邮件发送。当电子邮件收件人打开电子邮件并保存附件时,XML 文件不再是 UTF-8(而是报告 ANSI 编码)。在这种情况下,如果重要的话,收件人使用的是 Microsoft Outlook。
我在一个无法依赖合适的 MIME 库可用性的环境中进行编程,因此我需要了解哪里出错了。
在通过电子邮件发送 XML 文件之前,在服务器上创建它之后,我可以使用 Linux 文件命令看到它是一个 UTF-8 文件。除此之外,XML 还有一个版本 header <?xml version="1.0" encoding="UTF-8"?>
(这与我的问题并不相关,但为了完整起见,我将其包括在内)。我很确定我通过电子邮件发送文件的代码是这里的问题,但我不确定 "right" 执行此操作的方法。
我发送的 header 是:
"Mime-Version" "1.0"
"Content-Type" "multipart/mixed; boundary="__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___"\n\n"
邮件的body是:
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___\n
Content-Type: text/plain; charset="utf-8"; format=flowed\n
Content-Transfer-Encoding: 7bit\n\n
Please find attached the data file generated
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___\n
Content-Type: text/plain; charset="utf-8"\n
Content-Disposition: attachment; filename="My_File_Name"\n\n
XML FILE CONTENTS GO HERE
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___--\n
问题:
- 我应该使用
quoted-printable
、8bit
还是其他类型的
Content-Transfer-Encoding
在这里?我已经尝试了所有这些,但是它
没有改变结果。
Content-Type: text/plain
对于 XML 附件是否正确?
- 还有其他建议吗?
通过指定 text/plain
,您基本上将控制权交给了远程客户端的 text-handling 能力,在这种特殊情况下,这些能力显然是有限的。 XML 是规范的 Unicode,因此通过选择更好的 content-type,您更有可能成功。尝试使用 text/xml
或 application/xml
,甚至是完全不透明的 application/octet-stream
,它应该 仅 允许收件人将其保存在磁盘上 [=67] =] 相同的形式。
内容传输编码根本不会影响此行为,但由于您似乎不清楚其意义,因此这里进行简要讨论。
content-transfer-encoding完全透明;它不会影响交付的内容或远程客户端可以使用它做什么。选择哪种内容传输编码取决于数据的性质和需要传输的电子邮件系统的功能。如果它不是 8-bit clean,你需要一个 7-bit CTE 来封装它。如果内容的行太长而无法放入 SMTP,则需要将其封装到行较短的内容中。但是远程客户端将提取另一端封装内的任何内容。视情况而定。
有针对不同情况的内容传输编码层次结构:
7bit
如果您的数据完全是 7 位 ASCII 并且没有超过大约 990 个字符的行,则合适。然后它甚至可以在未经修改的情况下在原始的旧 SMTP 传输中存活下来。在没有任何显式 Content-Transfer-Encoding:
header 的情况下,这是根据标准的默认设置(尽管您经常看到其中包含 8 位数据但没有显式 CTE,甚至带有显式 7bit
声明)。
8bit
放宽了对数据为 7 位干净的要求。如果传输此消息的所有系统都支持 ESMTP 8BITMIME
扩展,这对于行长度受限的数据应该没问题。
binary
还允许无限行长度。理论上,您应该能够使用它来传递不受限制的内容,但实际上,当系统不严格遵守规范时,这似乎会引发故障。一个典型的症状是超长线路在运输过程中被截断或折叠,破坏了有效载荷的完整性。为避免此类问题(并更好地遵守互操作性标准的文字和精神),您最好采用以下方法之一。
base64
接受不受限制的内容,但以满足对受限行长度和严格受限的 7 位字符库的严格要求的格式对其进行编码。它将有效负载扩展到原始大小的 4/3 多一点。示例:
ugqcA7R5cPq667vNaSifRUH9HsW00NqZ1gwICk0pNrUkXFpNIFOpbf3o
5ml8cqqSygkp8KBgPbHrqnDXvZTEBOkNo7ThE+BAvexa75Tm0Ebo/Yjl
y697pMp1+dnSlk3YTqxkPI9vqpple13dXLHlvnFDmSi0gqIMSwo7kUFD
SivAWhyCBR6tFO3lY1Pk6lz78+zgL28VthI72kVRkrWWtzoFef/4u5Ip
GR00CtsNNEJo01GAQGpkTNFT9U9Q/UI9CMGgaI9E9RkMaTDTQICBEyaE
woSCQOrNGA==
quoted-printable
同样接受任意内容,但将选定字节编码为原始字节的 3 倍。当大部分输入是 ASCII 时,这是可以容忍的开销。换句话说,这适用于带有偶尔 non-ASCII 内容的大致文本格式,例如使用 8 位编码的许多西方语言中的文本,或像 HTML 这样的格式,其中 ASCII 标记在实际中占主导地位几乎任何语言的内容。示例:
<?xml version=3D"1.0" encoding=3D"UTF-8"?>h=C3=ABll=C3=B6 =
w=C3=B6rld
Quoted printable 一点也不难实现,似乎适合您的场景。
所有这些都编入了 MIME RFC 2045 through 2048. Wikipedia has nice readable articles about e.g. base64 and quoted-printable。
从您的描述中不清楚您是只是声明您的内容是quoted-printable,还是实际上对其进行了编码。我见过人们做前者,当它不起作用时表现得很惊讶,但希望你做的是后者。只是一个警示故事。
我有一个 UTF-8 编码的 XML 文件,它作为附件通过电子邮件发送。当电子邮件收件人打开电子邮件并保存附件时,XML 文件不再是 UTF-8(而是报告 ANSI 编码)。在这种情况下,如果重要的话,收件人使用的是 Microsoft Outlook。
我在一个无法依赖合适的 MIME 库可用性的环境中进行编程,因此我需要了解哪里出错了。
在通过电子邮件发送 XML 文件之前,在服务器上创建它之后,我可以使用 Linux 文件命令看到它是一个 UTF-8 文件。除此之外,XML 还有一个版本 header <?xml version="1.0" encoding="UTF-8"?>
(这与我的问题并不相关,但为了完整起见,我将其包括在内)。我很确定我通过电子邮件发送文件的代码是这里的问题,但我不确定 "right" 执行此操作的方法。
我发送的 header 是:
"Mime-Version" "1.0"
"Content-Type" "multipart/mixed; boundary="__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___"\n\n"
邮件的body是:
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___\n
Content-Type: text/plain; charset="utf-8"; format=flowed\n
Content-Transfer-Encoding: 7bit\n\n
Please find attached the data file generated
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___\n
Content-Type: text/plain; charset="utf-8"\n
Content-Disposition: attachment; filename="My_File_Name"\n\n
XML FILE CONTENTS GO HERE
--__==NAHDHDH2.28ABSDJxjhkjhsdkjhd___--\n
问题:
- 我应该使用
quoted-printable
、8bit
还是其他类型的Content-Transfer-Encoding
在这里?我已经尝试了所有这些,但是它 没有改变结果。 Content-Type: text/plain
对于 XML 附件是否正确?- 还有其他建议吗?
通过指定 text/plain
,您基本上将控制权交给了远程客户端的 text-handling 能力,在这种特殊情况下,这些能力显然是有限的。 XML 是规范的 Unicode,因此通过选择更好的 content-type,您更有可能成功。尝试使用 text/xml
或 application/xml
,甚至是完全不透明的 application/octet-stream
,它应该 仅 允许收件人将其保存在磁盘上 [=67] =] 相同的形式。
内容传输编码根本不会影响此行为,但由于您似乎不清楚其意义,因此这里进行简要讨论。
content-transfer-encoding完全透明;它不会影响交付的内容或远程客户端可以使用它做什么。选择哪种内容传输编码取决于数据的性质和需要传输的电子邮件系统的功能。如果它不是 8-bit clean,你需要一个 7-bit CTE 来封装它。如果内容的行太长而无法放入 SMTP,则需要将其封装到行较短的内容中。但是远程客户端将提取另一端封装内的任何内容。视情况而定。
有针对不同情况的内容传输编码层次结构:
7bit
如果您的数据完全是 7 位 ASCII 并且没有超过大约 990 个字符的行,则合适。然后它甚至可以在未经修改的情况下在原始的旧 SMTP 传输中存活下来。在没有任何显式Content-Transfer-Encoding:
header 的情况下,这是根据标准的默认设置(尽管您经常看到其中包含 8 位数据但没有显式 CTE,甚至带有显式7bit
声明)。8bit
放宽了对数据为 7 位干净的要求。如果传输此消息的所有系统都支持 ESMTP8BITMIME
扩展,这对于行长度受限的数据应该没问题。binary
还允许无限行长度。理论上,您应该能够使用它来传递不受限制的内容,但实际上,当系统不严格遵守规范时,这似乎会引发故障。一个典型的症状是超长线路在运输过程中被截断或折叠,破坏了有效载荷的完整性。为避免此类问题(并更好地遵守互操作性标准的文字和精神),您最好采用以下方法之一。base64
接受不受限制的内容,但以满足对受限行长度和严格受限的 7 位字符库的严格要求的格式对其进行编码。它将有效负载扩展到原始大小的 4/3 多一点。示例:
ugqcA7R5cPq667vNaSifRUH9HsW00NqZ1gwICk0pNrUkXFpNIFOpbf3o
5ml8cqqSygkp8KBgPbHrqnDXvZTEBOkNo7ThE+BAvexa75Tm0Ebo/Yjl
y697pMp1+dnSlk3YTqxkPI9vqpple13dXLHlvnFDmSi0gqIMSwo7kUFD
SivAWhyCBR6tFO3lY1Pk6lz78+zgL28VthI72kVRkrWWtzoFef/4u5Ip
GR00CtsNNEJo01GAQGpkTNFT9U9Q/UI9CMGgaI9E9RkMaTDTQICBEyaE
woSCQOrNGA==
quoted-printable
同样接受任意内容,但将选定字节编码为原始字节的 3 倍。当大部分输入是 ASCII 时,这是可以容忍的开销。换句话说,这适用于带有偶尔 non-ASCII 内容的大致文本格式,例如使用 8 位编码的许多西方语言中的文本,或像 HTML 这样的格式,其中 ASCII 标记在实际中占主导地位几乎任何语言的内容。示例:
<?xml version=3D"1.0" encoding=3D"UTF-8"?>h=C3=ABll=C3=B6 =
w=C3=B6rld
Quoted printable 一点也不难实现,似乎适合您的场景。
所有这些都编入了 MIME RFC 2045 through 2048. Wikipedia has nice readable articles about e.g. base64 and quoted-printable。
从您的描述中不清楚您是只是声明您的内容是quoted-printable,还是实际上对其进行了编码。我见过人们做前者,当它不起作用时表现得很惊讶,但希望你做的是后者。只是一个警示故事。