As we all know (or should), you can use Django's template system to render email bodies:
def email(email, subject, template, context):
from django.core.mail import send_mail
from django.template import loader, Context
send_mail(subject, loader.get_template(template).render(Context(context)), 'from@domain.com', [email,])
This has one flaw in my mind: to edit the subject and content of an email, you have to edit both the view and the template. While I can justify giving admin users access to the templates, I'm not giving them access to the raw python!
What would be really cool is if you could specify blocks in the email and pull them out separately when you send the email:
{% block subject %}This is my subject{% endblock %}
{% block plaintext %}My body{% endblock%}
{% block html %}My HTML body{% endblock%}
But how would you do that? How would you go about rendering just one block at a time?
This is my third working iteration. It assuming you have an email template like so:
{% block subject %}{% endblock %}
{% block plain %}{% endblock %}
{% block html %}{% endblock %}
I've refactored to iterate the email sending over a list by default and there are utility methods for sending to a single email and django.contrib.auth
User
s (single and multiple). I'm covering perhaps more than I'll sensibly need but there you go.
I also might have gone over the top with Python-love.
def email_list(to_list, template_path, context_dict):
from django.core.mail import send_mail
from django.template import loader, Context
nodes = dict((n.name, n) for n in loader.get_template(template_path).nodelist if n.__class__.__name__ == 'BlockNode')
con = Context(context_dict)
r = lambda n: nodes[n].render(con)
for address in to_list:
send_mail(r('subject'), r('plain'), 'from@domain.com', [address,])
def email(to, template_path, context_dict):
return email_list([to,], template_path, context_dict)
def email_user(user, template_path, context_dict):
return email_list([user.email,], template_path, context_dict)
def email_users(user_list, template_path, context_dict):
return email_list([user.email for user in user_list], template_path, context_dict)
As ever, if you can improve on that, please do.