Search code examples
pythonemailsmtpgmail

Sending email with Python and Gmail SMTP server doesn't work with attachment


I'm trying send email with a PDF attached. I have defined the next function:

def mail(to, subject, text, attach):
    gmail_user = "[email protected]"
    gmail_name = "name <[email protected]>"
    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()

The problem is that the console shows the following error

smtplib.SMTPServerDisconnected: Server not connected

However, if I simply replace 'msg.as_string' with "Whatever string" it works fine. So I think that this issue happens when I try attach a PDF file.

Could you help me please ?

Thanks


Solution

  • Try this-

    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 = '[email protected]'
    To = '[email protected]'
    
    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('[email protected]', '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"
    

    Adapted from: https://docs.python.org/2/library/email-examples.html