Gmail Python 多个附件

7

我正在尝试编写一个小脚本,可以使用Gmail发送多个附件。下面的代码可以发送电子邮件,但是无法发送附件。预期用途是计划一些数据库查询并通过电子邮件发送结果。每天都会有2个文件,文件名中包含报告的日期,因此文件名将不同。否则,我只需使用:

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

任何帮助都将不胜感激。
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)
3个回答

10

发布前应再等一个小时。做出了两个更改:

1.) 将附件循环移至顶部

2.) 将

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

替换为

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

非常有效。Gmail可以同时发送给多个收件人和多个附件。

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)

2

感谢 @marc!由于我无法评论您的回答,因此在此提供一些修复(变量名称错误)和小改进:

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'])

0

我有一个类似的问题。我能够发送多个附件,但在我的Mac邮件应用程序中,并非所有附件都出现,HTML也不出现(在Gmail网页上一切正常)。如果有人遇到同样的问题,下面的代码对我来说在python3.8中有效。现在所有附件和HTML都出现在邮件应用程序中。

https://docs.python.org/3/library/email.examples.html#email-examples

小更新:

import os, ssl, sys
import smtplib
# For guessing MIME type based on file name extension
import mimetypes
from email.message import EmailMessage
from email.policy import SMTP
from datetime import datetime
from uuid import uuid4

directory = '/path/to/files'
recipients = ['recipient@gmail.com']
sender = 'username@gmail.com'
password = 'password'
email_host, email_port = 'smtp.gmail.com', 465

msg = EmailMessage()
msg['Subject'] = f'This is a subject {datetime.utcnow()}'
msg['To'] = ', '.join(recipients)
msg['From'] = sender
msg.preamble = f'{str(uuid4())}\n'

msg.add_alternative('This is a PLAIN TEXT', subtype='plain')
msg.add_alternative('''\
    <html>
    <head></head>
    <body>
        <h4>Hello World! this is HTML </h4>
        <p style="margin: 0;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat.</p>
    </body>
    </html>''', subtype='html')

for filename in ['sample.pdf', 'sample2.pdf']:
    path = os.path.join(directory, filename)
    if not os.path.isfile(path):
        continue
    # Guess the content type based on the file's extension.  Encoding
    # will be ignored, although we should check for simple things like
    # gzip'd or compressed files.
    ctype, encoding = mimetypes.guess_type(path)
    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)
    with open(path, 'rb') as fp:
        msg.add_attachment(fp.read(),
                            maintype=maintype,
                            subtype=subtype,
                            filename=filename)

context = ssl.create_default_context()
with smtplib.SMTP_SSL(email_host, email_port, context=context) as server:
    server.login(sender, password)
    server.send_message(msg)





请熟悉一下本网站的运作方式。这不是一个讨论论坛,而是一个严格的问答网站。如果您有问题,请将其作为新问题提出(并参考相关问题),而不要像您目前所做的那样在相关问题的__答案__中发布它。答案应该只用于真正回答问题。 - Steffen Ullrich

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