3

我有以下脚本可以成功发送带有附加到 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)
4

2 回答 2

9

您需要附加它在 HTML 中引用它。即附加一条带有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)
于 2019-08-10T17:07:49.977 回答
0

对我有用的代码如下,因为“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)
于 2021-01-29T05:38:56.387 回答