Sending HTML Emails With Python

by IoFAdmin at

python | programming

Send HTML Emails And Amaze Your Friends!

I guess that depends on how easy your friends are to impress...

Overview and a Disclaimer

We're going to use Google's Gmail to act as our email provider because it's free and easy to set up.

What this project is:

  • a simple example of how to send multipart emails
  • a proof of concept

What this project is not:

  • a production-ready email sending system
  • an in-depth tutorial of email design

Don't Use This For An Email Server!

Like I said above, this is a proof of concept. If you try to send a ton of emails in a short period of time, Google will probably ban your account. This tutorial will work fine if you send to your friends and family but not to a contact list of a 1000 emails.

First Steps

  • Create a new email address at Gmail.
  • Set up your Gmail account to allow sending emails from your Python script. Follow these steps. This will make you Gmail account "less secure" (as Google puts it) so that's why you should use your newly created account instead of your main one.

Super Simple Discussion of Multipart Emails

So what are multipart emails you ask? I got you covered Random Internet Stranger! When you send HTML emails you are actually sending two version of the email: text and HTML. It can get rather complicated so I won't go into here but your email client will display either the text or HTML version depending on its settings. The two versions of the email can be completely different, but the main content should be the same.

Compose Your Email!

Create a file called email.txt and put this in it:

Email Test
----------

See More at {QUICKLINK_URL}

{FROM_ROLE} {FROM_FULLNAME}
Internet Expert

Hi {TO_FIRSTNAME},

We're so glad that you're interested in becoming an Internet Guru! Just go to our website and we'll tell you how you can become the envy of your friends, loved ones and co-workers. It's very exciting!

Millions of other people have already followed the program and changed their mundane lives!

Thank you!

- {FROM_ROLE} {FROM_LASTNAME}

Start Now at {QUICKLINK_URL}

This is an auto-generated message that a very smart computer created just for you!

----------

Remind me Later at {QUICKLINK_URL}

Unsubscribe at {UNSUBSCRIBE}

