How to send HTML content in email using Python? I can send simple texts.
212 Answers
From Python v2.7.14 documentation - 18.1.11. email: Examples:
Here’s an example of how to create an HTML message with an alternative plain text version:
#! /usr/bin/python import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # me == my email address # you == recipient's email address me = "" you = "" # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart('alternative') msg['Subject'] = "Link" msg['From'] = me msg['To'] = you # Create the body of the message (a plain-text and an HTML version). text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://" html = """\ <html> <head></head> <body> <p>Hi!<br> How are you?<br> Here is the <a href="">link</a> you wanted. </p> </body> </html> """ # Record the MIME types of both parts - text/plain and text/html. part1 = MIMEText(text, 'plain') part2 = MIMEText(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) # Send the message via local SMTP server. s = smtplib.SMTP('localhost') # sendmail function takes 3 arguments: sender's address, recipient's address # and message to send - here it is sent as one string. s.sendmail(me, you, msg.as_string()) s.quit() 12Here is a Gmail implementation of the accepted answer:
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # me == my email address # you == recipient's email address me = "" you = "" # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart('alternative') msg['Subject'] = "Link" msg['From'] = me msg['To'] = you # Create the body of the message (a plain-text and an HTML version). text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttp://" html = """\ <html> <head></head> <body> <p>Hi!<br> How are you?<br> Here is the <a href="">link</a> you wanted. </p> </body> </html> """ # Record the MIME types of both parts - text/plain and text/html. part1 = MIMEText(text, 'plain') part2 = MIMEText(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) # Send the message via local SMTP server. mail = smtplib.SMTP('smtp.gmail.com', 587) mail.ehlo() mail.starttls() mail.login('userName', 'password') mail.sendmail(me, you, msg.as_string()) mail.quit() 5You might try using my mailer module.
from mailer import Mailer from mailer import Message message = Message(From="", To="") message.Subject = "An HTML Email" message.Html = """<p>Hi!<br> How are you?<br> Here is the <a href="">link</a> you wanted.</p>""" sender = Mailer('smtp.example.com') sender.send(message) 5Here is a simple way to send an HTML email, just by specifying the Content-Type header as 'text/html':
import email.message import smtplib msg = email.message.Message() msg['Subject'] = 'foo' msg['From'] = '' msg['To'] = '' msg.add_header('Content-Type','text/html') msg.set_payload('Body of <b>message</b>') # Send the message via local SMTP server. s = smtplib.SMTP('localhost') s.starttls() s.login(email_login, email_passwd) s.sendmail(msg['From'], [msg['To']], msg.as_string()) s.quit() 2for python3, improve @taltman 's answer:
- use
email.message.EmailMessageinstead ofemail.message.Messageto construct email. - use
email.set_contentfunc, assignsubtype='html'argument. instead of low level funcset_payloadand add header manually. - use
SMTP.send_messagefunc instead ofSMTP.sendmailfunc to send email. - use
withblock to auto close connection.
from email.message import EmailMessage from smtplib import SMTP # construct email email = EmailMessage() email['Subject'] = 'foo' email['From'] = '' email['To'] = '' email.set_content('<font color="red">red color text</font>', subtype='html') # Send the message via local SMTP server. with smtplib.SMTP('localhost') as s: s.login('foo_user', 'bar_password') s.send_message(email) 2Here's sample code. This is inspired from code found on the Python Cookbook site (can't find the exact link)
def createhtmlmail (html, text, subject, fromEmail): """Create a mime-message that will render HTML in popular MUAs, text in better ones""" import MimeWriter import mimetools import cStringIO out = cStringIO.StringIO() # output buffer for our message htmlin = cStringIO.StringIO(html) txtin = cStringIO.StringIO(text) writer = MimeWriter.MimeWriter(out) # # set up some basic headers... we put subject here # because smtplib.sendmail expects it to be in the # message body # writer.addheader("From", fromEmail) writer.addheader("Subject", subject) writer.addheader("MIME-Version", "1.0") # # start the multipart section of the message # multipart/alternative seems to work better # on some MUAs than multipart/mixed # writer.startmultipartbody("alternative") writer.flushheaders() # # the plain text section # subpart = writer.nextpart() subpart.addheader("Content-Transfer-Encoding", "quoted-printable") pout = subpart.startbody("text/plain", [("charset", 'us-ascii')]) mimetools.encode(txtin, pout, 'quoted-printable') txtin.close() # # start the html subpart of the message # subpart = writer.nextpart() subpart.addheader("Content-Transfer-Encoding", "quoted-printable") # # returns us a file-ish object we can write to # pout = subpart.startbody("text/html", [("charset", 'us-ascii')]) mimetools.encode(htmlin, pout, 'quoted-printable') htmlin.close() # # Now that we're done, close our writer and # return the message body # writer.lastpart() msg = out.getvalue() out.close() print msg return msg if __name__=="__main__": import smtplib html = 'html version' text = 'TEST VERSION' subject = "BACKUP REPORT" message = createhtmlmail(html, text, subject, 'From Host <>') server = smtplib.SMTP("smtp_server_address","smtp_port") server.login('username', 'password') server.sendmail('', '', message) server.quit() 2Actually, yagmail took a bit different approach.
It will by default send HTML, with automatic fallback for incapable email-readers. It is not the 17th century anymore.
Of course, it can be overridden, but here goes:
import yagmail yag = yagmail.SMTP("", "mypassword") html_msg = """<p>Hi!<br> How are you?<br> Here is the <a href="">link</a> you wanted.</p>""" yag.send("", "the subject", html_msg) For installation instructions and many more great features, have a look at the github.
1Here's a working example to send plain text and HTML emails from Python using smtplib along with the CC and BCC options.
#!/usr/bin/env python import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText def send_mail(params, type_): email_subject = params['email_subject'] email_from = "" email_to = params['email_to'] email_cc = params.get('email_cc') email_bcc = params.get('email_bcc') email_body = params['email_body'] msg = MIMEMultipart('alternative') msg['To'] = email_to msg['CC'] = email_cc msg['Subject'] = email_subject mt_html = MIMEText(email_body, type_) msg.attach(mt_html) server = smtplib.SMTP('YOUR_MAIL_SERVER.DOMAIN.COM') server.set_debuglevel(1) toaddrs = [email_to] + [email_cc] + [email_bcc] server.sendmail(email_from, toaddrs, msg.as_string()) server.quit() # Calling the mailer functions params = { 'email_to': '', 'email_cc': '', 'email_bcc': '', 'email_subject': 'Test message from python library', 'email_body': '<h1>Hello World</h1>' } for t in ['plain', 'html']: send_mail(params, t) 1Here is my answer for AWS using boto3
subject = "Hello" html = "<b>Hello Consumer</b>" client = boto3.client('ses', region_name='us-east-1', aws_access_key_id="your_key", aws_secret_access_key="your_secret") client.send_email( Source='ACME <>', Destination={'ToAddresses': [email]}, Message={ 'Subject': {'Data': subject}, 'Body': { 'Html': {'Data': html} } } Simplest solution for sending email from Organizational account in Office 365:
from O365 import Message html_template = """ <html> <head> <title></title> </head> <body> {} </body> </html> """ final_html_data = html_template.format(df.to_html(index=False)) o365_auth = ('sender_username@company_email.com','Password') m = Message(auth=o365_auth) m.setRecipients('receiver_username@company_email.com') m.setSubject('Weekly report') m.setBodyHTML(final_html_data) m.sendMessage() 1here df is a dataframe converted to html Table, which is being injected to html_template
I may be late in providing an answer here, but the Question asked a way to send HTML emails. Using a dedicated module like "email" is okay, but we can achieve the same results without using any new module. It all boils down to the Gmail Protocol.
Below is my simple sample code for sending HTML mail only by using "smtplib" and nothing else.
import smtplib FROM = "" TO = "" SUBJECT= "Subject" PWD = "thesecretkey" TEXT=""" <h1>Hello</h1> """ #Your Message (Even Supports HTML Directly) message = f"Subject: {SUBJECT}\nFrom: {FROM}\nTo: {TO}\nContent-Type: text/html\n\n{TEXT}" #This is where the stuff happens try: server=smtplib.SMTP("smtp.gmail.com",587) server.ehlo() server.starttls() server.login(FROM,PWD) server.sendmail(FROM,TO,message) server.close() print("Successfully sent the mail.") except Exception as e: print("Failed to send the mail..", e) 1In case you want something simpler:
from redmail import EmailSender email = EmailSender(host="smtp.myhost.com", port=1) email.send( subject="Example email", sender="", receivers=[""], html="<h1>Hi, this is HTML body</h1>" ) Pip install Red Mail from PyPI:
pip install redmail Red Mail has most likely all you need from sending emails and it has a lot of features including: