18.11. rfc822 — 解析 RFC 2822 邮件头 — Python 文档
18.11. RFC822 — 解析 RFC 2822 邮件头
这个模块定义了一个类,Message,它代表一个“电子邮件”,如互联网标准 RFC 2822 所定义。 1 这样的消息由一组消息头和一个消息体组成。 该模块还定义了一个辅助类 AddressList 用于解析 RFC 2822 地址。 有关 RFC 2822 消息的特定语法的信息,请参阅 RFC。
mailbox 模块提供了读取各种最终用户邮件程序生成的邮箱的类。
- class rfc822.Message(file[, seekable])
Message 实例使用输入对象作为参数进行实例化。 Message 仅依赖于具有 readline() 方法的输入对象; 特别是,普通文件对象符合条件。 实例化从输入对象读取标题直到分隔符行(通常为空行)并将它们存储在实例中。 不使用标头后面的消息正文。
此类可以与支持 readline() 方法的任何输入对象一起使用。 如果输入对象具有搜索和告诉功能,则 rewindbody() 方法将起作用; 此外,非法行将被推回输入流。 如果输入对象缺少seek但有一个
unread()
方法可以推回一行输入,Message将使用它来推回非法行。 因此,此类可用于解析来自缓冲流的消息。提供可选的 seekable 参数作为某些 stdio 库的解决方法,其中
tell()
在发现lseek()
系统调用不起作用之前丢弃缓冲数据。 为了获得最大的可移植性,您应该将可搜索参数设置为零,以防止在传入不可搜索对象(例如从套接字对象创建的文件对象)时出现初始tell()
。从文件中读取的输入行可以由 CR-LF 或单个换行符终止; 在存储行之前,终止的 CR-LF 被单个换行符替换。
所有标头匹配都独立于大写或小写; 例如
m['From']
、m['from']
和m['FROM']
都产生相同的结果。
- class rfc822.AddressList(field)
- 您可以使用单个字符串参数实例化 AddressList 帮助器类,即要解析的 RFC 2822 地址的逗号分隔列表。 (参数
None
产生一个空列表。)
- rfc822.quote(str)
- 返回一个新字符串,其中 str 中的反斜杠被两个反斜杠替换,双引号被反斜杠-双引号替换。
- rfc822.unquote(str)
- 返回一个新字符串,它是 str 的 未加引号的 版本。 如果 str 以双引号结束并开始,它们将被剥离。 同样,如果 str 以尖括号结束并开始,它们将被剥离。
- rfc822.parseaddr(address)
- 解析 address,它应该是一些包含地址的字段的值,例如 To 或 Cc,解析为其组成的“真实姓名”和“电子邮件地址”部分. 返回该信息的元组,除非解析失败,在这种情况下返回 2 元组
(None, None)
。
- rfc822.dump_address_pair(pair)
- parseaddr() 的反函数,它采用
(realname, email_address)
形式的 2 元组,并返回适合 To 或 Cc 的字符串值] 标题。 如果 pair 的第一个元素为假,则第二个元素原封不动地返回。
- rfc822.parsedate(date)
- 尝试根据 RFC 2822 中的规则解析日期。 但是,有些邮件程序不遵循指定的格式,因此 parsedate() 尝试在这种情况下正确猜测。 date 是包含 RFC 2822 日期的字符串,例如
'Mon, 20 Nov 1995 19:12:08 -0500'
。 如果解析成功,parsedate()返回一个9元组,可以直接传递给time.mktime(); 否则将返回None
。 请注意,结果元组的索引 6、7 和 8 不可用。
- rfc822.parsedate_tz(date)
- 执行与 parsedate() 相同的功能,但返回
None
或 10 元组; 前 9 个元素组成一个元组,可以直接传递给 time.mktime(),第十个元素是日期时区与 UTC(格林威治标准时间的官方术语)的偏移量。 (注意时区偏移的符号与相同时区的time.timezone
变量的符号相反;后者变量遵循 POSIX 标准,而本模块遵循 RFC 2822。)如果输入字符串没有时区,则返回的元组的最后一个元素是None
。 请注意,结果元组的索引 6、7 和 8 不可用。
- rfc822.mktime_tz(tuple)
- 将 parsedate_tz() 返回的 10 元组转换为 UTC 时间戳。 如果元组中的时区项是
None
,则假定为本地时间。 轻微缺陷:这首先将前 8 个元素解释为本地时间,然后补偿时区差异; 这可能会在夏令时切换日期周围产生轻微错误。 不足以为普通使用担心。
也可以看看
- 模块电子邮件
- 全面的电子邮件处理包; 取代 rfc822 模块。
- 模块邮箱
- 读取最终用户邮件程序生成的各种邮箱格式的类。
- 模块 mimetools
- rfc822.Message 的子类,用于处理 MIME 编码的消息。
18.11.1. 消息对象
Message 实例具有以下方法:
- Message.rewindbody()
- 寻找消息正文的开头。 这仅在文件对象可查找时才有效。
- Message.isheader(line)
- 如果该行是合法的 RFC 2822 标头,则返回该行的规范化字段名(将用于索引它的字典键); 否则返回
None
(暗示应该在此处停止解析并将该行推回到输入流上)。 在子类中重写此方法有时很有用。
- Message.islast(line)
- 如果给定的行是 Message 应该停止的分隔符,则返回 true。 分隔符行被消耗,文件对象的读取位置紧随其后。 默认情况下,此方法仅检查该行是否为空,但您可以在子类中覆盖它。
- Message.iscomment(line)
- 如果给定的行应该被完全忽略,只是跳过,则返回
True
。 默认情况下,这是一个始终返回False
的存根,但您可以在子类中覆盖它。
- Message.getallmatchingheaders(name)
- 返回包含匹配 name 的所有标头的行列表(如果有)。 每个物理行,无论是否为延续行,都是一个单独的列表项。 如果没有标题匹配 name,则返回空列表。
- Message.getfirstmatchingheader(name)
- 返回包含匹配 name 的第一个标头及其后续行(如果有)的行列表。 如果没有头匹配 name,则返回
None
。
- Message.getrawheader(name)
- 返回由匹配 name 的第一个标头中冒号后的文本组成的单个字符串。 这包括前导空格、尾随换行以及内部换行和空格(如果存在任何续行)。 如果没有头匹配 name,则返回
None
。
- Message.getheader(name[, default])
- 返回由匹配 name 的最后一个标头组成的单个字符串,但去除前导和尾随空格。 内部空白不会被剥离。 可选的 default 参数可用于指定在没有标头匹配 name 时要返回的不同默认值; 默认为
None
。 这是获取解析标头的首选方法。
- Message.get(name[, default])
- getheader() 的别名,使界面与常规词典更兼容。
- Message.getaddr(name)
返回从
getheader(name)
返回的字符串中解析出的一对(full name, email address)
。 如果不存在匹配name的头部,则返回(None, None)
; 否则全名和地址都是(可能是空的)字符串。示例:如果 m 的第一个 From 标头包含字符串
'jack@cwi.nl (Jack Jansen)'
,则m.getaddr('From')
将产生('Jack Jansen', 'jack@cwi.nl')
对。 如果标头包含'Jack Jansen <jack@cwi.nl>'
,则会产生完全相同的结果。
- Message.getaddrlist(name)
这类似于
getaddr(list)
,但解析包含电子邮件地址列表的标头(例如 To 标头)并返回(full name, email address)
对的列表(即使标头中只有一个地址)。 如果没有头匹配 name,则返回一个空列表。如果存在多个与命名的标头匹配的标头(例如 如果有多个 Cc 标头),则全部解析地址。 命名标题包含的任何连续行也会被解析。
- Message.getdate(name)
使用 getheader() 检索标头并将其解析为与 time.mktime() 兼容的 9 元组; 请注意,字段 6、7 和 8 不可用。 如果没有匹配到 name 的头部,或者无法解析,则返回
None
。日期解析似乎是一门黑色艺术,并非所有邮件程序都遵守该标准。 虽然它已经过测试并在来自许多来源的大量电子邮件中被发现是正确的,但此功能仍有可能偶尔产生不正确的结果。
- Message.getdate_tz(name)
- 使用 getheader() 检索标头并将其解析为 10 元组; 前 9 个元素将使元组与 time.mktime() 兼容,第 10 个元素是给出日期时区与 UTC 的偏移量的数字。 请注意,字段 6、7 和 8 不可用。 与getdate()类似,如果没有匹配到name的header,或者无法解析,则返回
None
。
Message 实例也支持有限的映射接口。 特别是: m[name]
类似于 m.getheader(name)
但如果没有匹配的标头,则会引发 KeyError
; len(m)
、m.get(name[, default])
、name in m
、m.keys()
、m.values()
、m.items()
、正如预期的那样,唯一的区别是 setdefault()
使用空字符串作为默认值。 Message实例还支持映射可写接口m[name] = value
和del m[name]
。 Message 对象不支持映射接口的 clear()
、copy()、popitem()
或 update()
方法。 (仅在 Python 2.2 中添加了对 get()
和 setdefault()
的支持。)
最后, Message 实例有一些公共实例变量:
- Message.headers
- 一个包含整个标题行集的列表,按照它们被读取的顺序(除了 setitem 调用可能会干扰这个顺序)。 每行包含一个尾随换行符。 终止标题的空行不包含在列表中。
- Message.fp
- 在实例化时传递的文件或类似文件的对象。 这可用于读取消息内容。
- Message.unixfrom
- Unix
From
行,如果消息有一个,或者一个空字符串。 这需要在某些上下文中重新生成消息,例如mbox
样式的邮箱文件。
18.11.2. 地址列表对象
AddressList 实例具有以下方法:
- AddressList.__len__()
- 返回地址列表中的地址数。
- AddressList.__str__()
- 返回地址列表的规范化字符串表示形式。 地址以“名称”呈现< 主机@域 > 形式,逗号分隔。
- AddressList.__add__(alist)
- 返回一个新的 AddressList 实例,其中包含 AddressList 操作数中的所有地址,并删除重复项(设置联合)。
- AddressList.__iadd__(alist)
- __add__() 的就地版本; 将这个 AddressList 实例变成它自身和右侧实例 alist 的联合。
- AddressList.__sub__(alist)
- 返回一个新的 AddressList 实例,其中包含左侧 AddressList 操作数中的每个地址,而右侧地址操作数中不存在该地址(设置差异)。
- AddressList.__isub__(alist)
- __sub__() 的就地版本,删除此列表中的地址,这些地址也在 alist 中。
最后, AddressList 实例有一个公共实例变量:
- AddressList.addresslist
- 元组字符串对的列表,每个地址一个。 在每个成员中,第一个是规范化的名称部分,第二个是实际的路由地址(
'@'
分隔的用户名-主机.域对)。
脚注
- 1
- 该模块最初符合 RFC 822,因此得名。 从那时起,RFC 2822 作为 RFC 822 的更新发布。 该模块应被视为符合 RFC 2822,尤其是在自 RFC 822 以来语法或语义发生变化的情况下。