Skip to content

Instantly share code, notes, and snippets.

@David-Guillot
Last active September 24, 2019 07:54
Show Gist options
  • Save David-Guillot/709f3dbc99168f1006e3d6c7159d3e49 to your computer and use it in GitHub Desktop.
Save David-Guillot/709f3dbc99168f1006e3d6c7159d3e49 to your computer and use it in GitHub Desktop.
Python script to send HTML email from command line
# 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