2010-11-11 3 views
2
msg = \ 
"""To: =?ISO-8859-1?Q?Caren_K=F8lter?= <[email protected]>, [email protected] 
Cc: "James =?ISO-8859-1?Q?K=F8lter?=" <[email protected]> 
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 

getaddresses python() Il semble que email.utils.getaddresses() ne semble pas gérer automatiquement MIME RFC 2047 dans les champs d'adresse.Familiarisez décoder le codage mot codé

Comment puis-je obtenir le résultat attendu ci-dessous?

résultat réel:

set([('', '[email protected]'), ('=?ISO-8859-1?Q?Caren_K=F8lter?=', '[email protected]'), ('James =?ISO-8859-1?Q?K=F8lter?=', '[email protected]')])

résultat souhaité:

set([('', '[email protected]'), (u'Caren_K\xf8lter', '[email protected]'), (u'James \xf8lter', '[email protected]')])

Répondre

3

La fonction que vous voulez est email.header.decode_header, qui retourne une liste de (decoded_string, charset) paires. C'est à vous de les décoder davantage selon charset et de les rejoindre à nouveau avant de les passer à email.utils.getaddresses ou ailleurs.

Vous pourriez penser que ce serait simple:

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

Mais depuis les en-têtes de messages proviennent généralement de sources non fiables, vous devez gérer (1) Les données mal codées; et (2) de faux noms de jeux de caractères. Donc, vous pourriez faire quelque chose comme ceci:

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)) 
1

Oui, l'interface paquet email est vraiment pas très utile beaucoup de temps.

Ici, vous devez utiliser email.header.decode_header manuellement sur chaque adresse, puis, depuis que vous donne une liste de jetons décodés, vous devez les assembler à nouveau ensemble manuellement:

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) 
    ) 
    ... 
0

Merci Gareth Rees .Votre réponse m'a été utile dans la résolution d'un cas de problème:

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

l'absence d'espaces autour du mot codé causé email.Header.decode_header à négliger. Je suis trop nouveau à ce sujet pour savoir si j'ai seulement fait empirer les choses, mais ce kludge, avec joindre avec un '' au lieu de '', l'a réparé:

if not ' =?' in h: 
    h = h.replace('=?', ' =?').replace('?=', '?= ') 

Output: u'application/octet-stream; name="(USMs)_ARLO.jpg"' 
Questions connexes