Create a file called email.html and put this in it:

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>Test Email</title>
		<meta name="color-scheme" content="light dark">
    	<meta name="supported-color-schemes" content="light dark">
	    <style>
	    	:root {
	    		color-scheme: light dark;
	    		supported-color-schemes: light dark;
	    	}
	    	@media (prefers-color-scheme: dark) {
	    		.lightimage{display: none !important;}
	    		.darkimageWrapper,.darkimage{display: block !important;}
	    		h1,h2,p{color:#ffffff;}
	    		<!--[if !mso]>.mainwrapper{background-color:#000;}<![endif]-->
	    	}
	    	@media (prefers-color-scheme: light) {
	    		h1,h2,p{color:#000000;}
	    	}
	    	.highlight{color:#a1a1a5 !important;}
	    </style>
	</head>
	<body style="margin:0; padding:0;">
		<table class="mainwrapper" width="600" style="margin:0 auto;">
			<tr>
				<td>
					<div lang="en" style="width:600px; font-family:Arial; margin-bottom:25px; padding:20px 0; margin:0 auto;">
						<h1 style="text-align:center; font-size:30px;">Test Email</h1>
						<p style="text-align:center;"><img src="SOMETHING/header2.png" alt="header" width="550" style="width:92%;"></p>
						<div style="width:100%; text-align:center; font-size:24px; margin:35px 0;">
							<a href="{QUICKLINK_URL}" style="display:block; margin:0px 85px; padding:15px 10px; border:2px solid #e5d6ff; color:#7a3fe1; border-radius:30px; text-decoration:none;">See More</a>
						</div>
						<div style="margin:25px 0 0 0 0; color:#000000;">
							<table style="width:100%;" role="presentation" border="0" cellpadding="0" cellspacing="0">
								<tr>
									<td style="width:100px;">
										<img src="SOMETHING/profile.png" width="100" height="auto" class="lightimage" style="display:block; height:auto; padding:0; margin:0; width:100px; height:100px; border-radius:50%;">
 										<div class="darkimageWrapper" style="mso-hide:all; display:none;">
 											<img src="SOMETHING/profile.png" width="100" class="darkimage" style="display:none; padding:0; margin:0; width:100px; height:100px; border-radius:50%;">
 										</div>
									</td>
									<td style="width:500px; padding-left:30px;">
										<h2 style="padding:0; margin:0; font-size:20px; line-height:24px;">{FROM_TITLE} {FROM_FULLNAME}</h2>
										<div class="highlight" style="width:font-size:18px; line-height:24px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">Internet Expert</div>
									</td>
								</tr>
							</table>

							<hr style="margin:25px -5px 10px -5px; border-top:1px solid #a1a1a5;">

							<div style="font-size:23px; padding:0 10px; color:#000000;">
								<p>Hi {TO_FIRSTNAME},</p>

								<p>We're so glad that you're interested in becoming an Internet Guru! Just go to our website and we'll tell you how you can become the envy of your friends, loved ones and co-workers. It's very exciting!</p>

								<p>Millions of other people have already followed the program and changed their mundane lives!</p>

								<p>Thank you!</p>

								<p>- {FROM_TITLE} {FROM_LASTNAME}</p>
							</div>

							<div style="width:100%; text-align:center; font-size:24px; margin:35px 0;">
								<a href="{QUICKLINK_URL}" style="display:block; margin:0px 85px; padding:15px 10px; background-color:#7a3fe1; color:#f5f7f7; border-radius:30px; text-decoration:none;">Start Now!</a>
							</div>

						</div>

						<div style="width:438px; margin:0 49px 0px 49px; padding:0 30px;">
							<p style="font-size:20px; text-align:center; color:#a1a1a5;">This is an auto-generated message that a very smart computer created just for you!</p>
						</div>

						<div style="text-align:center; font-size:24px; margin-top:35px;">
							<a href="{QUICKLINK_URL}" style="display:block; margin:0px 100px; padding:15px 10px; border:2px solid #e5d6ff; color:#7a3fe1; border-radius:30px; text-decoration:none;">Remind me Later</a>
						</div>

						<div style="text-align:center; font-size:20px; margin-top:35px;">
							<a href="{UNSUBSCRIBE}" class="highlight" style="display:block; margin:0px 100px; padding:10px;">Unsubscribe</a>
						</div>
					</div>
				</td>
			</tr>
		</table>
	</body>
</html>

Note on images: for the images in the above HTML they have "SOMETHING" as the domain. You'll have to save the images to a website so that your email client can load them.

Let's Create Our Python Script

Create a file called send_email.py and put this in it:

import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os

# How to allow Google Email Sending
# https://kb.synology.com/en-global/SRM/tutorial/How_to_use_Gmail_SMTP_server_to_send_emails_for_SRM

tags = {
  '{FROM_TITLE}': 'Dr.',
  '{FROM_FULLNAME}': 'Jane Jones',
  '{TO_FIRSTNAME}': 'Steven',
  '{FROM_LASTNAME}': 'Jones',
  '{UNSUBSCRIBE}': 'http://www.google.com',
  '{QUICKLINK_URL}': 'http://www.google.com'
}

def replaceTags(taggedContent):

  for key, value in tags.items():
    taggedContent = taggedContent.replace(key, value)

  return taggedContent

sender_email = "SENDER_EMAIL"
password = "SENDER_EMAIL_PASSWORD"
receiver_email = "TO_EMAIL"

message = MIMEMultipart("alternative")
message["Subject"] = "multipart test"
message["From"] = sender_email
message["To"] = receiver_email

here = os.path.dirname(os.path.abspath(__file__))
final_html = os.path.join(here, 'email.html')
final_txt = os.path.join(here, 'email.txt')

with open(final_html, 'r') as htmlFile:
  html = htmlFile.read()

with open(final_txt, 'r') as txtFile:
  text = txtFile.read()

html = replaceTags(html)
text = replaceTags(text)

# Turn these into plain/html MIMEText objects
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")

# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
message.attach(part1)
message.attach(part2)

# Create secure connection with server and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
    server.login(sender_email, password)
    server.sendmail(
        sender_email, receiver_email, message.as_string()
    )

Modify the Code With Your Info

For sender_email change it to be your newly created Gmail email. password should be your Gmail password. receiver_email will be the email address that you're sending to.

What's Going On Here?

For both the HTML and text version of the email, we're opening the file (email.html and email.txt) and then calling replaceTags() on it. The replaceTags() function looks for tagged items (content between braces such as {FROM_TITLE}) and replaces it with the corresponding value defined in tags dictionary.

Then we define the two MIMEText objects with one being the HTML content and the other being the text. Next, we attach the two parts to the message object that is a MIMEMultipart object.

Finally, we connect to Gmail and send an email with the predefined info.

So What Does Our Email Look Like?

Our HTML email will look something like this:

The text version will look like this: