2010-05-09 9 views
6

Utilisation de Python 3.1.2 Un problème est survenu lors de l'envoi de fichiers joints binaires (jpeg, pdf, etc.) - Les pièces jointes MIMEText fonctionnent correctement. Le code en question est la suivante ...Problème de pièce jointe d'un fichier e-mail binaire

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()) 

Cependant, dans la façon calling-pile (voir retraçage ci-dessous), il semble que msg.as_string() a reçu une pièce jointe qui crée une charge utile de Type "octets" au lieu de chaîne.

Quelqu'un at-il une idée de ce qui pourrait causer le problème? Toute aide serait appréciée.

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 titre d'une solution de contournement (bien, une solution de contournement possible, Je n'ai vraiment aucune idée si cela va aider), vous pourriez essayer d'utiliser 'MIMEApplication' au lieu de' MIMEBase' –

+0

Salut David merci pour la réponse. J'ai essayé MIMEApplication, mais en vain (ie msg.get_payload() retourne toujours des octets au lieu de la chaîne). Je pense que c'est quelque chose à voir avec l'encodage qui ne convertit pas correctement le fichier binaire en une chaîne, mais je peux me tromper. Je suis également préoccupé par le fait que j'ai essayé de nombreux exemples similaires de divers sites Web - ils échouent tous pour moi, mais doivent avoir travaillé pour l'auteur. Cordialement –

Répondre

3

Ok - après beaucoup de frustration et de web recherche, j'ai trouvé que le problème est un bug connu qui s'applique à 3.x Python, encoders.py, fonction encode_base64, qui devrait se lire comme suit ...

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' 

Le bug a été soulevé comme question # 4768, et a été escaladé à l'état critique sur 2010-05-10. Espérons que cela sera corrigé dans la prochaine version (3.1.3?)

Cordialement, solution Alan

+0

Y at-il une solution de contournement que je peux utiliser? –

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

Cela semble prometteur - je vais essayer - merci. –

+0

ajouter "à partir d'e-mail importer des encodeurs" – mastier

2

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, merci pour cette solution. Je vais le stocker au cas où ma solution actuelle tomberait dans une future version de Python. –