It adds django.shortcuts.send_templated_mail, which mirrors the existing send_mail, but which renders the subject and body of the mail from a template, rather than taking their values explicitly. It also supports multipart html/plaintext emails.

The docs will look something like this...

**send_templated_mail(template_name, from_email, recipient_list, dictionary=None, context_instance=None, fail_silently=False, auth_user=None, auth_password=None, connection=None):**
Sends a mail, rendering the subject and body of the email from a template.
The template should contain a block named 'subject', and either/both of a 'plain' and/or 'html' block.
If only the 'plain' block exists, a plaintext email will be sent.
If only the 'html' block exists, the plaintext component will be automatically generated from the html, and a multipart email will be sent.
If both the 'plain' and 'html' blocks exist, a multipart email will be sent.
**Required arguments:**
`template_name` - The template that should be used to render the email.
`from_email` - The sender's email address.
`recipient_list` - A list of reciepient's email addresses.
**Optional arguments:**
`dictionary` - The context dictionary used to render the template. By default, this is an empty dictionary.
`context_instance` - The Context instance used to render the template. By default, the template will be rendered with a Context instance (filled with values from dictionary).
`fail_silently` - As in `send_mail`.
`auth_user` - As in `send_mail`.
`auth_password` - As in `send_mail`.
`connection` - As in `send_mail`.

It took me and the group I'm with longer than anticipated to get everything up and running. We've written a few unit tests for _render_mail, and aim to finish the rest this coming week. We apologize for the delay.

I have a few doubts about how this has been designed. With both html and plain 'templates' actually just being blocks of a single template, it is not possible to use template inheritance to design consistent emails, which is a common use of the template system. Without this, styles would need to be replicated across multiple templates.

In our send_mail wrapper at $JOB, we allow the user to pass in the stub name of a template. The utility then attempts to render the templates stub+'.html' and stub+'.txt', and uses the results of these to determine whether we send a text/plain, text/html or multipart/alternative.

Instead of extracting the subject from a template, we allow it to be passed in directly. We also add a language argument, which is used to activate the appropriate translation prior to rendering the emails, or coercing the subject to unicode. This allows us to send fully translated emails appropriate for the user receiving the email - which may not be the same as the language currently activated, if there is any, or the language that has been activated for the current view.

It's not quite true that you can't use template inheritance with this style, although I've come around to thinking that it probably is a an abuse of the 'block' tags to change their semantics for email templates.

I don't like the stub+'.txt', stub+'.html' for 2 reasons:

Firstly it's very easy for the two separate files to get out of sync, with no easy way of noticing that's happened.
Secondly the stub + extension style isn't used anywhere else.

I think a better solution would be a single template and a flag to switch between plaintext only, or html + autogenerated plaintext.

It's not impossible that I might get a spare couple of hours between now and the 1.4 checkin deadline, but it's not looking all that likely, so may have to defer this to 1.5.

Thank you all for your great work on this patch. However, I'm struggling a bit to see the value of adding this much new code for something that is already quite easily achievable using render_to_string() and separate templates.

I do agree that creating html+plain emails is still a little too hard in Django, but in my opinion this could be simplified by introducing a new helper class wrapping around EmailMultiAlternatives and providing a simpler API and sensible defaults. For example, something like: HTMLEmailMessage(body_plain='...', body_html='...')

In any case, I personally think that any template rendering should be left to the user to do separately (for example by using render_to_string()).

For now I'm marking this ticket as DDN instead of wontfixing so that more discussion can occur.

I do agree that creating html+plain emails is still a little too hard in Django, but in my opinion this could be simplified by introducing a new helper class wrapping around EmailMultiAlternatives and providing a simpler API and sensible defaults. For example, something like: HTMLEmailMessage(body_plain='...', body_html='...')

I'd be glad to continue work on it, but there is no any reason to polish it more for a while. :( At least unless I need some additional functionality, or some activity is registered on the github project. :) Propositions and suggestions are welcome.

Rendering a template is simple, but there are some minor gotchas in templated email (like remembering to remove newlines from the rendered subject template) that would be reasonable to put in a convenience function in Django rather than requiring everyone to implement them independently. And the EmailMultiAlternatives API is just enough boilerplate to always require looking up in the docs.

IMO the blocks approach implemented above (both in the patch and the linked external project) is too complex, too much code, and too unusual a use of templates (blocks are for template inheritance, not a way to combine multiple templates in one file.) I would rather favor a simple extension naming convention (i.e. give path/to/myemail and it looks for templates path/to/myemail.txt, path/to/myemail.html, and path/to/myemail.subject.txt). I've attached a sample implementation of this approach (not yet integrated as a patch to Django); it really isn't very much code. (This implements a two-layer API, with both a send_multipart function that accepts strings, and a send_templated_multipart that does the template-finding and rendering.)

I guess I'm personally +0 or +0.5 on including something like this in Django. I think it's a very common pattern that's just irritating enough to re-implement to be worth considering for inclusion, but I won't mind at all if another core dev decides to close this wontfix.

If the implementation requires Python code pulling out the blocks from the rendered template for individual specialized handling, then IMO it's a misuse of template blocks and it should be separate templates instead. If the hypothetical email/multipart.html base actually contained a full template for a multipart message, that would be a reasonable use of templates (but still not necessarily a good idea, as the template would then be re-implementing things already handled by EmailMultiAlternatives).

I don't buy the idea that maintaining three files is too hard. But for people who feel that way, alternative approaches would always be available as third-party packages. (Or we can just wontfix this and let all implementations stay outside core, I'm fine with that too.)

No, this does not close the original OPs request, and concept as mentioned by Carl.

This ticket is to introduce a helper function of some sort to handle send_mail(render_to_string(...)). It's just a helper function, it's achievable without, but it's an exceedingly common pattern and personally I'm +1 on having this. A significant number of projects I've worked on have included a utility function named something like render_to_send_mail().

The exact API is up for discussion still, which is probably the blocker for this ticket. As mentioned in #20817, it may be better as extension around the EmailMessage or EmailMultiAlternatives APIs rather than just as a helper function. I can see something like the following API being useful:

A functional approach to this could be added as well as a shortcut function, though this is already significantly easier than the existing APIs to do this. If we take Carl's earlier suggestion about a naming convention, it becomes simpler, alternatively we could add complexity by also supporting kwargs for subject, body and html_body which can take rendered strings as alternatives.

Also, one more argument against the "single template and pull out blocks" suggestion -- a single file with some portions that are HTML and some portions that are text does not work well with editor modes and syntax highlighting.