Gmail Python multiple attachments

2019-02-07 13:25发布

I am trying to create a little script that will email multiple attachments using gmail. The code below sends the email but not the attachments. The intended use is to cron a couple db queries and email the results. There will always be 2 files and the file names will be different each day as the date for the report is in the file name. Otherwise I would have just used:

part.add_header('Content-Disposition', 
    'attachment; filename="absolute Path for the file/s"')

Any help greatly appreciated.

import os
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEBase import MIMEBase
from email import Encoders


#Set up crap for the attachments
files = "/tmp/test/dbfiles"
filenames = [os.path.join(files, f) for f in os.listdir(files)]
#print filenames


#Set up users for email
gmail_user = "joe@email.com"
gmail_pwd = "somepasswd"
recipients = ['recipient1','recipient2']

#Create Module
def mail(to, subject, text, attach):
   msg = MIMEMultipart()
   msg['From'] = gmail_user
   msg['To'] = ", ".join(recipients)
   msg['Subject'] = subject

   msg.attach(MIMEText(text))

   mailServer = smtplib.SMTP("smtp.gmail.com", 587)
   mailServer.ehlo()
   mailServer.starttls()
   mailServer.ehlo()
   mailServer.login(gmail_user, gmail_pwd)
   mailServer.sendmail(gmail_user, to, msg.as_string())
   # Should be mailServer.quit(), but that crashes...
   mailServer.close()

#get all the attachments
   for file in filenames:
      part = MIMEBase('application', 'octet-stream')
      part.set_payload(open(file, 'rb').read())
      Encoders.encode_base64(part)
      part.add_header('Content-Disposition', 'attachment; filename="%s"'
                   % os.path.basename(file))
      msg.attach(part)
#send it
mail(recipients,
   "Todays report",
   "Test email",
   filenames)

2条回答
叛逆
2楼-- · 2019-02-07 14:01

Should have waited another hour before posting. Made 2 changes:

1.) moved the attachment loop up

2.) swapped out part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))

for part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)

Works like a champ. Gmail with multiple recipients and multiple attachments.

import os 
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEBase import MIMEBase
from email import Encoders


#Set up crap for the attachments
files = "/tmp/test/dbfiles"
filenames = [os.path.join(files, f) for f in os.listdir(files)]
#print filenames


#Set up users for email
gmail_user = "joe@email.com"
gmail_pwd = "somepasswd"
recipients = ['recipient1','recipient2']

#Create Module
def mail(to, subject, text, attach):
   msg = MIMEMultipart()
   msg['From'] = gmail_user
   msg['To'] = ", ".join(recipients)
   msg['Subject'] = subject

   msg.attach(MIMEText(text))

   #get all the attachments
   for file in filenames:
      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)

   mailServer = smtplib.SMTP("smtp.gmail.com", 587)
   mailServer.ehlo()
   mailServer.starttls()
   mailServer.ehlo()
   mailServer.login(gmail_user, gmail_pwd)
   mailServer.sendmail(gmail_user, to, msg.as_string())
   # Should be mailServer.quit(), but that crashes...
   mailServer.close()

#send it
mail(recipients,
   "Todays report",
   "Test email",
   filenames)
查看更多
▲ chillily
3楼-- · 2019-02-07 14:17

Thanks @marc! I can't comment on your answer, so here are few fixes (misnamed variables) and small improvements:

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

def mail(to, subject, text, attach):
    # allow either one recipient as string, or multiple as list
    if not isinstance(to,list):
        to = [to]
    # allow either one attachment as string, or multiple as list
    if not isinstance(attach,list):
        attach = [attach]

    gmail_user='username@gmail.com'
    gmail_pwd = "password"
    msg = MIMEMultipart()
    msg['From'] = gmail_user
    msg['To'] = ", ".join(to)
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    #get all the attachments
    for file in attach:
        print file
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(open(file, 'rb').read())
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
        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_user, to, msg.as_string())
    # Should be mailServer.quit(), but that crashes...
    mailServer.close()

if __name__ == '__main__':
    mail(['recipient1', 'recipient2'], 'subject', 'body text',
         ['attachment1', 'attachment2'])
查看更多
登录 后发表回答