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
Tags:
email attachment
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

Comments

nelsonvarela (on July 11, 2012):
<p>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.</p>

#

[email protected] (on July 11, 2012):
<p>Here is how I have used it in my code:</p> <pre>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() </pre>

#

nelsonvarela (on July 12, 2012):
<p>Thanks for helping me out. This helped me allot!</p>

#

nelsonvarela (on July 16, 2012):
<p>Images are blocked in Gmail. Do yo have the same issue. If not, what can I do so that Gmail shows images immediately??</p>

#

Please login first before commenting.