2010-05-09 79 views
6

使用Python 3.1.2我有一個問題發送二進制附件文件(JPEG,PDF等) - MIMEText附件工作正常。有問題的代碼如下...二進制文件電子郵件附件問題

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

然而,在調用堆棧一路下滑(見下文回溯),它看起來好像msg.as_string()已收到其產生的有效載荷附件'字節'類型而不是字符串。

有沒有人有任何想法可能會導致這個問題?任何幫助,將不勝感激。

艾倫


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

通過一個解決辦法的方式解決(當然,可能的解決方法,我實際上不知道它是否會有幫助),你可以嘗試使用'MIMEApplication'而不是'MIMEBase' – 2010-05-09 18:00:22

+0

大衛感謝您的回覆。我嘗試了MIMEApplication,但無濟於事(即.msg.get_payload()仍然返回字節而不是字符串)。我懷疑這是編碼不正確地將二進制文件轉換爲字符串,但我可能是錯的。我也擔心我已經嘗試了很多來自不同網站的類似例子 - 它們都失敗了,但是一定爲作者工作過。 Regards – 2010-05-09 21:38:31

回答

3

好了 - 太多的無奈和網絡搜索之後,我發現這個問題是一個已知的bug適用於Python的3.x中,encoders.py,功能encode_base64,這應改爲...

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' 

的錯誤已被提出的問題#4768,並升級到臨界狀態 上2010-05-10。希望這將是固定在下一版本(3.1.3?)

問候,艾倫

+0

有沒有可以使用的解決方法? – 2011-01-31 14:04:11

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

看起來很有希望 - 我會試一試 - 謝謝。 – 2010-06-11 02:37:41

+0

添加「從電子郵件進口編碼器」 – mastier 2016-10-20 14:56:40

2

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,感謝您的解決方案。我將把它存儲起來,以防我目前的解決方案在未來的Python版本中出現。 – 2011-03-16 22:24:47