[Risolto][Python3][sendmail] encoding/decoding di email

Linguaggi di programmazione: php, perl, python, C, bash, ecc.

[Risolto][Python3][sendmail] encoding/decoding di email

Messaggioda rai » sabato 18 marzo 2017, 20:31

Un saluto a tutti.

Uno script (peraltro funzionante senza errori) invia una mail e *alcuni* destinatari non ne leggono i caratteri nonASCII. Per dire: gli stessi caratteri diventano leggibili se quel destinatario inoltra quella stessa mail su Gmail.
La stringa che costituisce il corpo della mail viene estratta da un file di appoggio creato localmente. Questa è la mia localizzazione
Codice: Seleziona tutto
$ locale
LANG=it_IT.UTF-8
LANGUAGE=it:fr:en
LC_CTYPE="it_IT.UTF-8"
LC_NUMERIC=it_IT.UTF-8
LC_TIME=it_IT.UTF-8
LC_COLLATE="it_IT.UTF-8"
LC_MONETARY=it_IT.UTF-8
LC_MESSAGES="it_IT.UTF-8"
LC_PAPER=it_IT.UTF-8
LC_NAME=it_IT.UTF-8
LC_ADDRESS=it_IT.UTF-8
LC_TELEPHONE=it_IT.UTF-8
LC_MEASUREMENT=it_IT.UTF-8
LC_IDENTIFICATION=it_IT.UTF-8
LC_ALL=


Penso che sia un problema mio e non (solo) dei destinatari perché se eseguo l' invio con uno script bash, a partire dallo stesso file di testo, i caratteri si leggono tutti, e anche sui destinatari `problematici'. Quindi deve esserci un modo per evitare questo fastidio ma non mi raccapezzo.

posto il frammento che ritengo utile, sfoltito dagli import e da tutti i controlli di errori ed eccezioni
Codice: Seleziona tutto
[ . . . ]
ilTXT = "/tmp/{}.txt".format(CognomeNome) # il file di testo (creato con libreoffice)
with open(ilTXT, "r") as f:
    testo = f.read()
for regex in LISTAREGEX:
    match = re.search(regex, testo, re.DOTALL)
    if 'oggetto1' in regex:
        SUBJECT = match.group(0).strip()
    elif 'contatti' in regex:
        TO = match.group(0).strip()
    elif 'messaggio1' in regex:
        BODY = match.group(0).strip()

#
#   costruisce le mail   #
#¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
message = """\
From: {}
To: {}
Subject: {}

{}
""".format(USER, TO, SUBJECT, BODY)

#
#   invia le mail   #
#¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
listaDestinatari = TO.split(',')

s = smtplib.SMTP_SSL(smtpSERVER)invio
s.login(USER, password)
s.sendmail(USER, listaDestinatari, message.encode('utf-8')) # <------- ecco il punto
s.quit
[ . . . ]
ma se servisse posto tutto il malloppo, l'ho sfoltito sperando di invogliare di più alla lettura i volenterosi
Grazie
Ultima modifica di rai il giovedì 23 marzo 2017, 17:07, modificato 1 volta in totale.
rai
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1871
Iscrizione: maggio 2008
Località: Palermo
Distribuzione: 12.04 | 16.04

Re: [Python3] encoding/decoding di caratteri

Messaggioda crap0101 » sabato 18 marzo 2017, 23:28

ipotizzo che il problema sia appunto la codifica in utf-8... certi "visualizzatori" probabilmente sono abbastanza "furbi" da riconoscere che non è testo ascii e quindi lo decodificano correttamente, mentre altri non lo fanno e - in mancanza di specifiche - lo trattano come "plain text".
btw, nella doc del metodo sendmail() si dice appunto che il parametro "msg" dev'essere:
msg may be a string containing characters in the ASCII range, or a byte string

per cui è possibile che testo codificato diversamente dia problemi.

In un prog che mi pare ti avevo già linkato avevo fato diversamente, creando una classe per i messaggi esclusivamente in ascii e altre per quelli più "complessi", di cui ti riporto un estratto:

Codice: Seleziona tutto
class PlainMsg(MailMessage):
    """Plain text mail object."""
    def __init__(self, sender, receiver, subject, text):
        super(PlainMsg, self).__init__(
            sender, receiver, subject, text, None);

    def get_message(self, receiver=None):
        receiver = receiver if receiver is not None else self.receiver
        _time = mmutils.mail_format_time()
        return ("From: %s\r\nTo: %s\r\nSubject: %s\r\n"
                "Date: %s\r\nX-Mailer: %s\r\n\r\n%s"
                % (self.sender, receiver, self.subject,
                   _time, self.xmailer, self.text))

