Python - 将带有嵌入图像的邮件发送到 GMAIL

Python - send mail to GMAIL with embedded images

我有以下脚本可以成功发送附有图像的邮件到 hotmail。 问题是,如果我向 GMAIL 发送相同的邮件,图像会附在邮件中,而不是嵌入在 HTML 中。 为什么会这样?如何解决? 例如,HTML 中的图像按以下方式显示:

这是当前代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import base64
import email
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.header import Header
import codecs
from bs4 import BeautifulSoup
import mimetypes
import requests
import time

SMTP_SERVER = "xxx"
SMTP_PORT = 587
SMTP_USERNAME = "xxx"
SMTP_PASSWORD = "xxx"
SMTP_USE_TLS = False
FROM_EMAIL = "xxx@xxx.com"

lista_mails = ['my_mail@hotmail.com']
lista_apodos =['user']

subject='Test Mail'

def get_image(img_src):
    if img_src.startswith('http://') or img_src.startswith('https://'):
        try:
           resp = requests.get(img_src)
        except:
            print("Failed to retrieve {}".format(img_src))
            print(resp.text)
            return None

        return MIMEImage(resp.content)
    elif os.path.exists(img_src):
        fh = open(img_src, 'rb')
        image = MIMEImage(fh.read(),'jpeg')
        image.add_header('Content-Disposition', 'attachment', filename=os.path.basename(img_src))
        fh.close()

        return image

    return None

def envio_mail(who,nickname,subject):
    html = codecs.open("index.html", 'r', 'utf-8').read()

    msgRoot = MIMEMultipart('related')
    msgRoot['From'] = FROM_EMAIL
    msgRoot['Subject'] = subject
    msgRoot['To'] = nickname + " <" + who + ">"

    soup = BeautifulSoup(html,'lxml')

    cid = 0

    images = []

    for img_element in soup.findAll('img', None):
        img_src = img_element.get('src')

        image = get_image(img_src)

        if image is not None:
            image.add_header('Content-ID', str(cid))
            images.append(image)
            img_element['src'] = "cid:" + str(cid)
            cid += 1

    for element in soup.findAll(attrs={"background" : True}):
        img_src = element.get('background')

        image = get_image(img_src)

        if image is not None:
            image.add_header('Content-ID', str(cid))
            images.append(image)
            element['background'] = "cid:" + str(cid)
            cid += 1

    html = str(soup)

    msgAlternative = MIMEMultipart('alternative')
    msgAlternative.attach(MIMEText(html, "html"))

    msgRoot.attach(msgAlternative)

    for image in images:
        msgRoot.attach(image)
    s = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
    s.ehlo()

    if SMTP_USE_TLS:
        s.starttls() #Puts connection to SMTP server in TLS mode

    s.ehlo()
    s.login(SMTP_USERNAME, SMTP_PASSWORD)

    s.sendmail(msgRoot['From'], who, msgRoot.as_string())
    s.quit()


envio_mail(lista_mails[0],lista_apodos[0],subject)

您需要附加它 并且 在 HTML 中引用它。 IE。附上带有 HTML img 的消息,来源是您附加的图像。

我看到你进展顺利,使用相同的模块并有一个工作代码,所以你应该能够使用下面的代码片段完成它:

.....
import os
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
.....
            # Get the files/images you want to add.
            img_dir = "/images"
            images = [os.path.join(img_dir, i) for i in os.listdir(img_dir)]

            # Added a enumerate loop around the whole procedure.
            # Reference to cid:image_id_"j", which you will attach to the email later.
            for j, val in enumerate(images):
                msgText = MIMEText('<br> <img src="cid:image_id_{}"> </br>'.format(j), 'html')
                msgAlternative.attach(msgText)

                with open('{}'.format(val), "rb") as attachment:
                    msgImage = MIMEImage(attachment.read())

                # Define the image's ID with counter as you will reference it.
                msgImage.add_header('Content-ID', '<image_id_{}>'.format(j))
                msgRoot.attach(msgImage)

对我有用的代码如下所示,因为“msgAlternative.attach(msgText)”被其他图片覆盖,只发现嵌入了最后一张图片:

for val in file_list:
    img = dict(title = val, path = val, cid = str(uuid.uuid4()))
    image.append(img)
    msg_html += u'<h3>{title}</h3><div dir="ltr">''<img src="cid:{cid}" alt="{alt}"><br></div>'.format(alt=cgi.escape(img['title'], quote=True), **img)
msg_html = MIMEText(msg_html, 'html', 'utf-8')
msgAlternative.attach(msg_html)

for j, val in enumerate(file_list):
    with open('{}'.format(val), "rb") as attachment:
        msgImage = MIMEImage(attachment.read())
        # Define the image's ID with counter as you will reference it.
        msgImage.add_header('Content-ID', '<{}>'.format(image[j]['cid']))
        msgRoot.attach(msgImage)