2010-05-09 29 views
6

Uso de Python 3.1.2 Tengo problemas para enviar archivos adjuntos binarios (jpeg, pdf, etc.) - Los archivos adjuntos MIMEText funcionan bien. El código en cuestión es la siguiente ...Problema de archivo adjunto de correo electrónico de archivo 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()) 

Sin embargo, hasta abajo en la pila de llamadas-(ver rastreo más adelante), parece que msg.as_string() ha recibido un archivo adjunto que crea una carga útil de 'bytes' tipo en lugar de cadena.

¿Alguien tiene alguna idea de lo que podría estar causando el problema? Cualquier ayuda sería apreciada.

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 modo de solución (así, una posible solución, De hecho, no tengo idea si esto ayudará), puede intentar usar 'MIMEApplication' en lugar de' MIMEBase' –

+0

Hola David, gracias por la respuesta. Probé la aplicación MIMEA, pero fue en vano (es decir, msg.get_payload() aún devuelve bytes en lugar de cadena). Sospecho que tiene algo que ver con la codificación que no convierte correctamente el archivo binario a una cadena, pero podría estar equivocado. También me preocupa que haya intentado muchos ejemplos similares de varios sitios web: todos fallan, pero deben haber funcionado para el autor. Saludos –

Respuesta

3

Ok - después de mucha frustración y sitios de búsqueda, he encontrado que el problema es un error conocido que se aplica a Python 3.x, encoders.py, encode_base64 función, la cual debe ser el siguiente ...

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' 

El error se ha planteado como la edición # 4768, y fue aumentado al estado crítico en 2010-05-10. Es de esperar que se fijará en la próxima versión (3.1.3?)

Saludos, Alan

+0

¿Existe alguna solución alternativa que pueda usar? –

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

Eso parece prometedor. Lo intentaré, gracias. –

+0

agrega "de codificadores de importación de correo electrónico" – mastier

2

solución de 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, gracias por esta solución. Lo almacenaré en caso de que mi solución actual caiga en una versión futura de Python. –

Cuestiones relacionadas