Using the Python mailmerge command to send customized emails
Overview
Mailmerge is a Python command line tool to send individual customized email messages based on Jinja2 templates and an email database.
Details
Install mailmerge
:
pip install mailmerge
Configure the system by creating sample configuration files:
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ mailmerge --sample
Created sample template email "mailmerge_template.txt"
Created sample database "mailmerge_database.csv"
Created sample config file "mailmerge_server.conf"
Edit these files, then run mailmerge again.
The mailmerge_template.txt
is the source of the email message. The file is a Jinja2 template where variables are stored in {{variables}}
. Each of these fields are replaced with data from the mailmerge_database.csv
.
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ cat mailmerge_template.txt
TO: {{email}}
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
Hi, {{name}},
Your number is {{number}}.
The mailmerge_database.csv
contains the values for the Jinja2 variables used in the mailmerge_template.txt
:
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ cat mailmerge_database.csv
email,name,number
jemurray@zweck.net,"Myself",17
test@example.com,"Test",42
Configure a valid email server in the mailmerge_server.conf
file. In this example, I use a Gmail account to send the emails:
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ cat mailmerge_server.conf
# GMail
[smtp_server]
host = smtp.gmail.com
port = 465
security = SSL/TLS
username = example@gmail.com
My Gmail account uses 2-factor authentication. mailmerge
does not support 2FA, therefore requires a static application password. Generate one from the Google account settings:
Save the password:
Once the templates, variable expansions, and servers are configured, validate the configuration and view an expanded email without sending anything (dry run mode):
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ mailmerge
>>> message 1
TO: jemurray@zweck.net
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Date: Wed, 24 Mar 2021 19:40:43 -0000
Hi, Myself,
Your number is 17.
Attempt to send 1 message as a test by adding the --no-dry-run
option. Make sure it looks good before sending to the entire list:
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ mailmerge --no-dry-run
>>> password for example@gmail.com on smtp.gmail.com:
>>> message 1
TO: jemurray@zweck.net
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Date: Wed, 24 Mar 2021 19:43:29 -0000
Hi, Myself,
Your number is 17.
>>> message 1 sent
>>> Limit was 1 message. To remove the limit, use the --no-limit option.
After validating a single message looks ok, send to the entire list by adding the --no-limit
option:
(.venv) jemurray@phalanges:~/Documents/src/personalPython/mailmerge $ mailmerge --no-dry-run --no-limit
>>> password for example@gmail.com on smtp.gmail.com:
>>> message 1
TO: jemurray@zweck.net
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Date: Wed, 24 Mar 2021 19:44:52 -0000
Hi, Myself,
Your number is 17.
>>> message 1 sent
>>> message 2
TO: test@example.com
SUBJECT: Testing mailmerge
FROM: My Self <myself@mydomain.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Date: Wed, 24 Mar 2021 19:44:55 -0000
Hi, Test,
Your number is 42.
>>> message 2 sent