Instantly share code, notes, and snippets.

Embed
What would you like to do?
Python script to send HTML email from command line
<!--
This is a sample email taken from https://developers.google.com/gmail/schemas/apps-script-tutorial
and used to test the GMail actions support.
-->
<html>
<head>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"description": "Check this out",
"action": {
"@type": "ViewAction",
"url": "https://www.youtube.com/watch?v=eH8KwfdkSqU"
}
}
</script>
</head>
<body>
<p>
This a test for a Go-To action in Gmail.
</p>
</body>
</html>
# Simple script used to send an HTML file as an HTML formatted email,
# using Gmail's 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 Gmail account in order to access the SMTP service
if args.username is None:
args.username = raw_input('Gmail username: ')
print_args(args)
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 Google's 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 Gmail authenticating account"
"\n$ send_html_email.py fred@example.com test_file.html -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'"
"\n"
"\n5. Turn on SMTP debugging"
"\n$ send_html_email.py fred@example.com test_file.html -d"
)
epilog = "NB This script requires a Gmail account."
parser = argparse.ArgumentParser(description=usage, epilog=epilog,
# 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('-u', '--username',
help=('A valid Gmail user account (used to authenticate against Google\'s SMTP service). '
'If this argument is not supplied, the user will be prompted to type it 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)"
)
parser.add_argument('-d', '--debug', action='store_true',
help=('Use this option to turn on DEBUG for the SMTP server interaction.')
)
return parser
def print_args(args):
"""Print out the input arguments."""
print 'Sending test email to: %s' % args.recipients
print 'Sending test email from: %s' % args.sender
print 'Using Gmail account: %s' % args.username
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("smtp.gmail.com", 587)
smtpserver.set_debuglevel(args.debug)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
# getpass() prompts the user for their password (so it never appears in plain text)
smtpserver.login(args.username, getpass())
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
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()
@amynbe

This comment has been minimized.

amynbe commented Aug 28, 2015

Thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment