【问题标题】:Emails sent from Python not showing attachments even though they are there从 Python 发送的电子邮件没有显示附件,即使它们在那里
【发布时间】:2021-09-11 15:28:56
【问题描述】:

我正在使用 python 来生成和发送电子邮件。我希望消息包含两者

  • 嵌入图片(this 帖子展示了如何)
  • 附件

目前,除了附件没有 100% 显示外,下面的代码可以完成所有这些工作。在 Outlook 中,无法查看它们。在 Gmail 中,当您在收件箱中看到邮件时,它似乎没有附件,但当您打开邮件时,底部有附件。

如何让附件始终显示?

以下是我当前的代码。 我还将在下面显示,我的 gmail 收件箱中的标头似乎来自与此一起发送的电子邮件,与一切都按预期工作的标头之间的比较。

import smtplib
from os import getcwd, path
from config import mailer_settings

from email.message import EmailMessage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from email.utils import formatdate
from mimetypes import guess_type


def send_mail(send_from, send_to, subject, message, message_html="", file_loc: str = None, locs=[], cids=[],
              use_tls=True):
    """Compose and send email with provided info and attachments.

    Args:
        send_from (str): from name
        send_to (list[str]): to name(s)
        subject (str): message title
        message (str): message body
        message_html: message body with html
        file_loc (list[str]): path of file to be attached to email
        locs: list[str]: list of file locations for embedded images
        cids: list: list of generated (email.utils.make_msgid) cids for embedded images
        use_tls (bool): use TLS mode
    """

    # --- Method 1: can't get embedded pictures to work ---
    # msg = MIMEMultipart('alternative')
    # part1 = MIMEText(message, 'plain')
    # part2 = MIMEText(message_html, 'html')
    # msg.attach(part1)
    # msg.attach(part2)

    # --- Method 2 currently best ---
    msg = EmailMessage()
    msg.set_content(message)
    msg.add_alternative(message_html, subtype='html')

    # --- Method 3:
    # from (https://stackoverflow.com/questions/35925969/python-sent-mime-email-attachments-not-showing-up-in-mail-live)
    # not sure how to get it to work with embedded pictures, since MIMEImage is now deprecated ---
    # Create the root message and fill in the from, to, and subject headers
    b = False
    if b:
        msg = MIMEMultipart('related')
        msg.preamble = 'This is a multi-part message in MIME format.'

        # Encapsulate the plain and HTML versions of the message body in an
        # 'alternative' part, so message agents can decide which they want to display.
        msgAlternative = MIMEMultipart('alternative')
        msg.attach(msgAlternative)

        msgText = MIMEText('This is the alternative plain text message.')
        msgAlternative.attach(msgText)

        # We reference the image in the IMG SRC attribute by the ID we give it below
        msgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image1"><br>Nifty!', 'html')
        msgAlternative.attach(msgText)

        # This example assumes the image is in the current directory
        fp = open(getcwd() + '\\mail\\example_pdf.ong', 'rb')
        # :( MIMEImage is deprecated
        # msgImage = MIMEImage(fp.read())
        fp.close() 

        # Define the image's ID as referenced above
        # msgImage.add_header('Content-ID', '<image1>')
        # msg.attach(msgImage)

        # --- end Method 3 ---

    msg['From'] = send_from
    msg['To'] = send_to
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    # now open the image and attach it to the email
    for loc, cid in zip(locs, cids):
        with open(loc, 'rb') as img:

            # know the Content-Type of the image
            maintype, subtype = guess_type(img.name)[0].split('/')

            # attach it
            msg.get_payload()[1].add_related(img.read(), maintype=maintype, subtype=subtype, cid=cid)

    if file_loc:
        mimetype, encoding = guess_type(file_loc)
        mimetype = mimetype.split('/', 1)
        fp = open(file_loc, 'rb')
        attachment = MIMEBase(mimetype[0], mimetype[1])
        attachment.set_payload(fp.read())
        fp.close()
        encoders.encode_base64(attachment)
        attachment.add_header('Content-Disposition', 'attachment',
                              filename=path.basename(file_loc))
        msg.attach(attachment)

    server = mailer_settings["server"]
    port = mailer_settings["port"]
    username = mailer_settings["username"]
    password = mailer_settings["password"]

    smtp = smtplib.SMTP(server, port)
    if use_tls:
        smtp.starttls()
    smtp.login(username, password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    print("message sent!")
    smtp.quit()

我电子邮件中的标题:

--===============0780945104962264622==
Content-Type: application/pdf
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="Ecoemballage - test_product_01a.pdf"


--===============0780945104962264622==--

来自 Microsoft 电子邮件的标题,其中显示了它应有的附件:

--=-FabH5jV6gYAblpCdlHoDfQ==
Content-Type: application/octet-stream; name=221885190882013.pdf
Content-Disposition: attachment; filename=221885190882013.pdf
Content-Transfer-Encoding: base64


--=-FabH5jV6gYAblpCdlHoDfQ==--

【问题讨论】:

    标签: python image email email-attachments


    【解决方案1】:

    我找到了答案here

    这里的问题是你直接附加了一个预先构建的 MIME 部分到多部分/替代消息。它以不正确的结尾 邮件阅读器可能处理不当的邮件。

    在 email.message 界面中,你应该使用 add_attachement 方法。它将处理 base64 编码并更改消息 成一个多部分/混合的:

    为了解决这个问题,我将代码更改如下:

    if file_loc:
        fp = open(file_loc, 'rb')
        filename = path.basename(file_loc)
        # mimetype, encoding = guess_type(file_loc)
        # mimetype = mimetype.split('/', 1)
        # attachment = MIMEBase(mimetype[0], mimetype[1])
        # attachment.set_payload(fp.read())
        # fp.close()
        # encoders.encode_base64(attachment)
        # attachment.add_header('Content-Disposition', 'attachment',
        #                       filename=path.basename(file_loc))
        # msg.attach(attachment)
        msg.add_attachment(fp.read(), maintype='application',
                           subtype='octet-stream', filename=filename)
    

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2016-06-25
      • 2014-11-09
      • 2017-02-04
      • 2020-09-16
      • 2013-04-16
      • 2015-06-19
      • 1970-01-01
      相关资源
      最近更新 更多