"email.utils": 其他工具
***********************

**源代码:** Lib/email/utils.py

======================================================================

"email.utils" 模块提供如下几个工具

email.utils.localtime(dt=None)

   以感知型 datetime 对象返回当地时间。 如果调用时参数为空，则返回当前
   时间。 否则 *dt* 参数应该是一个 "datetime" 实例，并根据系统时区数据
   库转换为当地时区。 如果 *dt* 是简单型的 （即 "dt.tzinfo" 是 "None"
   )，则假定为当地时间。 在这种情况下，为正值或零的 *isdst* 会使
   "localtime" 假定夏季时间（例如，夏令时）对指定时间（分别）生效或不
   生效。 负值 *isdst* 会使 "localtime" 预测夏季时间对指定时间是否生效
   。

   3.3 新版功能.

email.utils.make_msgid(idstring=None, domain=None)

   返回一个适合作为兼容 **RFC 2822** 的 *Message-ID* 标头的字符串。可
   选参数 *idstring* 可传入一字符串以增强该消息 ID 的唯一性。可选参数
   *domain* 可用于提供消息 ID 中字符 '@' 之后的部分，其默认值是本机的
   主机名。正常情况下无需覆盖此默认值，但在特定情况下覆盖默认值可能会
   有用，比如构建一个分布式系统，在多台主机上采用一致的域名。

   在 3.2 版更改: 增加了关键字 *domain*

下列函数是旧（"Compat32"）电子邮件 API 的一部分。新 API 提供的解析和格
式化在标头解析机制中已经被自动完成，故在使用新 API 时没有必要直接使用
它们函数。

email.utils.quote(str)

   返回一个新的字符串， *str* 中的反斜杠被替换为两个反斜杠，并且双引号
   被替换为反斜杠加双引号。

email.utils.unquote(str)

   返回 *str* 被去除引用版本的字符串。如果 *str* 开头和结尾均是双引号
   ，则这对双引号被去除。类似地，如果 *str* 开头和结尾都是尖角括号，这
   对尖角括号会被去除。

email.utils.parseaddr(address, *, strict=True)

   将地址（应为诸如 *To* 或者 *Cc* 之类包含地址的字段值）解析为构成之
   的 *真实名字* 和 *电子邮件地址* 部分。返回包含这两个信息的一个元组
   ；如若解析失败，则返回一个二元组 "('', '')" 。

   如果 *strict* 为真值，将使用拒绝错误形式输入的严格解析器。

   在 3.10.15 版更改: 增加了 *strict* 可选形参并将默认拒绝错误形式输入
   。

email.utils.formataddr(pair, charset='utf-8')

   是 "parseaddr()" 的逆操作，接受一个 "(真实名字, 电子邮件地址)" 的二
   元组，并返回适合于 *To* or *Cc* 标头的字符串。如果第一个元素为假性
   值，则第二个元素将被原样返回。

   可选地，如果指定 *charset*，则被视为一符合 **RFC 2047** 的编码字符
   集，用于编码 "真实名字" 中的非 ASCII 字符。可以是一个 "str" 类的实
   例，或者一个 "Charset" 类。默认为  "utf-8" 。

   在 3.3 版更改: 添加了 *charset* 选项。

email.utils.getaddresses(fieldvalues, *, strict=True)

   该方法返回一个与 "parseaddr()" 返回值形式相同的 2 元组。
   *fieldvalues* 是与 "Message.get_all" 返回值形式相同的由标头字段值组
   成的序列。

   如果 *strict* 为真值，将使用拒绝错误形式输入的严格解析器。

   下面简单示例可获取一条消息的所有接收方:

      from email.utils import getaddresses

      tos = msg.get_all('to', [])
      ccs = msg.get_all('cc', [])
      resent_tos = msg.get_all('resent-to', [])
      resent_ccs = msg.get_all('resent-cc', [])
      all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)

   在 3.10.15 版更改: 增加了 *strict* 可选形参并将默认拒绝错误形式输入
   。

email.utils.parsedate(date)

   尝试根据 **RFC 2822** 的规则解析一个日期。然而，有些寄信人不严格遵
   守这一格式，所以这种情况下 "parsedate()" 会尝试猜测其形式。*date*
   是一个字符串包含了一个形如 ""Mon, 20 Nov 1995 19:12:08 -0500"" 的
   **RFC 2822** 格式日期。如果日期解析成功， "parsedate()" 将返回一个
   九元组，可直接传递给 "time.mktime()"；否则返回 "None"。注意返回的元
   组中下标为 6、7、8 的部分是无用的。

