19.1.14. "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)

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

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)

   该方法返回一个形似 "parseaddr()" 返回的二元组的列表。 *fieldvalues*
   是一个序列，包含了形似 "Message.get_all" 返回值的标头字段值。获取了
   一消息的所有收件人的简单示例如下：

      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)

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)

   Performs the same function as "parsedate()", but returns either
   "None" or a 10-tuple; the first 9 elements make up a tuple that can
   be passed directly to "time.mktime()", and the tenth is the offset
   of the date's timezone from UTC (which is the official term for
   Greenwich Mean Time) [1].  If the input string has no timezone, the
   last element of the tuple returned is "None".  Note that indexes 6,
   7, and 8 of the result tuple are not usable.

email.utils.parsedate_to_datetime(date)

   "format_datetime()" 的逆操作。 执行与 "parsedate()" 相同的功能，但
   会在成功时返回一个 "datetime"。 如果输入日期的时区值为 "-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**。
