发送Python电子邮件时添加Excel文件附件

31

如何使用Python在发送电子邮件时添加文档附件? 我能够发送电子邮件 (请忽略:我正在每5秒循环发送电子邮件,仅用于测试目的,我想让它每30分钟发送一次,只需将5更改为1800)

这是我目前的代码。如何从我的电脑上附加一个文档?

#!/usr/bin/python

import time
import smtplib

while True:
    TO = 'xxxx@gmail.com'
    SUBJECT = 'Python Email'
    TEXT = 'Here is the message'

    gmail_sender = 'xxxx@gmail.com'
    gmail_passwd = 'xxxx'

    server = smtplib.SMTP('smtp.gmail.com',587)
    server.ehlo()
    server.starttls()
    server.ehlo()
    server.login(gmail_sender, gmail_passwd)
    BODY = '\n'.join([
        'To: %s' % TO,
        'From: %s' % gmail_sender,
        'Subject:%s' % SUBJECT,
        '',
        TEXT

        ])

    try:
        server.sendmail(gmail_sender,[TO], BODY)
        print 'email sent'
    except:
        print 'error sending mail'

    time.sleep(5)

server.quit()
6个回答

67

这是对我有效的代码示例- 用 Python 发送带附件的电子邮件

#!/usr/bin/python
import smtplib,ssl
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import formatdate
from email import encoders

def send_mail(send_from,send_to,subject,text,files,server,port,username='',password='',isTls=True):
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = send_to
    msg['Date'] = formatdate(localtime = True)
    msg['Subject'] = subject
    msg.attach(MIMEText(text))

    part = MIMEBase('application', "octet-stream")
    part.set_payload(open("WorkBook3.xlsx", "rb").read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename="WorkBook3.xlsx"')
    msg.attach(part)

    #context = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
    #SSL connection only working on Python 3+
    smtp = smtplib.SMTP(server, port)
    if isTls:
        smtp.starttls()
    smtp.login(username,password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()

它完美地工作了,但是在这一行中尝试通过变量发送文件名:part.add_header('Content-Disposition', 'attachment; filename="WorkBook3.xlsx"'),我想从参数列表中添加文件,然后添加文件名本身,例如:part.add_header('Content-Disposition', 'attachment; filename=files') - 10raw

15

我发现了一种简单的方式,使用Corey Shafer在这个视频中讲解的方法来用Python发送电子邮件。

import smtplib
from email.message import EmailMessage

SENDER_EMAIL = "sender_email@gmail.com"
APP_PASSWORD = "xxxxxxx"

def send_mail_with_excel(recipient_email, subject, content, excel_file):
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = SENDER_EMAIL
    msg['To'] = recipient_email
    msg.set_content(content)

    with open(excel_file, 'rb') as f:
        file_data = f.read()
    msg.add_attachment(file_data, maintype="application", subtype="xlsx", filename=excel_file)

    with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
        smtp.login(SENDER_EMAIL, APP_PASSWORD)
        smtp.send_message(msg)

3
关于 xlsx 文件,正确的子类型应该是 vnd.openxmlformats-officedocument.spreadsheetml.sheet证明链接 - vladkras

10
这只是对SoccerPlayer上面帖子的微小调整,让我完成了99%的工作。我在这里找到了一个片段,在这里,让我完成了剩下的工作。没有功劳归于我。只是为了帮助下一个人而发帖。
file = 'File.xlsx'
username=''
password=''
send_from = ''
send_to = 'recipient1 , recipient2'
Cc = 'recipient'
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = send_to
msg['Cc'] = Cc
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = ''
server = smtplib.SMTP('smtp.gmail.com')
port = '587'
fp = open(file, 'rb')
part = MIMEBase('application','vnd.ms-excel')
part.set_payload(fp.read())
fp.close()
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename='Name File Here')
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com')
smtp.ehlo()
smtp.starttls()
smtp.login(username,password)
smtp.sendmail(send_from, send_to.split(',') + msg['Cc'].split(','), msg.as_string())
smtp.quit()

这个更加直接易懂,对我很有帮助,谢谢。 - Plato77
3年后,这对我非常有用...谢谢。 - Padua

2

您可以使用Python 3 来使用 MIMEApplication 处理IT技术相关内容:

import os, smtplib, traceback
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

def sendMail(sender,
             subject,
             recipient,
             username,
             password,
             message=None,
             xlsx_files=None):

    msg = MIMEMultipart()
    msg["Subject"] = subject
    msg["From"] = sender
    if type(recipient) == list:
        msg["To"] = ", ".join(recipient)
    else:
        msg["To"] = recipient
    message_text = MIMEText(message, 'html')
    msg.attach(message_text)

    if xlsx_files:
        for f in xlsx_files:
            attachment = open(f, 'rb')
            file_name = os.path.basename(f)
            part = MIMEApplication(attachment.read(), _subtype='xlsx')
            part.add_header('Content-Disposition', 'attachment', filename=file_name)
            msg.attach(part)

    try:
        server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
        server.ehlo()
        server.login(username, password)
        server.sendmail(sender, recipient, msg.as_string())
        server.close()
    except Exception as e:
        error = traceback.format_exc()
        print(error)
        print(e)


注意* 在这个例子中,我只是使用了print(error)。通常情况下,我会将错误发送到logging.critical(error)

1
要发送附件,需要创建一个MIMEMultipart对象并将附件添加到其中。以下是来自Python 电子邮件示例的示例。
# Import smtplib for the actual sending function
import smtplib

# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

COMMASPACE = ', '

# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = COMMASPACE.join(family)
msg.preamble = 'Our family reunion'

# Assume we know that the image files are all in PNG format
for file in pngfiles:
    # Open the files in binary mode.  Let the MIMEImage class automatically
    # guess the specific image type.
    fp = open(file, 'rb')
    img = MIMEImage(fp.read())
    fp.close()
    msg.attach(img)

# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()

同时,我的文件是一个Excel文件。 - soccerplayer
这是另一个Stack Overflow答案,展示了如何将任何文件编码为mime附件。 - Andrew Johnson

0

你也可以很好地用红信完成这个:

from redmail import EmailSender

from pathlib import Path
import pandas as pd

gmail = EmailSender(
    host='smtp.gmail.com',
    port=465,
    user_name="you@gmail.com",
    password="<YOUR PASSWORD>"
)

gmail.send(
    subject="Python Email",
    receivers=["you@gmail.com"],
    text="Here is the message",
    attachments={
        # From path on disk
        "my_file.xlsx": Path("path/to/file.xlsx"),
        # Or from Pandas dataframe
        "my_frame.xlsx": pd.DataFrame({"a": [1,2,3]})
    }
)

如果您希望以此方式附加Excel文件,也可以传递字节。

安装Red Mail:

pip install redmail

Red Mail是一个功能丰富的开源电子邮件库。它经过了充分的测试和文档化。文档可以在这里找到:https://red-mail.readthedocs.io/en/latest/


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