2009-09-15 10 views
8

Mam problem wysyłając unicode znaków za smtplib w Pythonie 3. To nie w 3.1.1, ale działa w 2.5.4:Python 3 smtplib wysłać ze znaków 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() 

Próbowałem przykład od dokumentów, które również zawiodły. http://docs.python.org/3.1/library/email-examples.html, Wyślij zawartość katalogu jako przykład wiadomości MIME

Jakieś sugestie?

+0

na celu wyjaśnienie, w 2.5.4, wysyła bez komunikatu o błędzie, ale zastępuje '€' z '?'. – foosion

Odpowiedz

10

Klucz jest w 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.

Więc co trzeba to jasno, niemsg = MIMEText('€10'), ale raczej:

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

Chociaż nie wszystko, co jasno udokumentowane, sendmail wymaga łańcucha bajtowego, a nie kodu Unicode (to właśnie określa protokół SMTP); spójrz na to, jak wygląda każdy z dwóch sposobów jego budowania - biorąc pod uwagę "brak zgadywania lub kodowania", twoja droga wciąż ma tam tę postać euro (i nie ma możliwości, aby sendmail przekształcił ją w bytestring), mój nie (i utf-8 jest wyraźnie określony w całym tekście).

+0

To wysyła bez generowania komunikatu o błędzie. Wysłałem do Thunderbirda i Gmaila. Thunderbird pokazał tylko 10 jako tekst wiadomości. Gmail pokazał pełne 10 EUR. Python wysyła jako "Content-transfer-encoding: base64", a Thunderbird wysyła 10 EUR jako "Content-transfer-encoding: 8-bit", a Gmail wysyła jako "multipart/alternative"; boundary = ... "Jakieś sugestie dotyczące generowania wiadomości, którą Thunderbird może zinterpretować? – foosion

+0

Nie jestem ekspertem od Thunderbirda, ale spróbuj innych kodowań, takich jak 'iso-8859-15'. Chociaż jakikolwiek program w dzisiejszych czasach, który nie może zrobić utf-8 właściwie JEST dobrze warty wrzucenie do śmietnika historii, umysłu! -) –

+0

Problem nie wydaje się być iso-8859-15 lub utf-8, wydaje się być kodowanie transferu treści. Wszystko, co sprawdziłem, używa 8-bitów, podczas gdy python używa base64. Konwertowanie nagłówka na 8-bitowe nie pomaga. Używanie quopri.encodestring() może działać, by uzyskać 8-bitowe kodowanie, ale nie byłem w stanie wymyślić, jak to zrobić. – foosion

2

_charset Parametr z jest domyślnie ustawiony na us-ascii zgodnie z docs. Ponieważ nie jest z nami - zestaw ascii nie działa.

przykład w docs że próbowałem jasno stwierdza:

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

Można użyć .get_charset sposób na wiadomości do zbadania charset istnieje notabene .set_charset również.

+0

Jak mówisz, zestaw znaków to us-ascii, który nie obejmuje €. Użycie set_charset w msg nie rozwiązuje problemu. Problem (powinienem być dokładniejszy) znajduje się na linii sendmail - UnicodeEncodeError: kodek 'ascii' nie może kodować znaku '\ x80' w pozycji 161: porządkowy nie w zakresie (128) Czytam to w ten sposób, że mam zakodować tekst tak, aby wszystko było w zasięgu (128), ale nie byłem w stanie wymyślić, jak to zrobić. – foosion

+0

Szukałem trzeciego przykładu na stronie przykładów, wysyłając cały katalog. Próbowałem wysłać katalog zawierający pojedynczy plik zip na przykładzie. To się nie udało. – foosion