Python-通过嵌入图像向GMAIL发送邮件

Python-通过嵌入图像向GMAIL发送邮件,python,html,mail-sender,Python,Html,Mail Sender,我有以下脚本,可以成功地发送带有附加到hotmail的图像的邮件。 问题是,如果我向GMAIL发送相同的邮件,图像会附加在邮件中,而不会嵌入HTML中。 为什么会这样?如何修复它? 例如,HTML中的图像以以下方式显示: 这是当前的代码 #!/usr/bin/env python3 # -*- coding: utf-8 -*- import base64 import email import smtplib import os from email.mime.text import MI

我有以下脚本,可以成功地发送带有附加到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)
#/usr/bin/env蟒蛇3
#-*-编码:utf-8-*-
导入base64
导入电子邮件
导入smtplib
导入操作系统
从email.mime.text导入MIMEText
从email.mime.multipart导入MIMEMultipart
从email.mime.image导入MIMEImage
从email.header导入头
导入编解码器
从bs4导入BeautifulSoup
导入模拟类型
导入请求
导入时间
SMTP_SERVER=“xxx”
SMTP_端口=587
SMTP_USERNAME=“xxx”
SMTP_PASSWORD=“xxx”
SMTP\u使用\u TLS=False
从_电子邮件=”xxx@xxx.com"
lista_邮件=['我的_mail@hotmail.com']
lista_apodos=['user']
主题为“测试邮件”
def get_图像(img_src):
如果img_src.startswith('http://')或img_src.startswith('https://'):
尝试:
resp=requests.get(img\u src)
除:
打印(“检索{}.format失败(img_src))
打印(分别为文本)
一无所获
返回模拟图像(分别为内容)
elif os.path.exists(img_src):
fh=打开(img_src,'rb')
image=mimimage(fh.read(),'jpeg')
image.add_头('Content-Disposition','attachment',filename=os.path.basename(img_src))
fh.close()
返回图像
一无所获
def envio_邮件(谁、昵称、主题):
html=codecs.open(“index.html”,“r”,“utf-8”).read()
msgRoot=MIMEMultipart('related')
msgRoot['From']=来自电子邮件
msgRoot['Subject']=主语
msgRoot['To']=昵称+“”
soup=BeautifulSoup(html,'lxml')
cid=0
图像=[]
对于汤中的img_元素。findAll('img',无):
img_src=img_元素.get('src'))
image=get\u image(img\u src)
如果图像不是无:
image.add_头('Content-ID',str(cid))
images.append(图像)
img_元素['src']=“cid:+str(cid)
cid+=1
对于soup.findAll中的元素(attrs={“background”:True}):
img_src=element.get('background')
image=get\u image(img\u src)
如果图像不是无:
image.add_头('Content-ID',str(cid))
images.append(图像)
元素['background']=“cid:+str(cid)
cid+=1
html=str(汤)
msgAlternative=MIMEMultipart('备选方案')
附加(MIMEText(html,“html”))
msgRoot.attach(msgaltentive)
对于图像中的图像:
msgRoot.attach(图片)
s=smtplib.SMTP(SMTP_服务器、SMTP_端口)
s、 ehlo()
如果SMTP\u使用\u TLS:
s、 starttls()#将与SMTP服务器的连接置于TLS模式
s、 ehlo()
s、 登录(SMTP\u用户名、SMTP\u密码)
s、 sendmail(msgRoot['From'],who,msgRoot.as_string())
s、 退出
环境邮件(列表邮件[0],列表邮件[0],主题)

您需要附加它,并在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)
。。。。。
导入操作系统
从email.mime.text导入MIMEText
从email.mime.base导入MIMEBase
从email.mime.image导入MIMEImage
.....
#获取要添加的文件/图像。
img_dir=“/images”
images=[os.path.join(img\u dir,i)代表os.listdir(img\u dir)中的i]
#在整个过程中添加了枚举循环。
#参考cid:image_id_uj,您稍后会将其附加到电子邮件中。
对于j,枚举中的val(图像):
msgText=MIMEText(“

”。格式(j),“html”) msgAlternative.attach(msgText) 以open({}.format(val),“rb”)作为附件: msgImage=MIMEImage(附件.read()) #在引用图像时,使用计数器定义图像的ID。 msgImage.add_标题('Content-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)
文件列表中val的
:
img=dict(title=val,path=val,cid=str(uuid.uuid4())
image.append(img)
msg_html+=u'{title}'
'.格式(alt=cgi.escape(img['title'],quote=True),**img) msg_html=MIMEText(msg_html,'html','utf-8') msgAlternative.attach(msg_html) 对于j,枚举中的val(文件列表): 以open({}.format(val),“rb”)作为附件: msgImage=MIMEImage(附件.read()) #在引用图像时,使用计数器定义图像的ID。 msgImage.add_头('Content-ID',''.format(image[j]['cid'])) msgRoot.attach(msgImage)
什么是index.html可能重复?它是包含图像的html:我想这个链接可能会对您有所帮助。如何在一个盒子里嵌入大约10幅图像呢?我为每张图片重复“打开”这个词?好的,多张图片/附件:我认为这样的东西应该适合你。只需循环/枚举附件进程n次,并向“image_id”添加一个计数器