Merge branch 'production'
[matthijs/projects/xerxes.git] / tools / notify.py
1 from django.contrib.auth.models import User,Group
2 from django.core.mail import EmailMessage
3 from django.template import loader
4 from xerxes.tools.misc import make_iter
5
6 """
7 Notify someone about something.
8 """
9 def notify(recipients, template, context = {}):
10     recipients = make_iter(recipients)
11     # Keep a dict of address -> (firstname, lastname)
12     to = {}; 
13     for r in recipients:
14         if (isinstance(r, User)):
15             to[r.email] = (r.first_name, r.last_name)
16         elif (isinstance(r, Group)):
17             to.update([(m.email, (m.first_name, m.last_name)) for m in r.user_set.all()])
18         else:
19             # Assume it is an email address
20             to[r] = None
21
22     for (address, name) in to.items():
23         if name is None:
24             name = (None, None)
25
26         context['first_name'] = name[0]
27         context['last_name']  = name[1]
28
29         rendered = loader.render_to_string(template, context)
30         (headers, body) = rendered.split('\n\n', 1)
31
32         # Turn the headers into a dict so EmailMessage can turn them into a
33         # string again. Bit pointless, but it works. 
34         # Perhaps we should just use python email stuff directly. OTOH, we
35         # still always need to parse for the From header.
36
37         headers_dict = {}
38         # If no From header is present, let EmailMessage do the default
39         # thing
40         from_email = None
41         subject    = ''
42         for header in headers.split('\n'):
43             (field, value) = header.split(':')
44             if (field == 'From'):
45                 from_email = value
46             elif (field == 'Subject'):
47                 subject = value
48             else:
49                 # Don't put From and Subject in the dict, else they'll be
50                 # present twice.
51                 headers_dict[field] = value
52
53         msg = EmailMessage(
54             # Only setting the From address through headers won't set the
55             # envelope address right.
56             from_email = from_email,
57             subject    = subject,
58             body       = body, 
59             to         = [make_rfc822_recipient(address, name)],
60             headers    = headers_dict
61         )
62         msg.send()
63
64 def make_rfc822_recipient(address, name):
65     """
66     Creates a rfc 822 style recipient: Firstname Lastname <address@domain.nl>
67
68     Takes an address and a tuple with firstname and lastname. The tuple can
69     also be None when no name is known.
70     """
71     if name:
72         return "%s %s <%s>" % (name[0], name[1], address)
73     else:
74         return address
75
76 # vim: set sts=4 sw=4 expandtab: