【问题标题】:Sending email with Python and Gmail SMTP server doesn't work with attachment使用 Python 和 Gmail SMTP 服务器发送电子邮件不适用于附件
【发布时间】:2015-10-24 15:14:45
【问题描述】:

我正在尝试发送带有 PDF 附件的电子邮件。我已经定义了下一个函数:

def mail(to, subject, text, attach):
    gmail_user = "email@gmail.com"
    gmail_name = "name <email@gmail.com>"
    gmail_pwd = "password"

    msg = MIMEMultipart()

    msg['From'] = gmail_name
    msg['To'] = to
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    part = MIMEBase('application', 'octet-stream')
    part.set_payload(open(attach, 'rb').read())
    Encoders.encode_base64(part)
    part.add_header('Content-Disposition',
           'attachment; filename="%s"' % os.path.basename(attach))
    msg.attach(part)

    mailServer = smtplib.SMTP("smtp.gmail.com", 587)

    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmail_user, gmail_pwd)
    mailServer.sendmail(gmail_name, to, msg.as_string())
    mailServer.close()

问题是控制台显示如下错误

smtplib.SMTPServerDisconnected: Server not connected

但是,如果我只是将“msg.as_string”替换为“Whatever string”,它就可以正常工作。所以我认为当我尝试附加 PDF 文件时会发生此问题。

你能帮帮我吗?

谢谢

【问题讨论】:

    标签: python email smtp gmail


    【解决方案1】:

    您还可以使用专门用于编写 HTML 电子邮件、内联显示图片和轻松附加文件的包!

    我指的包是yagmail,我是开发者/维护者。

    import yagmail
    yag = yagmail.SMTP(gmail_name, gmail_pwd)
    yag.send('xyz@gmail.com', 'Sample subject', contents = attach)
    

    仅此而已(3 行对 69 行)!!

    使用pip install yagmail 获取您的副本。

    Contents 可以是一个列表,您还可以在其中添加文本,但由于您没有文本,您只能将 attach 文件名作为内容,不是吗? 它读取文件,神奇地确定编码,并附加它:)

    【讨论】:

    • 漂亮!无忧无虑。
    • 非常感谢!为什么这个图书馆不出名? :)
    • @MarjanModerc 我想我应该解雇市场部 ;)
    • 哇,这太棒了!我只知道要走很长的路——接受的答案所暗示的方式。您的库/模块很棒,可以节省大量时间。
    【解决方案2】:

    试试这个-

    import smtplib
    import mimetypes
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEBase import MIMEBase
    from email.MIMEText import MIMEText
    from email.Utils import COMMASPACE, formatdate
    from email import Encoders
    
    
    filePath = "fileName.pdf"
    
    From = 'abc@gmail.com'
    To = 'xyz@gmail.com'
    
    msg = MIMEMultipart()
    msg['From'] = From
    msg['To'] = To
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = 'Sample subject'
    
    msg.attach(MIMEText('Sample message'))
    
    try:
        smtp = smtplib.SMTP('smtp.gmail.com:587')
        smtp.starttls()
        smtp.login('abc@gmail.com', '123456')
    except:
        i = 1
    else:
        i = 0
    
    if i == 0:
        ctype, encoding = mimetypes.guess_type(filePath)
        if ctype is None or encoding is not None:
            # No guess could be made, or the file is encoded (compressed), so
            # use a generic bag-of-bits type.
            ctype = 'application/octet-stream'
        maintype, subtype = ctype.split('/', 1)
        if maintype == 'text':
            fp = open(filePath)
            # Note: we should handle calculating the charset
            part = MIMEText(fp.read(), _subtype=subtype)
            fp.close()
        elif maintype == 'image':
            fp = open(filePath, 'rb')
            part = MIMEImage(fp.read(), _subtype=subtype)
            fp.close()
        elif maintype == 'audio':
            fp = open(filePath, 'rb')
            part = MIMEAudio(fp.read(), _subtype=subtype)
            fp.close()
        else:
            fp = open(filePath, 'rb')
            part = MIMEBase(maintype, subtype)
            part.set_payload(fp.read())
            fp.close()
            # Encode the payload using Base64
            Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % filePath)
        msg.attach(part)
        try:
            smtp.sendmail(From, To, msg.as_string())
        except:
            print "Mail not sent"
        else:
            print "Mail sent"
        smtp.close()
    else:
        print "Connection failed"
    

    改编自: https://docs.python.org/2/library/email-examples.html

    【讨论】:

    • 它显示“邮件未发送”,我已使用您的代码发送了一个 txt 文件并且工作正常,但我仍然遇到同样的问题
    • @luigonsec 我已经更新了我的答案。这个应该能够处理所有类型的文件作为附件。
    • @CrakC 看看我的回答,我想你可能会喜欢它:)
    【解决方案3】:

    我相信你应该改变这个:part = MIMEBase('application', 'pdf')
    查看How do I send an email with a .csv attachment using Python 了解如何尝试猜测文件类型。
    其他可能的问题:

    • 尝试像这样添加标题: attachment.add_header("Content-Disposition", "attachment", filename=fileToSend)
    • 您在这条线上使用什么编码器? Encoders.encode_base64(part)。我认为你应该使用from email import encoders 然后encoders.encode_base64(part)

    【讨论】:

    • 谢谢,我觉得你说的是真的,但是改了之后还是不行。
    猜你喜欢
    • 2016-09-07
    • 2014-10-27
    • 2022-01-09
    • 2014-10-15
    • 1970-01-01
    • 2012-10-20
    • 2010-10-17
    相关资源
    最近更新 更多