Login

Take a django.core.mail email message and replace any MEDIA_URL-served images with attached images

Author:
[email protected]
Posted:
January 24, 2012
Language:
Python
Version:
Not specified
Score:
0 (after 0 ratings)

The code here will take an EmailMessage from django.core.mail and replace the sourcing of any images served by the application with attached image content. Note: This expects a valid closing tag of /> on img elements, it will not properly handle filenames with ' characters in it, and it does not handle if invalid image sources are listed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import string
import random
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for x in range(size))

    
def localize_html_email_images(message):
    """Replace linked images served locally with attached images"""

    import re, os.path
    from email.MIMEImage import MIMEImage

    from django.conf import settings
    image_pattern = """<img\s*.*src=['"](?P<img_src>%s[^'"]*)['"].*\/>""" % settings.MEDIA_URL

    image_matches = re.findall(image_pattern, message.body)

    added_images = {}

    for image_match in image_matches:

        if image_match not in added_images:

            img_content_cid = id_generator()
            on_disk_path = os.path.join(settings.MEDIA_ROOT, image_match.replace(settings.MEDIA_URL, ''))
            img_data = open(on_disk_path, 'rb').read()
            img = MIMEImage(img_data)
            img.add_header('Content-ID', '<%s>' % img_content_cid)
            img.add_header('Content-Disposition', 'inline')
            message.attach(img)

            added_images[image_match] = img_content_cid

    def repl(matchobj):
        x = matchobj.group('img_src')
        y = 'cid:%s' % str(added_images[matchobj.group('img_src')])
        return matchobj.group(0).replace(matchobj.group('img_src'), 'cid:%s' % added_images[matchobj.group('img_src')])

    if added_images:
        message.body = re.sub(image_pattern, repl, message.body)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

nelsonvarela (on July 11, 2012):

Hi there, Can you put or send me an example how to use this code? What do i throw into 'localize_html_email_images(???)'. I guess the rendered html template but i'm not sure.

#

[email protected] (on July 11, 2012):

Here is how I have used it in my code:

def send_html_email(template, context, title, recipients, text_template = None):
    from django.template import loader, Context
    from django.conf import settings
    import os.path

    t = loader.get_template(template)
    html_content = t.render(Context(context))

    if (text_template):
        t = loader.get_template(text_template)
        text_content = t.render(Context(context))
    else:
        from html2text import html2text

        text_content = html2text(html_content)

    from django.core.mail import EmailMultiAlternatives, EmailMessage

    subject, from_email = title, server_email()

    if isinstance(recipients, basestring):
        to = [recipients]
    else:
    to = recipients

    msg = EmailMessage(subject, html_content, from_email,
         to)
    msg.content_subtype = "html"  # Main content is now text/html

    localize_html_email_images(msg)

    if 'attachments' in context:
        for att in context['attachments']:
            msg.attach_file(os.path.join(settings.MEDIA_ROOT, att ))

    if 'file_attachments' in context:
        for att in context['file_attachments']:
            msg.attach_file(att)

    msg.send()

#

nelsonvarela (on July 12, 2012):

Thanks for helping me out. This helped me allot!

#

nelsonvarela (on July 16, 2012):

Images are blocked in Gmail. Do yo have the same issue. If not, what can I do so that Gmail shows images immediately??

#

Please login first before commenting.