MIMEImage无法在电子邮件正文中显示 / 尝试在电子邮件中嵌入图像

5
我正在尝试在电子邮件中嵌入一张图片。我已经按照这里这里这里等示例进行操作,但是我无法让图片显示出来。
    import smtplib
    import os

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage

    logo = 'mylogo.png'
    msg = MIMEMultipart('alternative')
    msg['Subject'] = "Link"
    msg['From'] = 'sender@email.com'
    msg['To'] = 'recipient@email.com'

    html = """\
    <html>
      <head></head>
    <body>
      <p>GREETING<br><br>
       SOME TEXT<br>
       MORE TEXT<br><br>
       FAREWELL <br><br>
       DISCLAIMER
    </p>
    <img src="cid:image1" alt="Logo" \>
    </body>
    </html> """

    part1 = MIMEText(text, 'plain')
    part2 = MIMEText(html, 'html', 'utf-8')

    msg.attach(part1)
    msg.attach(part2)

    fp = open(logo, 'rb')
    msgImage = MIMEImage(fp.read())
    fp.close()

    msgImage.add_header('Content-ID', '<image1>')
    msgImage.add_header('Content-Disposition', 'inline', filename=os.path.basename(logo))
    msgImage.add_header("Content-Transfer-Encoding", "base64")
    msg.attach(msgImage)

    s = smtplib.SMTP(smtp_server,25)
    s.sendmail(sender, recipient, msg.as_string())
    s.quit()

当我执行此操作时,我得到一个空白的主体,里面有一个红色的十字,没有图像。如何使图像与电子邮件正文一起显示?
我正在使用Outlook 2016。我知道在使用Outlook本身时可以插入图片,并且我已经收到其他人在文本中插入图像的“普通”电子邮件,因此这意味着我必须能够查看从Python脚本生成的图像吗?
编辑:我已经查看了给出的解决方案here,被建议作为可能的重复项,但这也没有解决我的问题。
我还尝试将相同的电子邮件发送到Gmail和hotmail帐户,但仍然出现相同的问题,因此问题显然与代码有关。

可能是在电子邮件中嵌入图片的重复问题。 - Syfer
2个回答

3
我在Outlook 2013中找到了解决方案:
Outlook似乎会查找span标签以及一些图像信息,比如高度和宽度(目前为硬编码),ID等(见下文)。我用这段HTML文本包裹我的图片,然后使用与我用于cid和id相同的编号添加图像作为附件。然后,图像将显示为在Outlook中嵌入的文件。
    # loop through all uploaded files and add as attachments
    for index, file in enumerate(attachment):
       with open(file, "rb") as fp:
          data = fp.read()
          fileType = os.path.splitext(file)[-1].strip(".")

          ctype, _ = mimetypes.guess_type(file)

          if embedImages and "image/" in ctype:
             image = Image.open(data)
             # Build out the html for the email
             message += '<span style = "mso-no-proof:yes"><img width = 1280 height = 1920 id = "%s" src = "cid:%s"></span>' % (index, index)
             # Define the image's ID
             msgImage = MIMEImage(data, _subtype=fileType)
             msgImage.add_header('Content-ID', '<%s>' % index)
             msg.attach(msgImage)
             att = MIMEApplication(data, _subtype=fileType)
             att.add_header("Content-Disposition", "attachment", filename="%s" % index)
             msg.attach(att)
        else:
             att = MIMEApplication(data, _subtype=fileType)
             att.add_header("Content-Disposition", "attachment", filename=fileName)
             msg.attach(att)
        fp.close()

        # Attach html text
        if message:
            if embedImages or "mimeType" in kwargs:
                msg.attach(MIMEText(message, kwargs["mimeType"], 'utf-8'))
            else:
                msg.attach(MIMEText(message, "plain", 'utf-8'))

3

以下是另一种解决方案,使用MIMEMultipart('related')组件,因此您无需处理Outlook中的跨度。 适用于任何类型的多个附件。(图像将被嵌入,除非另有规定)

    # Determine attach type - defaults to attached only
    embedImages = kwargs["embedImages"] if "embedImages" in kwargs else False

    # Create the root message and fill in the from, and subject headers
    msgRoot = MIMEMultipart('related')
    msgRoot["Subject"] = subject
    msgRoot["From"] = kwargs["fromAddr"] if "fromAddr" in kwargs else noreply

    # 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')
    msgRoot.attach(msgAlternative)

    # Get Recipient Type
    recipientType = kwargs.get("recipientType")

    # Chunk Process Recipients
    batchSize = 100
    for i in range(0, len(recipientList), batchSize):
        # Handle 100 recipients at a time
        recipients = recipientList[i:i + batchSize]
        # Set the to, bcc or cc in root message
        if recipientType == "bcc":
            msgRoot["Bcc"] = ", ".join(recipients)
        elif recipientType == "cc":
            msgRoot["Cc"] = ", ".join(recipients)
        else:
            msgRoot["To"] = ", ".join(recipients)

        # Add Attachments
        if attachment and isinstance(attachment, str):
            # For backwards compatibility turn single attachment into a list
            attachment = [attachment]

        # loop through all uploaded files and add as attachments
        for index, file in enumerate(attachment):
            with open(file, "rb") as fp:
                # guess the file type from mimetypes
                ctype, _ = mimetypes.guess_type(file)
                if embedImages and "image/" in ctype:
                    # Build out the html for the email
                    message += '<p><img src="cid:%s"></p>' % index
                    msgImage = MIMEImage(fp.read())
                    # Define the image's ID in header
                    msgImage.add_header('Content-ID', '<%s>' % index)
                    # attach it to root
                    msgRoot.attach(msgImage)
                else:
                    fileName = alias if alias and len(attachment) == 1 else os.path.basename(file)
                    msgApp = MIMEApplication(fp.read())
                    # define header as attachment
                    msgApp.add_header("Content-Disposition", "attachment", filename=fileName)
                    # attach it to root
                    msgRoot.attach(msgApp)
                # close the file handle
                fp.close()

        # Attach html text
        if message:
            if embedImages or "mimeType" in kwargs:
                msgAlternative.attach(MIMEText(message, kwargs["mimeType"], 'utf-8'))
            else:
                msgAlternative.attach(MIMEText(message, "plain", 'utf-8'))

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