2009-09-15 6 views
8

Je vais avoir un problème emailing à l'aide de caractères unicode smtplib en Python 3. Cela échoue 3.1.1, mais fonctionne en 2.5.4:Python 3 smtplib envoyer avec des personnages unicode

import smtplib 
    from email.mime.text import MIMEText 

    sender = to = '[email protected]' 
    server = 'smtp.DEF.com' 
    msg = MIMEText('€10') 
    msg['Subject'] = 'Hello' 
    msg['From'] = sender 
    msg['To'] = to 
    s = smtplib.SMTP(server) 
    s.sendmail(sender, [to], msg.as_string()) 
    s.quit() 

J'ai essayé un exemple des docs, qui ont également échoué. http://docs.python.org/3.1/library/email-examples.html, le Envoyer le contenu d'un répertoire en tant qu'exemple de message MIME

Des suggestions?

+0

Pour clarifier les choses, en 2.5.4, il envoie sans message d'erreur, mais remplace '€' avec '?'. – foosion

Répondre

10

La clé est dans the docs:

class email.mime.text.MIMEText(_text, _subtype='plain', _charset='us-ascii') 

A subclass of MIMENonMultipart, the MIMEText class is used to create MIME objects of major type text. _text is the string for the payload. _subtype is the minor type and defaults to plain. _charset is the character set of the text and is passed as a parameter to the MIMENonMultipart constructor; it defaults to us-ascii. No guessing or encoding is performed on the text data.

donc ce que vous avez besoin est clairement, pasmsg = MIMEText('€10'), mais plutôt:

msg = MIMEText('€10'.encode('utf-8'), _charset='utf-8') 

Bien que pas si clairement documenté, sendmail a besoin d'une chaîne d'octets, pas d'un Unicode (c'est ce que le protocole SMTP spécifie); Regardez à quoi ressemble msg.as_string() pour chacune des deux façons de le construire - étant donné le "pas de deviner ou d'encoder", votre chemin a toujours ce caractère euro là (et aucun moyen pour sendmail de le transformer en un bytestring), le mien n'est pas (et utf-8 est clairement spécifié tout au long).

+0

Cela envoie sans générer un message d'erreur. J'ai envoyé à Thunderbird et Gmail. Thunderbird n'a montré que 10 comme le texte du message. Gmail a montré le plein 10 €. Python envoie comme 'content-transfer-encoding: base64' alors que Thunderbird envoie 10 € comme 'encodage de transfert de contenu: 8 bits' et gmail envoie 'multipart/alternative; boundary = ... 'Des suggestions pour générer un message que Thunderbird peut interpréter? – foosion

+0

Je ne suis pas un expert Thunderbird, mais essayez d'autres encodages tels que 'iso-8859-15'. Bien que tout programme de ces jours qui ne peut pas faire correctement utf-8 Vaut bien jeter dans la poubelle de l'histoire, l'esprit! -) –

+0

Le problème ne semble pas être iso-8859-15 ou utf-8, il semble être Content-transfer-encoding. Tout le reste que j'ai vérifié utilise 8 bits, tandis que python utilise base64. Contraindre l'en-tête à 8 bits n'aide pas. L'utilisation de quopri.encodestring() peut fonctionner pour obtenir un encodage 8 bits, mais je n'ai pas réussi à comprendre comment le faire fonctionner. – foosion

2

_charset Le paramètre MIMEText prend la valeur us-ascii par défaut selon docs. Depuis n'est pas de nous-ascii ensemble, il ne fonctionne pas.

exemple dans les documents que vous avez essayé clairement:

For this example, assume that the text file contains only ASCII characters.

Vous pouvez utiliser la méthode .get_charset sur votre message pour enquêter sur le charset, il est d'ailleurs .set_charset aussi bien.

+0

Comme vous le dites, le jeu de caractères est us-ascii, ce qui n'inclut pas €. L'utilisation de set_charset sur le msg ne résout pas le problème. Le problème (j'aurais dû être plus précis) est sur la ligne sendmail - UnicodeEncodeError: le codec 'ascii' ne peut pas encoder le caractère '\ x80' en position 161: ordinal pas en gamme (128) J'ai lu cela pour signifier que j'ai pour encoder le texte de sorte que tout est à portée (128), mais je n'ai pas été capable de comprendre comment. – foosion

+0

Je regardais le 3ème exemple sur la page des exemples, en envoyant un répertoire entier. J'ai essayé d'envoyer un répertoire composé d'un seul fichier zip en utilisant l'exemple. Cela a échoué. – foosion