Displaying inline images on iPhone, iPad
Question: I'm trying to create an email in Django with inline images.

    
    
    msg = EmailMultiAlternatives(...)
    image_file = open('file_path', 'rb') 
    img = MIMEImage(img_data)
    image_file.close()
    img.add_header('Content-ID', '<image1>') 
    img.add_header('Content-Disposition', 'inline')
    msg.attach(img)
    msg.send()
    

And in the template I would reference it like so:

    
    
    <img src="cid:image1" />
    

This works fine in web browsers, outlook, thunderbird ... all except for the
apple mail client on OSX, iPad and iPhone. The images are displayed twice.
They are placed inline correctly but they are also attached to the bottom of
the email. My question is, how do I get rid of the images at the bottom? or
should I approach images in emails differently.

References:  
<http://djangosnippets.org/snippets/1507/>  
[Django: How to send HTML emails with embedded
images](http://stackoverflow.com/questions/3787755/django-how-to-send-html-
emails-with-embedded-images)  
[creating a MIME email template with images to send with python /
django](http://stackoverflow.com/questions/1633109/creating-a-mime-email-
template-with-images-to-send-with-python-django)


Answer: 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()
    

