I am learning how to use Python for automating emails, and am facing issues in creating a "clean" email.
Problem: I have a Google doc which has a certain text, followed by an image, followed by some text. I wish to use this as the content of an email, which I wish to send using Python
Approach: Based on what I read on SO and blogs, I used MIMEMultipart and broke my original doc into 3 parts: text, image, text and I downloaded the html versions for both the text files. Thereafter, I used the following code:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from string import Template
me = "myemail#gmail.com"
you = "youremail#gmail.com"
msg = MIMEMultipart()
msg['From'] = me
msg['To'] = you
msg['Subject'] = 'This is a test'
html1 = open('test_doc_part1.html')
part1 = MIMEText(html1.read(), 'html')
msg.attach(part1)
html1.close()
image_text = MIMEText('<img src="cid:image1">', 'html')
msg.attach(image_text)
fp = open('test_image.jpg', 'rb')
image = MIMEImage(fp.read())
fp.close()
image.add_header('Content-ID', '<image1>') # Define the image's ID as referenced in the HTML body above
msg.attach(image)
html2 = open('test_doc_part2.html')
part2 = MIMEText(html2.read(), 'html')
msg.attach(part2)
html2.close()
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(me, "password")
text = msg.as_string()
# Do text substitutions here
server.sendmail(from_addr= me, to_addrs= you, msg=text)
server.quit()
Issue: Depending on the text sources, the text of my email is either hidden under the image, or all/some of it is underlined/garbled. I'm using gmail and viewing this email in Google Chrome. The original content of the received email can be viewed here. Can someone point out where I'm incorrect?
trying to send email through python. Can get it to send email with correct text content in the body but it's printing the the actual variable name "New Companies" instead of it's content. here's the code and the resulting email.
(not sure why the html tags aren't showing up in my code below, but I used html and body tags before and after the email content)
Any and all help is appreciated.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
EMAIL_SERVER = 'blahblah'
EMAIL_PORT = 25
f = open('diff.txt', 'r')
NEW_COMPANIES = f.read()
EMAIL_FROM = 'blabal'
RECIPIENT_LIST = ['blahblah']
msg = MIMEMultipart()
msg['From'] = EMAIL_FROM
msg['To'] = ", ".join(RECIPIENT_LIST)
msg['Subject'] = 'North Carolina New Business Registration'
body = '''<html>
<body>
New Business Names:<br><br>
body.format('NEW_COMPANIES')
<br><br>
Affiliate: r2thek
<br><br>
Website Link:
https://www.sosnc.gov/online_services/search/by_title/_Business_Registration
</body>
</html>'''
body.format('NEW_COMPANIES')
msg.attach(MIMEText(body, 'html'))
smtpserver = smtplib.SMTP(EMAIL_SERVER, EMAIL_PORT)
smtpserver.sendmail(EMAIL_FROM, RECIPIENT_LIST, msg.as_string())
smtpserver.quit()
Email Result:
New Business Names:
{NEW_COMPANIES}
Affiliate: r2thek
Website Link: https://www.sosnc.gov/online_services/search/by_title/_Business_Registration
It doesn't look like you've passed any variables to format the string, you'll need to do
body.format(variable1, variable2, etc)
In your case I think it's just the one variable, so wherever you stored what NEW_COMPANIES should be needs to be used as the argument for str.format()
After replacing headers like from,to,sub i am able to forward mail to another email address.
But how can I forward mail by adding more attachments and more text or html content.
As we see in the gmail, new contents should be displayed before the forwrded message content. Any idea on how could we achieve this?
Forwarded mail can be multipart or not.
But since we add new content it will be multipart
I have tried the code below
# open IMAP connection and fetch message with id msgid
# store message data in email_data
client = imaplib.IMAP4_SSL(imap_host,993)
client.login(user, passwd)
client.select('INBOX')
result, data = client.uid('fetch', msg_id, "(RFC822)")
client.close()
client.logout()
# create a Message instance from the email data
message = email.message_from_string(data[0][1])
# replace headers (could do other processing here)
message.replace_header("From", from_addr)
message.replace_header("To", to_addr)
message.replace_header("Subject", "Fwd:"+ message["Subject"].replace("FWD: ", "").replace("Fwd: ","" ))
# open authenticated SMTP connection and send message with
# specified envelope from and to addresses
smtp = smtplib.SMTP_SSL(smtp_host, smtp_port)
smtp.login(user, passwd)
smtp.sendmail(from_addr, to_addr, message.as_string())
smtp.quit()
I was able to achieve this using the email package, attaching the original email as a part:
from email.message import Message
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.message import MIMEMessage
from email import message_from_bytes
raw_email = get_raw_email() # get the original email from wherever
original_email = message_from_bytes(raw_email)
part1 = MIMEText("This is new content")
part2 = MIMEMessage(original_email)
new_email = MIMEMultipart()
new_email['Subject'] = "My subject"
new_email['From'] = 'abc#xyz.com'
new_email['To'] = '123#456.com'
new_email.attach(part1)
new_email.attach(part2)
How to send HTML content in email using Python? I can send simple texts.
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 = "my#email.com"
you = "your#email.com"
# 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://www.python.org"
html = """\
<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the link 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()
Here 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 = "my#email.com"
you = "your#email.com"
# 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://www.python.org"
html = """\
<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the link 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()
You might try using my mailer module.
from mailer import Mailer
from mailer import Message
message = Message(From="me#example.com",
To="you#example.com")
message.Subject = "An HTML Email"
message.Html = """<p>Hi!<br>
How are you?<br>
Here is the link you wanted.</p>"""
sender = Mailer('smtp.example.com')
sender.send(message)
Here 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'] = 'sender#test.com'
msg['To'] = 'recipient#test.com'
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()
for python3, improve #taltman 's answer:
use email.message.EmailMessage instead of email.message.Message to construct email.
use email.set_content func, assign subtype='html' argument. instead of low level func set_payload and add header manually.
use SMTP.send_message func instead of SMTP.sendmail func to send email.
use with block to auto close connection.
from email.message import EmailMessage
from smtplib import SMTP
# construct email
email = EmailMessage()
email['Subject'] = 'foo'
email['From'] = 'sender#test.com'
email['To'] = 'recipient#test.com'
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)
Here'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 <sender#host.com>')
server = smtplib.SMTP("smtp_server_address","smtp_port")
server.login('username', 'password')
server.sendmail('sender#host.com', 'target#otherhost.com', message)
server.quit()
Actually, 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("me#example.com", "mypassword")
html_msg = """<p>Hi!<br>
How are you?<br>
Here is the link you wanted.</p>"""
yag.send("to#example.com", "the subject", html_msg)
For installation instructions and many more great features, have a look at the github.
Here's a working example to send plain text and HTML emails from Python using smtplib along with the CC and BCC options.
https://varunver.wordpress.com/2017/01/26/python-smtplib-send-plaintext-and-html-emails/
#!/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 = "from_email#domain.com"
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': 'to_email#domain.com',
'email_cc': 'cc_email#domain.com',
'email_bcc': 'bcc_email#domain.com',
'email_subject': 'Test message from python library',
'email_body': '<h1>Hello World</h1>'
}
for t in ['plain', 'html']:
send_mail(params, t)
Here 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 <do-not-reply#acme.com>',
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()
here 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 = "....#gmail.com"
TO = "another....#gmail.com"
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)
```
In case you want something simpler:
from redmail import EmailSender
email = EmailSender(host="smtp.myhost.com", port=1)
email.send(
subject="Example email",
sender="me#example.com",
receivers=["you#example.com"],
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:
Attachments
Templating (with Jinja)
Embedded images
Prettified tables
Send as cc or bcc
Gmail preconfigured
Documentation: https://red-mail.readthedocs.io/en/latest/index.html
Source code: https://github.com/Miksus/red-mail
i'm new with python..
Actually, i'm trying to send featured email with python: html body, text alternative body, and attachment.
So, i've found this tutorial and adapted it with the gmail authentication (tutorial found here)
The code i have atm, is that:
def createhtmlmail (html, text, subject):
"""Create a mime-message that will render HTML in popular
MUAs, text in better ones"""
import MimeWriter
import mimetools
import cStringIO
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
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("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()
return msg
import smtplib
f = open("/path/to/html/version.html", 'r')
html = f.read()
f.close()
f = open("/path/to/txt/version.txt", 'r')
text = f.read()
subject = "Prova email html da python, con allegato!"
message = createhtmlmail(html, text, subject)
gmail_user = "thegmailaccount#gmail.com"
gmail_pwd = "thegmailpassword"
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(gmail_user, gmail_pwd)
server.sendmail(gmail_user, "example#example.com", message)
server.close()
and that works.. now only miss the attachment..
And i am not able to add the attachment (from this post)
So, why there is not a python class like phpMailer for php?
Is it because, for a medium-able python programmer sending a html email with attachment and alt text body is so easy that a class is not needed?
Or is because i just didn't find it?
If i'll be able to wrote a class like that, when i'll be enough good with python, would that be useful for someone?
If you can excuse some blatant self promotion, I wrote a mailer module that makes sending email with Python fairly simple. No dependencies other than the Python smtplib and email libraries.
Here's a simple example for sending an email with an attachment:
from mailer import Mailer
from mailer import Message
message = Message(From="me#example.com",
To=["you#example.com", "him#example.com"])
message.Subject = "Kitty with dynamite"
message.Body = """Kitty go boom!"""
message.attach("kitty.jpg")
sender = Mailer('smtp.example.com')
sender.login("username", "password")
sender.send(message)
Edit: Here's an example of sending an HTML email with alternate text. :)
from mailer import Mailer
from mailer import Message
message = Message(From="me#example.com",
To="you#example.com",
charset="utf-8")
message.Subject = "An HTML Email"
message.Html = """This email uses <strong>HTML</strong>!"""
message.Body = """This is alternate text."""
sender = Mailer('smtp.example.com')
sender.send(message)
Edit 2: Thanks to one of the comments, I've added a new version of mailer to pypi that lets you specify the port in the Mailer class.
Django includes the class you need in core, docs here
from django.core.mail import EmailMultiAlternatives
subject, from_email, to = 'hello', 'from#example.com', 'to#example.com'
text_content = 'This is an important message.'
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.attach_file('/path/to/file.jpg')
msg.send()
In my settings I have:
#GMAIL STUFF
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'name#gmail.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
Just want to point to Lamson Project which was what I was looking for when I found this thread. I did some more searching and found it. It's:
Lamson's goal is to put an end to the hell that is "e-mail application development". Rather than stay stuck in the 1970s, Lamson adopts modern web application framework design and uses a proven scripting language (Python).
It integrates nicely with Django. But it's more made for email based applications. It looks like pure love though.
Maybe you can try with turbomail python-turbomail.org
It's more easy and useful :)
import turbomail
# ...
message = turbomail.Message("from#example.com", "to#example.com", subject)
message.plain = "Hello world!"
turbomail.enqueue(message)
I recommend reading the SMTP rfc. A google search shows that this can easily be done by using the MimeMultipart class which you are importing but never using. Here are some examples on Python's documentation site.