Python无法通过电子邮件发送附件文件

9

我有以下代码,它可以正常工作,但是它没有发送附件文件。

import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.MIMEBase import MIMEBase
from email import Encoders

msg=MIMEMultipart()

def mymail(address,body,format,mylist=None):

    msg['To']=address
    msg['From']='ggous1@gmail.com'
    if format=='txt':
        text_msg=MIMEText(body,'plain')
    elif format=='html':
        text_msg=MIMEText(body,'html')
    msg.attach(text_msg)
    if mylist is not None:
        mylist=[]
        fn=[]
        for f in range(len(mylist)):
            direct=os.getcwd()
            os.chdir(direct)
            part=MIMEBase('application','octet-stream')
            part.set_payload(open(mylist[f],'rb').read())
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(mylist[f])) 
            fn.append(part)
            msg.attach(fn)

    srv=smtplib.SMTP('smtp.gmail.com')
    srv.set_debuglevel(1)
    srv.ehlo()
    srv.starttls()
    srv.ehlo()
    srv.login('username','pass')
    srv.sendmail(msg['From'],msg['To'],msg.as_string())
    srv.quit()

if __name__=="__main__":
    address=raw_input('Enter an address to send email in the form "name@host.com" ')
    body=raw_input('Enter the contents of the email')
    format=raw_input('The format is txt or html?')
    question=raw_input('Do you have any files to attach?Yes or No?')
    mylist=[]
    if question=='Yes' or question=='yes':
        fn=raw_input('Enter filename')
        mylist.append(fn)

    mymail(address,body,format,mylist)

我使用MIMEBase有没有问题,还是我的代码出现了错误?
更新------------------------
 if mylist is not None:
        mylist=[]
        fn=[]
        for f in range(len(mylist)):
            direct=os.getcwd()
            os.chdir(direct)
            fn[f]=open(mylist[f],'r')             
            part=msg.attach(MIMEApplication(fn[f]))
            mylist.append(part)

此外,你可以(应该)只需检查 'if mylist:' 而不是显式比较。**'if mylist:'** 如果它是 'None' 或空列表、字典、字符串等,则返回 False。同时考虑使用 **"if question.lower() == 'yes':"**。 - MrWonderful
1个回答

23

我建议使用MIMEApplication代替附件。你也不需要手动进行所有负载编码,因为这已经自动完成了。以下示例对我有效:

from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.utils import formataddr
from email.utils import make_msgid
from email.utils import formatdate

email = MIMEMultipart()
email['From'] = formataddr(('Jane Doe', 'jane@example.com'))
email['Subject'] = u'Test email'
email['Message-Id'] = make_msgid()
email['Date'] = formatdate(localtime=True)
email.attach(MIMEText(u'This is your email contents.'))
email.attach(MIMEApplication('your binary data'))
print email.as_string()
请注意,我还要注意设置正确的日期和消息ID标头。
将其应用于您的代码(进行一些小的清理),我得到以下工作代码:
import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.mime.text import MIMEText
from email.utils import make_msgid
from email.utils import formatdate


def make_mail(address,body,format,mylist=[]):
    msg = MIMEMultipart()
    msg['To'] = address
    msg['From'] = 'ggous1@gmail.com'
    msg['Message-Id'] = make_msgid()
    msg['Date'] = formatdate(localtime=True)
    msg.attach(MIMEText(body, 'plain' if format == 'txt' else 'html'))
    for filename in mylist:
        part = MIMEApplication(open(filename).read())
        part.add_header('Content-Disposition',
                'attachment; filename="%s"' % os.path.basename(filename))
        msg.attach(part)
    return msg    

def send_mail(msg):
    srv = smtplib.SMTP('smtp.gmail.com')
    srv.set_debuglevel(1)
    srv.ehlo()
    srv.starttls()
    srv.ehlo()
    srv.login('username','pass')
    srv.sendmail(msg['From'], msg['To'], msg.as_string())
    srv.quit()

if __name__=="__main__":
    address=raw_input('Enter an address to send email in the form "name@host.com" ')
    body=raw_input('Enter the contents of the email')
    format=raw_input('The format is txt or html?')
    question=raw_input('Do you have any files to attach?Yes or No?')
    mylist=[]
    if question=='Yes' or question=='yes':
        fn=raw_input('Enter filename')
        mylist.append(fn)

    msg = make_mail(address,body,format,mylist)
    send_mail(msg)

你好,我按照你说的做了,但还是一样。我已经更新了。谢谢! - George
我已经添加了一个经过清理的版本,这个版本对我来说是可行的。 - Wichert Akkerman
好的,我现在正在做这个,但结果还是一样!"mylist=[]",然后是 "for filename in mylist: part=......" 我想把 "mylist=None" 作为函数的参数。我该怎么处理? - George
你根本不需要“mylist=[]”。只需删除那一行即可。 - Wichert Akkerman
不错 :-) 我花了一个小时尝试使用MIMEBase,但是没有成功...然后我看到了这个。非常好用。 - Julien Spronck
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接