【问题标题】:Get python getaddresses() to decode encoded-word encoding获取 python getaddresses() 来解码编码字编码
【发布时间】:2011-05-08 15:48:13
【问题描述】:
msg = \
"""To: =?ISO-8859-1?Q?Caren_K=F8lter?= <ck@example.dk>, bob@example.com
Cc: "James =?ISO-8859-1?Q?K=F8lter?=" <jk@example.dk>
Subject: hello

message body blah blah blah

"""

import email.parser, email.utils
import itertools


parser = email.parser.Parser()
parsed_message = parser.parsestr(msg)

address_fields = ('to', 'cc')
addresses = itertools.chain(*(parsed_message.get_all(field) for field in address_fields if parsed_message.has_key(field)))
address_list = set(email.utils.getaddresses(addresses))


print address_list

看起来 email.utils.getaddresses() 似乎不会自动处理地址字段中的MIME RFC 2047

我怎样才能得到下面的预期结果?

实际结果:

set([('', 'bob@example.com'), ('=?ISO-8859-1?Q?Caren_K=F8lter?=', 'ck@example.dk'), ('James =?ISO-8859-1?Q?K=F8lter?=', 'jk@example.dk')])

想要的结果:

set([('', 'bob@example.com'), (u'Caren_K\xf8lter', 'ck@example.dk'), (u'James \xf8lter', 'jk@example.dk')])

【问题讨论】:

    标签: python email encoding mime


    【解决方案1】:

    谢谢 Gareth Rees。您的回答有助于解决问题案例:

    Input: 'application/octet-stream;\r\n\tname="=?utf-8?B?KFVTTXMpX0FSTE8uanBn?="'
    

    编码字周围没有空格导致email.Header.decode_header 忽略它。我对此太陌生了,不知道我是否只会让事情变得更糟,但是这个 kludge 以及加入 '' 而不是 ' ',修复了它:

    if not ' =?' in h:
        h = h.replace('=?', ' =?').replace('?=', '?= ')
    
    Output: u'application/octet-stream; name="(USMs)_ARLO.jpg"' 
    

    【讨论】:

      【解决方案2】:

      您想要的函数是email.header.decode_header,它返回(decoded_string, charset) 对的列表。您可以根据charset 对它们进行进一步解码,然后将它们重新组合在一起,然后再将它们传递给email.utils.getaddresses 或其他任何地方。

      您可能认为这很简单:

      def decode_rfc2047_header(h):
          return ' '.join(s.decode(charset or 'ascii')
                         for s, charset in email.header.decode_header(h))
      

      但由于消息标头通常来自不受信任的来源,因此您必须处理 (1) 编码错误的数据; (2) 伪造的字符集名称。所以你可能会这样做:

      def decode_safely(s, charset='ascii'):
          """Return s decoded according to charset, but do so safely."""
          try:
              return s.decode(charset or 'ascii', 'replace')
          except LookupError: # bogus charset
              return s.decode('ascii', 'replace')
      
      def decode_rfc2047_header(h):
          return ' '.join(decode_safely(s, charset)
                         for s, charset in email.header.decode_header(h))
      

      【讨论】:

        【解决方案3】:

        是的,email 包界面在很多时候确实不是很有帮助。

        在这里,您必须在每个地址上手动使用email.header.decode_header,然后,由于这会为您提供已解码令牌的列表,您必须再次手动将它们缝合在一起:

        for name, address in email.utils.getaddresses(addresses):
            name= u' '.join(
                unicode(b, e or 'ascii') for b, e in email.header.decode_header(name)
            )
            ...
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-09
          • 2019-12-19
          • 2012-04-10
          相关资源
          最近更新 更多