Jun Murakami
Jun Murakami

Reputation: 845

What would be the right way to render jinja2 template in the pyramid view for an e-mail message?

I use pyramid_mailer package to send emails in my pyramid app.

I found examples, where as body for an e-mail were used only simple strings. Obviously, in the real app, I need to use more complicated templates, with information populated in the view callable.

For example:

# templates/mail/notification.jinja2
Dear {{username}},<br> blah blah blah... 

I use Jinja2 for templating and came up with the following solution:

@view_config(route_name='email', renderer='templates/email.jinja2')
def send_email(request):
    import pyramid_jinja2
    user = # ... got user from DB
    env = pyramid_jinja2.get_jinja2_environment(request)
    template = env.get_template('/templates/mail/notification.jinja2')
    message = template.render({'username': user.name})

It works, but looks a bit cluttered.

So, the question here: Is this the right way of doing it?

Upvotes: 3

Views: 1282

Answers (1)

Mikko Ohtamaa
Mikko Ohtamaa

Reputation: 83358

Please see the following code:

from pyramid.renderers import render

from pyramid_mailer import get_mailer
from pyramid_mailer.message import Message

import premailer


def send_templated_mail(request, recipients, template, context, sender=None):
    """Send out templatized HTML and plain text emails.

    Each HTML email should have a plain text fallback. Premailer package is used to convert any CSS styles in HTML email messages to inline, so that email clients display them.  

    The email is assembled from three different templates:

    * Read subject from a subject specific template $template.subject.txt

    * Generate HTML email from HTML template, $template.body.html

    * Generate plain text email from HTML template, $template.body.txt

    Make sure you have configured your template engine (Jinja 2) to read TXT templates beside HTML.

    :param request: HTTP request, passed to the template engine. Request configuration is used to get hold of the configured mailer.

    :param recipients: List of recipient emails

    :param template: Template filename base string for template tripled (subject, HTML body, plain text body). For example ``email/my_message`` would map to templates ``email/my_message.subject.txt``, ``email/my_message.body.txt``, ``email/my_message.body.html``

    :param context: Template context variables as a dict

    :param sender: Override the sender email - if not specific use the default set in the config as ``mail.default_sender``
    """

    assert recipients
    assert len(recipients) > 0
    assert type(recipients) != str, "Please give a list of recipients, not a string"

    subject = render(template + ".subject.txt", context, request=request)
    subject = subject.strip()

    html_body = render(template + ".body.html", context, request=request)
    text_body = render(template + ".body.txt", context, request=request)

    if not sender:
        sender = request.registry.settings["mail.default_sender"]

    # Inline CSS styles
    html_body = premailer.transform(html_body)

    message = Message(subject=subject, sender=sender, recipients=recipients, body=text_body, html=html_body)

    mailer = get_mailer(request)
    mailer.send(message)

Upvotes: 2

Related Questions