当前位置: 首页 > 面试题库 >

使用Python将电子邮件与内嵌图像发送到Gmail

冯俊英
2023-03-14
问题内容

我的目标是使用Python向具有嵌入式图像的Gmail用户发送电子邮件。href由于图片(我的工作中的数据)的敏感性,无法在线托管该图片,然后通过链接到该图片。

我尝试过将base64版本编码为,HTML然后发送th is
HTML,但是众所周知这是行不通的。然后,我注意到在Gmail中,您可以将图像拖放到发送框中,它将在接收端内联显示。鉴于此,我然后尝试从Python发送带有图像作为附件的电子邮件。在下面的代码中可以看到这一点,但是不幸的是,该图像没有内联显示。

我的问题是: 如何发送图像以使其内联显示?

    import smtplib
    from email.MIMEMultipart import MIMEMultipart
    from email.MIMEBase import MIMEBase
    from email.MIMEText import MIMEText
    from email import Encoders
    import os

    gmail_user = "user1@gmail.com"
    gmail_pwd = "pass"

    to = "user2@gmail.com"
    subject = "Report"
    text = "Picture report"
    attach = 'TESTING.png'

    msg = MIMEMultipart()

    msg['From'] = gmail_user
    msg['To'] = to
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    part = MIMEBase('application', 'octet-stream')
    part.set_payload(open(attach, 'rb').read())
    Encoders.encode_base64(part)
    part.add_header('Content-Disposition',
       'attachment; filename="%s"' % os.path.basename(attach))
    msg.attach(part)

    mailServer = smtplib.SMTP("smtp.gmail.com", 587)
    mailServer.ehlo()
    mailServer.starttls()
    mailServer.ehlo()
    mailServer.login(gmail_user, gmail_pwd)
    mailServer.sendmail(gmail_user, to, msg.as_string())
    # Should be mailServer.quit(), but that crashes...
    mailServer.close()

当我手动将嵌入式图像发送给自己时,这就是“原始电子邮件”的样子:

      Content-Type: multipart/related; boundary=047d7bd761fe73e03304e7e02237

    --047d7bd761fe73e03304e7e02237
    Content-Type: multipart/alternative; boundary=047d7bd761fe73e03004e7e02236

    --047d7bd761fe73e03004e7e02236
    Content-Type: text/plain; charset=ISO-8859-1

    [image: Inline images 1]

    --047d7bd761fe73e03004e7e02236
    Content-Type: text/html; charset=ISO-8859-1

    <div dir="ltr"><img alt="Inline images 1" src="cid:ii_141810ee4ae92ac6" height="400" width="534"><br></div>

    --047d7bd761fe73e03004e7e02236--
    --047d7bd761fe73e03304e7e02237
    Content-Type: image/png; name="Testing.png"
    Content-Transfer-Encoding: base64
    Content-ID: <ii_141810ee4ae92ac6>
    X-Attachment-Id: ii_141810ee4ae92ac6

当我通过Python将其作为附件发送给自己时,它是非常不同的:

    Content-Type: multipart/mixed; boundary="===============6881579935569047077=="
    MIME-Version: 1.0
    (.... some stuff deleted here)
    --===============6881579935569047077==
    Content-Type: text/plain; charset="us-ascii"
    MIME-Version: 1.0
    Content-Transfer-Encoding: 7bit

    See attachment for report.
    --===============6881579935569047077==
    Content-Type: application/octet-stream
    MIME-Version: 1.0
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment; filename="TESTING.png"

问题答案:

似乎遵循gmail电子邮件模板有效:

* multipart/alternative
  - text/plain
  - multipart/related
    + text/html
      <img src="cid:msgid"/>
    + image/png
      Content-ID: <msgid>

基于email 模块文档中的示例:

#!/usr/bin/env python3
import html
import mimetypes
from email.headerregistry import Address
from email.message import EmailMessage
from email.utils import make_msgid
from pathlib import Path

title = "Picture report…"
path = Path('TESTING.png')
me = Address("Pepé Le Pew", *gmail_user.rsplit('@', 1))

msg = EmailMessage()
msg['Subject'] = 'Report…'
msg['From'] = me
msg['To'] = [me]
msg.set_content('[image: {title}]'.format(title=title))  # text/plain
cid = make_msgid()[1:-1]  # strip <>    
msg.add_alternative(  # text/html
    '<img src="cid:{cid}" alt="{alt}"/>'
    .format(cid=cid, alt=html.escape(title, quote=True)),
    subtype='html')
maintype, subtype = mimetypes.guess_type(str(path))[0].split('/', 1)
msg.get_payload()[1].add_related(  # image/png
    path.read_bytes(), maintype, subtype, cid="<{cid}>".format(cid=cid))

# save to disk a local copy of the message
Path('outgoing.msg').write_bytes(bytes(msg))

msg通过gmail发送:

import smtplib
import ssl

with smtplib.SMTP('smtp.gmail.com', timeout=10) as s:
    s.starttls(context=ssl.create_default_context())
    s.login(gmail_user, gmail_password)
    s.send_message(msg)

Python 2/3兼容版本

* multipart/related
  - multipart/alternative
    + text/plain
    + text/html
      <div dir="ltr"><img src="cid:ii_xyz" alt="..."><br></div>
  - image/jpeg
    Content-ID: <ii_xyz>

