2010-05-09 14 views
6

Uso di Python 3.1.2 Ho problemi nell'invio di file di allegati binari (jpeg, pdf, ecc.) - Gli allegati MIMEText funzionano correttamente. Il codice in questione è il seguente ...Problema di allegato alla posta elettronica file binario

for file in self.attachments: 
    part = MIMEBase('application', "octet-stream") 
    part.set_payload(open(file,"rb").read()) 
    encoders.encode_base64(part) 
    part.add_header('Content-Disposition', 'attachment; filename="%s"' % file) 
    msg.attach(part) # msg is an instance of MIMEMultipart() 

server = smtplib.SMTP(host, port) 
server.login(username, password) 
server.sendmail(from_addr, all_recipients, msg.as_string()) 

Tuttavia, fino in fondo nella chiamata-stack (vedi traceback sotto), sembra che msg.as_string() ha ricevuto un allegato che crea un carico utile di tipo "byte" anziché stringa.

Qualcuno ha idea di cosa potrebbe causare il problema? Qualsiasi aiuto sarebbe apprezzato.

Alan


builtins.TypeError: string payload expected: <class 'bytes'> 
File "c:\Dev\CommonPY\Scripts\email_send.py", line 147, in send 
    server.sendmail(self.from_addr, all_recipients, msg.as_string()) 
File "c:\Program Files\Python31\Lib\email\message.py", line 136, in as_string 
    g.flatten(self, unixfrom=unixfrom) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 76, in flatten 
    self._write(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 101, in _write 
    self._dispatch(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 127, in _dispatch 
    meth(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 181, in _handle_multipart 
    g.flatten(part, unixfrom=False) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 76, in flatten 
    self._write(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 101, in _write 
    self._dispatch(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 127, in _dispatch 
    meth(msg) 
File "c:\Program Files\Python31\Lib\email\generator.py", line 155, in _handle_text 
    raise TypeError('string payload expected: %s' % type(payload)) 
+0

A titolo di una soluzione alternativa (o meglio, una soluzione possibile, In realtà non ho idea se sarà d'aiuto), potresti provare a usare 'MIMEApplication' invece di' MIMEBase' –

+0

Ciao David grazie per la risposta. Ho provato l'applicazione MIMEA, ma senza alcun risultato (cioè msg.get_payload() restituisce ancora byte invece di stringa). Sospetto che abbia a che fare con la codifica non convertendo correttamente il file binario in una stringa, ma potrei sbagliarmi. Sono anche preoccupato per il fatto che ho provato molti esempi simili da vari siti Web - falliscono tutti per me, ma devono aver funzionato per l'autore. Saluti –

risposta

3

Ok - dopo molta frustrazione e web-ricerca, ho scoperto che il problema è un bug noto che si applica a Python 3.x, encoders.py, la funzione encode_base64, che va letto come segue ...

def encode_base64(msg): 
    """Encode the message's payload in Base64. 

    Also, add an appropriate Content-Transfer-Encoding header. 
    """ 
    orig = msg.get_payload() 
    encdata = _bencode(orig) 

    # new line inserted to ensure all bytes characters are converted to ASCII 
    encdata = str(encdata, "ASCII") 

    msg.set_payload(encdata) 
    msg['Content-Transfer-Encoding'] = 'base64' 

Il bug è stato cresciuto come numero # 4768, ed è stata aumentata a stato critico su 2010-05-10. Speriamo che sarà fissato nella prossima versione (3.1.3?)

saluti, Alan

+0

C'è una soluzione che posso usare? –

3
for file in self.attachments: 
    fp = open(file,"rb")  
    part = MIMEApplication(fp.read())  
    fp.close()  
    encoders.encode_base64(part) 

    # the miracle 
    part.set_payload(part.get_payload().decode('ASCII')) 

    part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)  
    msg.attach(part) 
+0

Sembra promettente - ci proverò - grazie. –

+0

aggiungi "da encoder di importazione e-mail" – mastier

2

soluzione da this SO answer

from base64 import encodebytes 
for file in self.attachments: 
    fp = open(file, 'rb') 
    part = MIMEBase('application', "octet-stream") 
    part.set_payload(encodebytes(fp.read()).decode()) 
    fp.close() 
    part.add_header('Content-Transfer-Encoding', 'base64') 
    part.add_header('Content-Disposition', 'attachment; filename="%s"' % file) 
    msg.attach(part) # msg is an instance of MIMEMultipart() 

server = smtplib.SMTP(host, port) 
server.login(username, password) 
server.sendmail(from_addr, all_recipients, msg.as_string()) 
+0

@bstpierre, grazie per questa soluzione. Lo memorizzerò nel caso in cui la mia attuale soluzione cada in una versione futura di Python. –

Problemi correlati