Last active
September 24, 2019 07:54
-
-
Save David-Guillot/709f3dbc99168f1006e3d6c7159d3e49 to your computer and use it in GitHub Desktop.
Python script to send HTML email from command line
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Simple script used to send an HTML file as an HTML formatted email, | |
# using any SMTP service. Used for testing HTML emails. | |
# The core message-sending code is taken from the docs: | |
# http://docs.python.org/2/library/email-examples.html | |
# The code for correctly authenticating against Gmail comes from: | |
# http://kutuma.blogspot.co.uk/2007/08/sending-emails-via-gmail-with-python.html | |
import smtplib | |
import argparse | |
from getpass import getpass | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
def parse_args(): | |
""" | |
Parse script input arguments. | |
Returns the parsed args, having validated that the input | |
file can be read, and that there is a valid Username. | |
""" | |
parser = get_parser() | |
args = parser.parse_args() | |
# artificially adding this to args, so that | |
# it can be passed around easily | |
args.html = open(args.html_filename).read() | |
# we have to have a valid SMTP host | |
if not args.smtp_host: | |
args.smtp_host = input('SMTP host: ') | |
if not args.username: | |
args.username = input('SMTP username: ') | |
if not args.password_file: | |
args.password = getpass('SMTP password: ') | |
else: | |
f = open(args.password_file, 'r') | |
args.password = f.read().strip() | |
return args | |
def get_parser(): | |
""" Return the parser used to interpret the script arguments.""" | |
usage = ( | |
"Script to send an HTML file as an HTML email, using any SMTP server." | |
"\nExamples:" | |
"\n1. Send the contents of test_file.html to fred" | |
"\n$ send_html_email.py fred@example.com test_file.html" | |
"\n" | |
"\n2. Send the mail to both fred and bob" | |
"\n$ send_html_email.py fred@example.com bob@example.com test_file.html" | |
"\n" | |
"\n3. Use fred123@gmail.com as the SMTP authenticating account" | |
"\n$ send_html_email.py fred@example.com test_file.html -h smtp.gmail.com -u fred123@gmail.com" | |
"\n" | |
"\n4. Override the default test mail subject line" | |
"\n$ send_html_email.py fred@example.com test_file.html -t 'Test email'" | |
) | |
parser = argparse.ArgumentParser(description=usage, | |
# maintains raw formatting, instead of wrapping lines automatically | |
formatter_class=argparse.RawDescriptionHelpFormatter | |
) | |
parser.add_argument('recipients', help='The recipient email addresses (space delimited)', nargs='+') | |
parser.add_argument('html_filename', help='The HTML file to use as the email body content') | |
parser.add_argument('-s', '--sender', | |
help='The sender email address (defaults to <do-not-reply@example.com>)', | |
default='do-not-reply@example.com' | |
) | |
parser.add_argument('--smtp-host', | |
help=('A valid SMTP host' | |
'If this argument is not supplied, the user will be prompted to type it in.') | |
) | |
parser.add_argument('-u', '--username', | |
help=('A valid SMTP username' | |
'If this argument is not supplied, the user will be prompted to type it in.') | |
) | |
parser.add_argument('-f', '--password-file', | |
help=('The path to a file containing the SMTP password' | |
'If this argument is not supplied, the user will be prompted to type the SMTP password in.') | |
) | |
parser.add_argument('-t', '--title', | |
help='The test email subject line (defaults to "Test email")', | |
default="Test email" | |
) | |
parser.add_argument('-p', '--plain', | |
help=('The test email plain text content. This script is designed primarily for the ' | |
'testing of HTML emails, so this text is really just a placeholder, for completeness. ' | |
'The default is "This is a test email (plain text)."'), | |
default="This is a test email (plain text)" | |
) | |
return parser | |
def create_message(args): | |
""" Create the email message container from the input args.""" | |
# Create message container - the correct MIME type is multipart/alternative. | |
msg = MIMEMultipart('alternative') | |
msg['Subject'] = args.title | |
msg['From'] = args.sender | |
msg['To'] = ','.join(args.recipients) | |
# Record the MIME types of both parts - text/plain and text/html. | |
part1 = MIMEText(args.plain, 'plain') | |
part2 = MIMEText(args.html, 'html') | |
# Attach parts into message container. | |
# According to RFC 2046, the last part of a multipart message, in this case | |
# the HTML message, is best and preferred. | |
msg.attach(part1) | |
msg.attach(part2) | |
return msg | |
def main(): | |
args = parse_args() | |
msg = create_message(args) | |
try: | |
smtpserver = smtplib.SMTP(args.smtp_host, 587) | |
smtpserver.ehlo() | |
smtpserver.starttls() | |
smtpserver.ehlo() | |
smtpserver.login(args.username, args.password) | |
smtpserver.sendmail(args.sender, args.recipients, msg.as_string()) | |
print("Message sent to '%s'." % args.recipients) | |
smtpserver.quit() | |
except smtplib.SMTPAuthenticationError as e: | |
print("Unable to send message: %s" % e) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment