Different email clients choose to render multipart/mixed
messages in different ways.
Most clients choose to render each part (in a "multipart" message) inline – in the order they were added to the email. However, if an image is referred to in a text/html
part, most clients don't display that image again later on as part of the "inlining all parts" process.
Apple Mail on OSX and iOS are different, in so far as they will display each part in a multipart/mixed
message in the order they were included, regardless of any inner references between HTML and images. This results in your images being displayed once within your HTML, and again at the end of the message where they've been inlined automatically.
The solution is to group your HTML and image assets into a single related
part. i.e.:
from django.core.mail import EmailMultiAlternatives
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# HTML + image container
related = MIMEMultipart("related")
# Add the HTML
html = MIMEText('an image: <img src="cid:some_image"/>', "html")
related.attach(html)
# Add an image
with open("icon.png", "rb") as handle:
image = MIMEImage(handle.read())
image.add_header("Content-ID", "<some_image>")
image.add_header("Content-Disposition", "inline")
related.attach(image)
# top level container, defines plain text version
email = EmailMultiAlternatives(subject="demo", body="plain text body",
from_email="foo@example.com",
to=["bar@example.com"])
# add the HTML version
email.attach(related)
# Indicate that only one of the two types (text vs html) should be rendered
email.mixed_subtype = "alternative"
email.send()
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…