"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.9.20 版更改: 增加了 *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.9.20 版更改: 增加了 *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)

   The inverse of "format_datetime()".  Performs the same function as
   "parsedate()", but on success returns a "datetime".  If the input
   date has a timezone of "-0000", the "datetime" will be a naive
   "datetime", and if the date is conforming to the RFCs it will
   represent a time in UTC but with no indication of the actual source
   timezone of the message the date comes from.  If the input date has
   any other valid timezone offset, the "datetime" will be an aware
   "datetime" with the corresponding a "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**。
