Login

Template tag to create mailto links with options

Author:
celopes
Posted:
June 19, 2009
Language:
Python
Version:
1.0
Score:
0 (after 0 ratings)

A {% mailto %}{% endmailto %} template tag that requires an e-mail destination and optionally accepts subject, cc and bcc. It will then wrap whatever is within the tag in an <a href="mailto:..."> </a> HTML tag.

See the docstring in the code for the {% mailto %} usage and some examples.

You will need to load this template tag to your template. You can find detailed instructions here. But in a nutshell:

  1. Create a templatetags package (meaning a directory with a init.py file in it) on the same level as your application's model.py
  2. Put the code for this tag in a module (example: extra_tags.py)
  3. On your template use {% load extra_tags %} -- note: the app where the templatetags package was created needs to be in INSTALLED_APPS
  4. Use {% mailto user.email 'You subject here for {{user.get_full_name}}' %}blah{% endmailto %}

This is my first django template tag. I am also NOT tremendously experienced with Python. Criticism and corrections are more than welcome.

  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
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from django import template
from django.template import Node, NodeList, TemplateSyntaxError

register = template.Library()

class MailtoNode(Node):
    '''
        Node for mailto tag
    '''    
    def __init__(self, nodelist, email, subject, cc_list, bcc_list):
        self.nodelist = nodelist
        self.email=template.Variable(email)
        
        self.subject_words=None
        if subject is not None:
            if subject[0] == subject[-1] and subject[0] in ('"', "'"):
                subject=subject[1:-1]
            self.subject_words=[template.Variable(subject_word[2:-2]) if subject_word[0:2] == "{{" and subject_word[-2:] == "}}" else subject_word for subject_word in subject.split(" ")]
            
        self.cc_list=None
        if cc_list is not None:
            if cc_list[0] == cc_list[-1] and cc_list[0] in ('"', "'"):
                self.cc_list=cc_list[1:-1]
            else:
                self.cc_list=template.Variable(cc_list)

        self.bcc_list=None
        if bcc_list is not None:
            if bcc_list[0] == bcc_list[-1] and bcc_list[0] in ('"', "'"):
                self.bcc_list=bcc_list[1:-1]
            else:
                self.bcc_list=template.Variable(bcc_list)

    def render(self, context):
        try:
            email=self.email.resolve(context)
        except:
            email=self.email
            
        additional='?'
        if self.subject_words is not None:
            subject_words_expanded=[]
            for word in self.subject_words:
                word_expanded=''
                try:
                    word_expanded = word.resolve(context)
                except: 
                    word_expanded = word
                # Mailto links sometimes truncates the URI if there is an ampersand in the string somewhere
                subject_words_expanded.append(str(word_expanded).replace('&amp;', '%26').replace('&','%26'))
            additional += 'subject=%s&' % " ".join(subject_words_expanded)
    
        if self.cc_list is not None:
            try:
                cc_list=self.cc_list.resolve(context)
                if isinstance(cc_list, list):
                    cc_list=",".join(cc_list)
            except:
                cc_list=self.cc_list
            additional += 'cc=%s&' % (cc_list)
            
        if self.bcc_list is not None:
            try:
                bcc_list=self.bcc_list.resolve(context)
                if isinstance(bcc_list, list):
                    bcc_list=",".join(bcc_list)
            except:
                bcc_list=self.bcc_list
            additional += 'bcc=%s&' % (bcc_list)
           
        nodelist_expanded=[]
        for node in self.nodelist:
            try:
                nodelist_expanded.append(node.render(context))
            except:
                nodelist_expanded.append(node)
        linktext=' '.join(nodelist_expanded)
            
        return '<a href="mailto:%s%s">%s</a>' % (email, additional[0:-1], linktext)

@register.tag
def mailto(parser, token):
    '''
        Custom template tag to create complete mailto links.
        
        Format:
        
        {% mailto email subject comma_separated_cc_list comma_separated_bcc_list %}link content{% endmailto %}
        
        Where:  email is the recipient (only required field; string or context variable)
                subject is the subject for the email (optional; string containing context variables with no {{}}.)
                cc is the comma separated list of carbon copied (optional; will also accept a variable containing a string or python list)
                bcc is the comma separated list of blind carbon copied (optional; will also accept a variable containing a string or a python list)
        
        Examples: 
            {% mailto '[email protected]' 'subject line' '[email protected], [email protected]' '[email protected]' %}link text{% endmailto %}
        Produces:
            <a href="mailto:[email protected]?subject=subject line&[email protected], [email protected]&[email protected]">link text</a>
    
        Examples: 
            {% mailto context.var.email 'subject for user.get_full_name' context.var.cc '[email protected]' %}link text{% endmailto %}
            Where context.var.email has [email protected], context.var.cc has [email protected], and current user is jimmy
        Produces:
            <a href="mailto:[email protected]?subject=subject for jimmy&[email protected]&[email protected]">link text</a>
    '''
    tokenlist = token.split_contents()
    if len(tokenlist) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument"
                                  " (the email recipient)" % tokenlist[0])
    
    email=tokenlist[1]
    subject=None
    if len(tokenlist) >= 3:
        subject = tokenlist[2]
    cc_list=None
    if len(tokenlist) >= 4:
        cc_list=tokenlist[3]
    bcc_list=None
    if len(tokenlist) == 5:
        bcc_list=tokenlist[4]
    
    nodelist = parser.parse(('endmailto',))
    parser.delete_first_token()
    
    return MailtoNode(nodelist, email, subject, cc_list, bcc_list)

More like this

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

Comments

Please login first before commenting.