class MimeMsg(MailMessage):
    """Plain text mail object."""
    def __init__(self, sender, receiver, subject, text, ttype, attachments):
        super(MimeMsg, self).__init__(
            sender, receiver, subject, text, attachments)
        self.text_type = ttype
        self.build()

    def build(self):
        if not self.attachments:
            if self.text_type == 'html':
                self.msg = MIMENonMultipart('text', 'html')
            else:
                self.msg = MIMENonMultipart('text', 'plain', charset='utf-8')
            self.msg.set_payload(self.text)
            self.msg['boundary'] = self.delimiter
        else:
            self.msg = MIMEMultipart(boundary=self.delimiter)
            if self.text_type == 'html':
                self.msg.attach(MIMEText(self.text, 'html'))
            else:



in cui come vedi uso il modulo email.mime che semplifica un po' le cose... e che vedo nella stdlib di py3 è stato almeno in parte sostituito da email.contentmanager
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8149
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: [Python3] encoding/decoding di caratteri

Messaggioda rai » domenica 19 marzo 2017, 13:53

Grazie crap0101, ho fatto tesoro del programma che hai condiviso in questa discussione, tra l'altro anche applicando la classe email.mime.text.MIMEText() che determina Content-Type e charset in modo trasparente all'utente.
Ma l'ho usata solo per costruire mail con allegati. Per mail non-multipart mi era sembrato overkill usare il modulo email per costruire il messaggio e invece ...

Comunque la doc di sendmail, che tu citi, mi sembra migliorabile: dice di fornire il msg come bytes, che è appunto quello che fa il mio script, ma non avvisa ( se non fra le righe ) della possibile mis-decodifica da parte dei destinatari.
rai
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1871
Iscrizione: maggio 2008
Località: Palermo
Distribuzione: 12.04 | 16.04

Re: [Python3] encoding/decoding di caratteri

Messaggioda crap0101 » lunedì 20 marzo 2017, 23:05

uhm... nel codice che hai postato non mi pare che il messaggio sia un oggetto di tipo bytes, anche perchè ti darebbe errore quando utilizzi il metodo encode() che gli oggetti bytes non hanno.
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8149
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: [Python3] encoding/decoding di caratteri

Messaggioda rai » lunedì 20 marzo 2017, 23:28

Sì `message' è sicuramente str (essendo somma di stringhe matchate con re).
Ma quando la prende sendmail dovrebbe essere diventata bytes dato che la passo come `message.encode() '
O almeno, salvo errori
Codice: Seleziona tutto
>>> type(stringa)
<class 'str'>
>>> type(stringa.encode())
<class 'bytes'>
rai
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1871
Iscrizione: maggio 2008
Località: Palermo
Distribuzione: 12.04 | 16.04

Re: [Python3] encoding/decoding di caratteri

Messaggioda crap0101 » martedì 21 marzo 2017, 1:35

sì giusto, quindi dev'essere proprio come dice la doc e - che sia stringa o che siano bytes - la codifica dev'essere ascii.
Credo quindi non ci sia molto da fare mandano la mail in quella modalità senza usare i mime con cui si può specificare la codifica che verrà poi letta dal prog destinatario.
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Avatar utente
crap0101
Rampante Reduce
Rampante Reduce
 
Messaggi: 8149
Iscrizione: ottobre 2007
Località: TO
Desktop: Lubuntu
Distribuzione: Ubuntu 14.04.3 LTS
Sesso: Maschile

Re: [Python3] encoding/decoding di caratteri

Messaggioda rai » martedì 21 marzo 2017, 17:55

Sì quindi faccio una cosa del genere:
Codice: Seleziona tutto
import smtplib
from email.mime.nonmultipart import MIMENonMultipart

SUBJECT = "prova"
FROM = user
PASSWORD = password
TO = ['destinatario1@mail.com', 'destinatario2@mail.it']
TEXT = " à € ì ò ù "
msg = MIMENonMultipart('text', 'plain', charset='utf-8')
msg['Subject'] = SUBJECT
msg['From'] = FROM
msg['To'] = ", ".join(TO)
msg.set_payload(TEXT + ' Creata col modulo email.mime.')

SERVER = "il.server.smtps"
smtp = smtplib.SMTP_SSL(SERVER)
smtp.login(FROM, PASSWORD)
smtp.sendmail(FROM, TO, msg.as_string().encode('utf-8'))
smtp.quit()
il che funziona comunque, anche se la mail è 100% ascii

Grazie, come sempre
rai
Entusiasta Emergente
Entusiasta Emergente
 
Messaggi: 1871
Iscrizione: maggio 2008
Località: Palermo
Distribuzione: 12.04 | 16.04


Torna a Programmazione

Chi c’è in linea

Visualizzano questa sezione: 0 utenti registrati e 1 ospite