- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用 Python 3.6.0b2。
我正在解析大量电子邮件。这封特定的电子邮件是一个问题,因为我无法打印电子邮件地址的显示名称。尝试打印电子邮件地址显示名称给出:
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc2' in position 30: surrogates not allowed
下面是一段测试用例代码,展示了如何重现问题:
(venv3.6) mailripper@ip-10-0-0-112:/opt/mailripper$ cat test.py
from email import policy
from email.headerregistry import Address
from email.parser import BytesHeaderParser, BytesParser
email_bytes = b'From: =?utf-8?Q?John_Smith=2C_Prince2=C2=AE=2CPMP=C2=AE=2C_CSM=C2?=\r\n =?utf-8?Q?=AE=2C_ITIL=C2=AE=2C_ISTQB=C2=AE?= <jon.smith@example.org>\r\n'
msg = BytesHeaderParser(policy=policy.default).parsebytes(email_bytes)
print(msg['from'])
print(msg['from'].addresses[0].display_name)
这是上面代码产生的错误:
(venv3.6) mailripper@ip-10-0-0-112:/opt/mailripper$ python test.py
"John Smith, Prince2®,PMP®, CSM� �, ITIL®, ISTQB®" <jon.smith@example.org>
Traceback (most recent call last):
File "test.py", line 8, in <module>
print(msg['from'].addresses[0].display_name)
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc2' in position 30: surrogates not allowed
这是 OSX 电子邮件客户端中显示的显示名称,它似乎能够正确解析它(这是屏幕截图,裁剪得很小):
我的目标是能够处理任何电子邮件而不会出现 unicode 错误,并且无需编写自定义 unicode 错误处理代码 - 这可能吗?
任何人都可以建议我可以做些什么来避免在显示电子邮件地址显示名称时出现 Unicode 错误吗?
最佳答案
你这里有一个棘手的问题。您的直接示例并不难:根据 RFC 2047 的规则,它是无效的. email.parser
模块有理由拒绝它。但是,电子邮件中充满了按规定无效的内容。电子邮件工具通常会努力从无效内容中挽救一些东西。您希望您的工具如何处理无效内容?
这是您的示例无效的地方。我把它缩短了一点。它的相关部分是这样的,
b'From: =?utf-8?Q?John=2C_PMP=C2=AE=2C_CSM=C2?=\r\n =?utf-8?Q?=AE=2C?= <jon@eg.org>\r\n'
这可能最初是字符串:From: John, PMP®, CSM®, <jon@eg.org>
.
这是一个 Python 字节字符串,包含一个 From:
header 作为编码词。规范是 RFC 2047, MIME Part Three: Message Header Extensions for Non-ASCII Text .
在示例中,您会看到两个序列,每个序列都是 =?utf-8?Q?
和 ?=
. RFC 2047, Section 2, "Syntax of encoded-words"告诉我们这些标记了两个 encoded-words 的开头和结尾,并且它们使用 UTF-8 字符集和 Quoted-Printable 编码。在“PMP”之后,是序列=C2=AE
。 .这编码了 2 个八位字节的 UTF-8 序列 0xC2 0xAE
, 即字符 '®'。序列 =2C
对 1 字节 UTF-8(和 ASCII)序列 0x2C 进行编码,即字符“,”。
第一个?=
之间的部分第二个=?utf-8?Q?
阅读,\r\n
.这是文字,未根据 RFC 2047 编码。它是通过插入行结尾和前导空白来延续长标题行。这也是相当合法的。
现在关注“CSM”。注意有一个序列 =C2
, 然后是第一个 ?=
这结束了第一个编码词。秒后=?utf-8?Q?
从第二个encoded-word开始,有一个序列=AE
.这是相同的 2 字节 UTF-8 序列 0xC2 0xAE
, 再次代表字符 '®'。但是,UTF-8 字符的两个八位位组在相邻的编码词 中分开。
这违反了 RFC 2047, Section 5, "Use of encoded-words in message headers" 的规则*。上面写着:
Each 'encoded-word' MUST represent an integral number of characters.
A multi-octet character may not be split across adjacent 'encoded-word's.
输入的这两个渲染中的任何一个都是有效的:
b'From: =?utf-8?Q?John=2C_PMP=C2=AE=2C_CSM=C2=AE?=\r\n =?utf-8?Q?=2C?= <jon@eg.org>\r\n'
b'From: =?utf-8?Q?John=2C_PMP=C2=AE=2C_CSM?=\r\n =?utf-8?Q?=C2=AE=2C?= <jon@eg.org>\r\n'
(这是我阅读规范时的结果。我没有运行代码来检查。)
现在,你问两个问题:
My goal is to be able to process any email without unicode errors, andwithout writing custom unicode error handling code - is that possible?
我的建议是“否”。如果您想处理任何电子邮件,您需要准备好处理格式不正确的电子邮件。您将需要编写自定义错误处理代码——不仅仅是针对 Unicode 问题,而是针对所有问题——以应对毫无疑问会被冲掉的奇怪东西。
Can anyone suggest what I can do to avoid getting Unicode errors whendisplaying email address display names?
对于这个例子,我可以看到三种方法:
看看 class email.policy.EmailPolicy(**kw)
看看你是否能想出如何扩展它来处理这种编码不正确的内容。您将此类的亲戚传递为 policy
在 BytesHeaderParser(policy=policy.default).parsebytes(email_bytes)
.
预处理所有标题行,查看此问题的连续编码字 结尾和开头的字节。使用您自己的代码修复它,然后将更正后的标题提供给 BytesHeaderParser()
.也许你可以写一个 regular expression这可以检测到问题。
将您的电话转接至 BytesHeaderParser()
在异常处理程序中,它将仅针对失败的行尝试#2 中的修复。修复线路后,您可以尝试 BytesHeaderParser()
再次。
还会有其他问题。考虑构建您的代码,以便能够在您发现需要时容纳越来越多的无效内容修复。
关于python - 'utf- 8' codec can' t 编码字符 '\udcc2' : surrogates not allowed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43335607/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
为什么在 C# 中添加两个 char 结果是 int 类型? 例如,当我这样做时: var pr = 'R' + 'G' + 'B' + 'Y' + 'P'; pr 变量变为 int 类型。我希望它是
下面的代码可以编译,但 char 类型的行为与 int 类型的行为不同。 特别是 cout ::ikIsX >() ::ikIsX >() ::ikIsX >() using names
我正在寻找一个正则表达式,它可以匹配长度为 1 个或多个字符但不匹配 500 的内容。这将在 Rails 路由文件中使用,特别是用于处理异常。 路线.rb match '/500', to: 'err
对于 C 编程作业,我正在尝试编写几个头文件来检查所谓的“X 编程语言”的语法。我最近才开始,正在编写第一个头文件。这是我编写的代码: #ifndef _DeclarationsChecker_h_
为什么扩展的 ascii 字符(â、é 等)被替换为 字符? 我附上了一张图片...但我正在使用 PHP 从 MySQL 中提取数据,其中一些位置有扩展字符...我使用的是 Arial 字体。 您可以
我有一个与 R 中的断线相关的简单问题。 我正在尝试粘贴,但在获取(字符/数字)之间的断线时遇到问题。请注意,这些值包含在向量中(V1=81,V2=55,V3=25)我已经尝试过这段代码: cat(p
如何将 ANSI 字符 (char) 转换为 Unicode 字符 (wchar_t),反之亦然? 是否有用于此目的的任何跨平台源代码? 最佳答案 是的,在 中你有mbstowcs()和 wcsto
函数 fromCharCode 不适用于国际 ANSI 字符。例如,对于 ID 为 192 到 223 的俄语 ANSI (cp-1251) 字符,它返回特殊字符。如何解决这个问题? 我认为,需要将A
如果不喜欢,我想隐藏 id,但不起作用 SELECT * FROM character, character_actor WHERE character.id NOT LIKE character_a
现在这个程序成功地反转了键盘输入的单词。但是我想在我反转它之前“保存”指针中的单词,所以我可以比较两者,反转的和“原始的”,并检查它们是否是回文。我还没有太多经验,可能会出现比我知道的更多的错误,但我
Memcpy 和 memcmp 函数可以接受指针变量吗? char *p; char* q; memcpy(p,q,10); //will this work? memcmp(p,q,10); //w
恐怕我对一个相当过饱和的主题的细节有疑问,我搜索了很多,但找不到一个明确的答案来解决这个特定的明显-imho-重要的问题: 使用UTF-8将byte[]转换为String时,每个字节(8bit)都变成
我有一个奇怪的问题。我需要从 stat 命令打印输出字符串。 我已经编写了获取一些信息的代码。 import glob import os for file in glob.glob('system1
我正在使用 Java 并具有其值如下所示的字符串, String data = "vale-cx"; data = data.replaceAll("\\-", "\\-\\"); 我正在替换其中的“
String urlParameters = "login=test&password=te&ff"; 我有一个String urlParams,& - 是密码的一部分,如何使其转义,从而不被识别为分
大家好,我只想从此字符串中提取第一个字母: String str = "使 徒 行 傳 16:31 ERV-ZH"; 我只想获取这些字符: 使 徒 行 傳 并且不包括 ERV-ZH 仅数
这个问题已经有答案了: Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized point
所以, 我有一个字符**;它本质上是一个句子,带有指向该句子中每个单词的指针;即 'h''i''\0''w''o''r''l''d''\0''y''a''y''!''\0' 在这种情况下,我希望使用可
这个问题在这里已经有了答案: Using quotation marks inside quotation marks (12 个答案) 关闭 7 年前。 如何打印 " 字符? 我知道打印 % 符号
我是一名优秀的程序员,十分优秀!