基于发送带有嵌入式图像和纯文本备用内容的HTML电子邮件:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cgi
import uuid
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text      import MIMEText
from email.mime.image     import MIMEImage
from email.header         import Header

img = dict(title=u'Picture report…', path=u'TESTING.png', cid=str(uuid.uuid4()))

msg = MIMEMultipart('related')
msg['Subject'] = Header(u'Report…', 'utf-8')
msg['From'] = gmail_user
msg['To'] = ", ".join([to])
msg_alternative = MIMEMultipart('alternative')
msg.attach(msg_alternative)
msg_text = MIMEText(u'[image: {title}]'.format(**img), 'plain', 'utf-8')
msg_alternative.attach(msg_text)

msg_html = MIMEText(u'<div dir="ltr">'
                     '<img src="cid:{cid}" alt="{alt}"><br></div>'
                    .format(alt=cgi.escape(img['title'], quote=True), **img),
                    'html', 'utf-8')
msg_alternative.attach(msg_html)

with open(img['path'], 'rb') as file:
    msg_image = MIMEImage(file.read(), name=os.path.basename(img['path']))
    msg.attach(msg_image)
msg_image.add_header('Content-ID', '<{}>'.format(img['cid']))

msg通过gmail发送:

import ssl

s = SMTP_SSL('smtp.gmail.com', timeout=10,
             ssl_kwargs=dict(cert_reqs=ssl.CERT_REQUIRED,
                             ssl_version=ssl.PROTOCOL_TLSv1,
                             # http://curl.haxx.se/ca/cacert.pem
                             ca_certs='cacert.pem')) 
s.set_debuglevel(0)
try:
    s.login(gmail_user, gmail_pwd)
    s.sendmail(msg['From'], [to], msg.as_string())
finally:
    s.quit()

SMTP_SSL是可选的,您可以改用starttls问题中的方法:

import smtplib
import socket
import ssl
import sys

class SMTP_SSL(smtplib.SMTP_SSL):
    """Add support for additional ssl options."""
    def __init__(self, host, port=0, **kwargs):
        self.ssl_kwargs = kwargs.pop('ssl_kwargs', {})
        self.ssl_kwargs['keyfile'] = kwargs.pop('keyfile', None)
        self.ssl_kwargs['certfile'] = kwargs.pop('certfile', None)
        smtplib.SMTP_SSL.__init__(self, host, port, **kwargs)

    def _get_socket(self, host, port, timeout):
        if self.debuglevel > 0:
            print>>sys.stderr, 'connect:', (host, port)
        new_socket = socket.create_connection((host, port), timeout)
        new_socket = ssl.wrap_socket(new_socket, **self.ssl_kwargs)
        self.file = getattr(smtplib, 'SSLFakeFile', lambda x: None)(new_socket)
        return new_socket


 类似资料:
  • 问题内容: 我正在尝试使用图像发送带有PHPMailer的HTML邮件。正文是从包含所有信息的html文件加载的。 发送邮件时,尽管我什至也将图像作为附件发送,但图像并未出现在正文中。 HTML 标记指向与该位置相同的位置。 PHP: 如何使html指向附件,以便可以将图像加载到正文中。 查看PHPMailer附带的示例,我没有发现任何区别,在这种情况下,确实出现了图像。 问题答案: 我找到了答案

  • 问题内容: 我正在尝试发送包含嵌入式gif图像的多部分/相关html电子邮件。该电子邮件是使用Oracle PL / SQL生成的。我的尝试失败了,图片显示为红色X(在Outlook 2007和yahoo邮件中) 我已经发送HTML电子邮件已有一段时间了,但是我现在的要求是在电子邮件中使用多个gif图像。我可以将它们存储在我们的一台Web服务器上并仅链接到它们,但是许多用户的电子邮件客户端不会自动

  • 问题内容: 如何使用Python在电子邮件中发送HTML内容?我可以发送简单的文字。 问题答案: 这是一个如何使用替代纯文本版本创建HTML消息的示例:

  • 问题内容: 我想使用gmail作为smtp服务器发送电子邮件。 这是我的代码,我没有让它工作…运行testSettings()之后,我得到了调试输出,然后它停止了。没有超时,没有错误,什么都没有。 发生以下错误:http : //pastie.org/private/rkoknss6ppiufjd9swqta 问题答案: 代替 props.put(“ mail.transport.protocol

  • 我目前正在使用yagmail模块使用Python发送电子邮件,并且我很难将本地存储的图像嵌入到电子邮件中。这可能吗? 下面是一个代码示例: 使用上面的代码示例,如果我输入一个外部路径(例如,imgur图像或谷歌图像),它完美地工作,把我似乎无法得到一个本地路径识别。 解决方案不必使用yagmail,它似乎是我迄今为止使用的最简单的电子邮件模块。 谢谢你的帮助!

  • 问题内容: 如何使用curl命令行程序从gmail帐户发送电子邮件? 我尝试了以下方法: 使用file.txt作为电子邮件的内容,但是,当我运行此命令时,出现以下错误: 是否可以从仍由curl托管的个人服务器托管帐户发送电子邮件?这样会使身份验证过程更容易吗? 问题答案: curl –url 'smtps://smtp.gmail.com:465’ –ssl-reqd \ –mail-from '