email.utils.parsedate_tz(date)

   执行与 "parsedate()" 相同的功能，但会返回 "None" 或是一个 10 元组；
   前 9 个元素构成一个可以直接传给 "time.mktime()" 的元组，而第十个元
   素则是该日期的时区与 UTC (格林威治平均时 GMT 的正式名称) [1] 的时差
   。 如果输入字符串不带时区，则所返回元组的最后一个元素将为 "0"，这表
   示 UTC。 请注意结果元组的索引号 6, 7 和 8 是不可用的。

email.utils.parsedate_to_datetime(date)

   "format_datetime()" 的逆操作。 执行与 "parsedate()" 相同的功能，但
   会在成功时返回一个 "datetime"；否则如果 *date* 包含无效的值例如小时
   值大于 23 或时区偏移量不在 -24 和 24 时范围之内则会引发
   "ValueError"。 如果输入日期的时区值为 "-0000"，则 "datetime" 将为一
   个简单形 "datetime"，而如果日期符合 RFC 标准则它将代表一个 UTC 时间
   ，但是并不指明日期所在消息的实际源时区。 如果输入日期具有任何其他有
   效的时区偏移量，则 "datetime" 将是一个感知型 "datetime" 并与
   "timezone" "tzinfo" 相对应。

   3.3 新版功能.

email.utils.mktime_tz(tuple)

   将 "parsedate_tz()" 所返回的 10 元组转换为一个 UTC 时间戳（相距
   Epoch 纪元初始的秒数）。 如果元组中的时区项为 "None"，则视为当地时
   间。

email.utils.formatdate(timeval=None, localtime=False, usegmt=False)

   返回 **RFC 2822** 标准的日期字符串，例如:

      Fri, 09 Nov 2001 01:08:47 -0000

   可选的 *timeval* 如果给出，则是一个可被 "time.gmtime()" 和
   "time.localtime()" 接受的浮点数时间值，否则会使用当前时间。

   可选的 *localtime* 是一个旗标，当为 "True" 时，将会解析 *timeval*，
   并返回一个相对于当地时区而非 UTC 的日期值，并会适当地考虑夏令时。
   默认值 "False" 表示使用 UTC。

   可选的 *usegmt* 是一个旗标，当为 "True" 时，将会输出一个日期字符串
   ，其中时区表示为 ascii 字符串 "GMT" 而非数字形式的 "-0000"。 这对某
   些协议（例如 HTTP）来说是必要的。 这仅在 *localtime* 为 "False" 时
   应用。 默认值为 "False"。

email.utils.format_datetime(dt, usegmt=False)

   类似于 "formatdate"，但输入的是一个 "datetime" 实例。 如果实例是一
   个简单型 datetime，它会被视为 "不带源时区信息的 UTC"，并且使用传统
   的 "-0000" 作为时区。 如果实例是一个感知型 "datetime"，则会使用数字
   形式的时区时差。 如果实例是感知型且时区时差为零，则 *usegmt* 可能会
   被设为 "True"，在这种情况下将使用字符串 "GMT" 而非数字形式的时区时
   差。 这提供了一种生成符合标准 HTTP 日期标头的方式。

   3.3 新版功能.

email.utils.decode_rfc2231(s)

   根据 **RFC 2231** 解码字符串 *s*。

email.utils.encode_rfc2231(s, charset=None, language=None)

   根据 **RFC 2231** 对字符串 *s* 进行编码。 可选的 *charset* 和
   *language* 如果给出，则为指明要使用的字符集名称和语言名称。 如果两
   者均未给出，则会原样返回 *s*。 如果给出 *charset* 但未给出
   *language*，则会使用空字符串作为 *language* 值来对字符串进行编码。

email.utils.collapse_rfc2231_value(value, errors='replace', fallback_charset='us-ascii')

   当以 **RFC 2231** 格式来编码标头形参时，"Message.get_param" 可能返
   回一个包含字符集、语言和值的 3 元组。 "collapse_rfc2231_value()" 会
   将此返回为一个 unicode 字符串。 可选的 *errors* 会被传递给 "str" 的
   "encode()" 方法的 *errors* 参数；它的默认值为 "'replace'"。 可选的
   *fallback_charset* 指定当 **RFC 2231** 标头中的字符集无法被 Python
   识别时要使用的字符集；它的默认值为 "'us-ascii'"。

   为方便起见，如果传给 "collapse_rfc2231_value()" 的 *value* 不是一个
   元组，则应为一个字符串并会将其原样返回。

email.utils.decode_params(params)

   根据 **RFC 2231** 解码参数列表。 *params* 是一个包含 "(content-
   type, string-value)" 形式的元素的 2 元组的序列。

-[ 备注 ]-

[1] 请注意时区时差的符号与同一时区的 "time.timezone" 变量的符号相反；
    后者遵循 POSIX 标准而此模块遵循 **RFC 2822**。
