Send an HTML Email Template with Python and Jinja2
Tags: python, jinja, template
Published: 2019-07-13 11:09:43

This is my first post in dev.to. 
As a beginner developer and as a practice exercise, I have learned how to send an HTML Email template using Python and Jinja2.

In the beginning, I focused on sending simple plain text, images, and template files emails. After understanding the logic of emails, I started to learn about the template engine and how to combine my template file with some data, first with Python's built-in string formatters and then with Jinja2.

In this post I am going to explore: 
- How to set up a local SMTP (Simple Mail Transfer Protocol) and to send an Email with Python.
- Template engine
- Loading a template
- Template Inheritance
- Control Structures

###Set up a local SMTP (Simple Mail Transfer Protocol)

Python contains the built-in smtplib module for sending emails, you can send plain text, images, attachments, and an HTML.

I started installing everything I needed for testing the email functionality.

Import the SMTP
```
from smtplib import SMTP 
```

Import from email.mime modules that also Python provides, MIMEtext and MIMEMultipart. MIMEText() objects will contain the HTML, and the MIMEMultipart("alternative") will combine the parts in a single message.
```
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
```

###Set up Jinja2

Import from Jinja2 the Environment, FileSystemsLoader, and os. For Jinja2 you can use pip or easy_install.
```
from jinja2 import Environment, FileSystemLoader
import os
```

###Loading a template with Jinja2.

The FileSystemLoader from Jinja2 helps to get the template from the file system or other location and the Environment will load it.
```
env = Environment(
    loader=FileSystemLoader('%s/templates/' % os.path.dirname(__file__)))
```

###The data in JSON format
```
def get_data():
    data = []
    data.append(
        {
         "movies": [
             {         
                 "title": 'Terminator',
                 "description": 'One soldier is sent back to protect her from the killing machine. He must find Sarah before the Terminator can carry out its mission.'
             },
             {                 
                 "title": 'Seven Years in Tibet',
                 "description": 'Seven Years in Tibet is a 1997 American biographical war drama film based on the 1952 book of the same name written by Austrian mountaineer Heinrich Harrer on his experiences in Tibet.'
             },
             {               
                 "title": 'The Lion King',
                 "description": 'A young lion prince is born in Africa, thus making his uncle Scar the second in line to the throne. Scar plots with the hyenas to kill King Mufasa and Prince Simba, thus making himself King. The King is killed and Simba is led to believe by Scar that it was his fault, and so flees the kingdom in shame.'
             }
         ]
         })
    return data
```

###Sending the email with HTML content

After installing all the necessary, I created a method for to send the email, it is include sender, receiver, subject, the HTML and the local server. In this case I used a Gmail account.
```
def send_mail(bodyContent):
    to_email = 'to@gmail.com'
    from_email = 'from@gmail.com'
    subject = 'This is a email from Python with a movies list!'
    message = MIMEMultipart()
    message['Subject'] = subject
    message['From'] = from_email
    message['To'] = to_email

    message.attach(MIMEText(bodyContent, "html"))
    msgBody = message.as_string()

    server = SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(from_email, 'your password')
    server.sendmail(from_email, to_email, msgBody)

    server.quit()
```

I created a second method to get the data, to load the template from the environment I used before, also I called the get_template() method which will return the loaded Template and for to render the template with the data I called the render() method.
```
def send_movie_list(event, context):
    json_data = get_data()
    template = env.get_template('child.html')
    output = template.render(data=jsonData[0])
    send_mail(output)    
    return "Mail sent successfully."
```

###Template Engine and Template Inheritance in Jinja2

Jinja2 is a template engine for Python. The template engine allows us to combine a template file with a data model and generate the desired content types.
There are different options when we are working with templates engine, one of them is Python's built-in string formatters, but sometimes we need something more powerful and that is the reason why I chose Jinja2.
Jinja2 is a modern templating language for Python. You can use it within a framework or without it. In this case, I did not use any framework.

Jinja2 contains the template inheritance, it defines an HTML skeleton document. The block tags define one block where the child template can fill in. You can define the number of blocks that you need. In this case, I only have one.
I called this template, "base.html".
```
<!DOCTYPE html>
<html lang="en">
<head>   
    <title>Movies</title>  
</head>
<body>
    <div id="content">{% block content %}{% endblock %}</div>     
</body>
</html>
```

###Control Structures with Jinja2

I created a second template called child, "child.html", contains a for loop to display our movies and a conditional.
```
{% extends "base.html" %}
{% block content %}
    <h1>Movies</h1>
    <p>
      {% for movie in data['movies'] %} {%if movie['title']!="Terminator" %}
      {{ movie['title'] }}
      {% endif %} {% endfor %}
    </p>
{% endblock %}
```

It's done!

[You can read more about Jinja2 here.](http://jinja.pocoo.org/docs/2.10/)