I'm creating some emails in Python and I'd like to have HTML, text, and an attachment. My code is 'working', though its outputs are shown by Outlook as EITHER HTML or text, while showing the other 'part' (email or txt) as an attachment. I'd like to have the robust-ness of both email and text versions along with the file attachment.
Is there a fundamental limitation or am I making a mistake?
#!/usr/bin/env python3
import smtplib,email,email.encoders,email.mime.text,email.mime.base
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# me == my email address
# you == recipient's email address
me = "me#me.com"
you = "you#you.com"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('mixed')
msg['Subject'] = "msg"
msg['From'] = me
msg['To'] = you
# Create the body of the message (a plain-text and an HTML version).
text = "Hi\nThis is text-only"
html = """\
<html> This is email</html>
"""
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
#attach an excel file:
fp = open('excelfile.xlsx', 'rb')
file1=email.mime.base.MIMEBase('application','vnd.ms-excel')
file1.set_payload(fp.read())
fp.close()
email.encoders.encode_base64(file1)
file1.add_header('Content-Disposition','attachment;filename=anExcelFile.xlsx')
# 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(part2)
msg.attach(part1)
msg.attach(file1)
composed = msg.as_string()
fp = open('msgtest.eml', 'w')
fp.write(composed)
fp.close()
I found this has in fact been answered. Strange how the search feature is less effective than the 'related' boxes.
Sending Multipart html emails which contain embedded images
Related
i am new to python,and below is the code which is suppose to send mail to multiple receipent but only dipeshyog94#gmail.com is getting a mail. milanthapa898#gmail.com which is second on To and alexlee94#gmail.com which is on cc is no getting the mail
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import smtplib
owner_emp_id_email = "dipeshyogi94#gmail.com,milanthapa989#gmail.com"
mymail='milanthapa898#gmail.com'
msg = MIMEMultipart()
msg['From'] = mymail
msg['To'] = owner_emp_id_email
cc_mail = "alexlee94#gmail.com"
msg['Cc'] = cc_mail
print('####44444444444444########\n')
print(owner_emp_id_email)
msg['Subject'] = 'Automated Test Mail with python'
a = 'Milan Thapa'
#body = 'Dear '+spoc_name+',\n\nYou have created new job with below Details:\n\nProject ID : '+project_ID+'\n\nProject Name : '+ibu_name+'\n\nJob Description : ' +job_description +'\n\nThanks and Regards,\n\nMilan Thapa'
html = """\
<html>
<head></head>
<body>
<p>'Dear <b>{}<b>
</p>
</body>
</html>
""".format(a)
msg.attach(MIMEText(html,'html'))
text = msg.as_string()
try:
server = smtplib.SMTP('smtp.gmail.com:587')
except:
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
server.ehlo()
server.login(mymail,'password')
server.sendmail(mymail,owner_emp_id_email,text)
server.quit()
i am stuck in this couldn't send the mail to multiple users.
any help will be greatly appreciated!
thanks in advance
The information in the headers doesn't control where the message actually goes. The second argument to sendmail is the only place where this is controlled. This value should be a list, not a comma-separated string.
owner_emp_id_email = "dipeshyogi94#gmail.com,milanthapa989#gmail.com"
env_rcpts = owner_emp_id_email.split(",")
# ...
cc_mail = "alexlee94#gmail.com"
env_rcpts.append(cc_mail)
# ...
server.sendmail(mymail,env_rcpts,text)
You'll notice that you could also add addresses which are neither in To: or Cc: (or a number of other headers which serve the same purpose) to effectively implement Bcc:
Maybe also look at send_message which saves you from having to separately convert your message to a string you can pass to sendmail.
msg['To'] = owner_emp_id_email
Here owner_emp_id_email is a string.
Make it a list of email ids. Then it would work.
to_ids = owner_emp_id_email.split(',')
msg['To'] = to_ids
>>> help(smtplib)
to_addrs: A list of addresses to send this mail to. A bare string will be treated as a list with 1 address.
You need to convert your CSV string to a list like mentioned in the the other answer. With this answer I just wanted to demonstrate how can we use the python's amazing help function when stuck.
I've got a script that sends emails with html content in them.. works as expected...
I'm having trouble sending an attachment with the email.
The attachment is an html file stored in the active directory of the script... "test.html"
How do I attach the html file to the email? I've tried snippets from various other posts I've found relating to this, but each returned the same output of "no such file or directory".
code as follows:
import smtplib
import os
import email.encoders
import email.mime.text
import email.mime.base
import mimetools
import base64
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# me == Outgoing email address
# you == Recipient's email address
me = "secret"
you = "secret"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "TEST"
msg['From'] = me
msg['To'] = you
emailMsg = email.MIMEMultipart.MIMEMultipart('alternative')
# Create the body of the message (a plain-text and an HTML version).
html = """\
<html>
<head></head>
<body>test</p>
</body>
</html>"""
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
filename = "C:/CHRIS/ServerStatus/Oceaneering_Server_Status.html"
f = file(filename)
attachment = MIMEText(f.read(), _subtype='html')
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
# 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)
msg.attach(attachment)
# Send the message via local SMTP server.
mail = smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
# mail.login(username, password) to Outgoing email account
mail.login('secret', 'secret')
mail.sendmail(me, you, msg.as_string())
mail.quit()
i've updated my code in hopes to get this question back on topic... i've made a little progress with the help of Dirk and this link:
Attach a txt file in Python smtplib...
I've been able to physically send an attachment now, but the attachment is still coming through as a text type of file of sort and does not open as the original html file does.
So to reword my question... What is the corrective action for changing the MIME type of this code to correctly attach an .html file to an html based email?
The relative path and directory of my py script and the html file needed to be sent is as follows:
C:\CHRIS\ServerStatus\
This is the output i'm receiving with the code I have:
This is the way the html doc looks outside of the email script (The way it's supposed to look):
I would encourage you to use a library rather than deal with the -rather unpythonic- built-in mail modules, such as the highly recommended envelopes:
https://tomekwojcik.github.io/envelopes/index.html
install with:
pip install envelopes
Python code:
import os
from envelopes import Envelope
filename = "C:/CHRIS/ServerStatus/Oceaneering_Server_Status.html"
envelope = Envelope(
from_addr=(me),
to_addr=(you),
subject=u'Test',
text_body=u'Plain text version',
html_body=html
)
envelope.add_attachment(filename)
envelope.send('smtp.gmail.com', login='secret', password='secret', tls=True)
Email With Mandrill to multiple emailId but it only deliver to id which is first in the list to rest it does not send.I want to send mail to multiple users using mandrill API
here is my code :
class mandrillClass:
def mandrillMail(self,param):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
msg = MIMEMultipart('alternative')
msg['Subject'] = param['subject']
msg['From'] = param['from']
msg['To'] = param['to']
html = param['message']
print html
text = 'dsdsdsdds'
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
username = 'xyz#gmail.com'
password = 'uiyhiuyuiyhihuohohio'
msg.attach(part1)
msg.attach(part2)
s = smtplib.SMTP('smtp.mandrillapp.com', 587)
s.login(username, password)
s.sendmail(msg['From'], msg['To'], msg.as_string())
s.quit()
and here i am calling the function
from API_Program import mandrillClass
msgDic = {}
msgDic['subject'] = "testing"
msgDic['from'] = "xyz#gmail.com"
#msgDic['to'] = 'abc#gmail.com','example#gmail.com'
COMMASPACE = ', '
family = ['abc#gmail.com','example#gmail.com']
msgDic['to'] = COMMASPACE.join(family)
msgDic['message'] = "<div>soddjags</div>"
mailObj = mandrillClass()
mailObj.mandrillMail(msgDic)
Since you're using smtplib, you'll want to review the documentation for that SMTP library on how you specify multiple recipients. SMTP libraries vary in how they handle multiple recipients. Looks like this StackOverflow post has information about passing multiple recipients with smtplib: How to send email to multiple recipients using python smtplib?
You need a list instead of just strings, so something like this:
msgDic['to'] = ['abc#gmail.com','example#gmail.com']
So, your family variable is declared properly, and you shouldn't need to do anything to that.
Try:
msgDic['to'] = [{"email":fam} for fam in family]
From the docs it looks like they expect this structure:
msgDic['to'] = [ {"email":"a#b.c", "name":"a.b", "type":"to"},
{"email":"x#y.z", "name":"x.z", "type":"cc"}
]
where you can omit name and type.
I am using Python 2.7 and trying to send an email using smtplib/MIMEMultipart. I want to send an email that contains multiple pieces e.g., a text message and an html message. I do NOT want them to be alternatives. I want to it to display the text message (inline) follow by the html (inline)
In the future, I would also like to include images. So, the message will contain text, html, and images all inline.
Here is what I have currently, which produces a text message and then the html as an attachment
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
s = smtplib.SMTP('localhost')
#this part works
msg = MIMEMultipart('mixed')
msg['Subject'] = subject
msg['From'] = from
msg['To'] = to
html_str = """<html><head></head><body><p>Test</p></body></html>"""
#this shows up with "This is my text" inline and the html as an attachment
text = MIMEText("This is my text", 'plain')
html = MIMEText(html_str, 'html')
msg.attach(text)
msg.attach(html)
s.sendmail(fromEmail, toEmail, msg.as_string())
s.quit()
How do I add multiple inline pieces to an email?
Thank you for your help
I wasn't able to do this exactly as I wanted, but I found a work around.
I ended up just making the entire email an html email. For every piece that I needed to add, I would just add html code. For example, here is how I ended up adding an image
html_list.append('<img src="cid:image.png">')
img = MIMEImage(my_data)
img.add_header('Content-ID', '<image.png>')
msg.attach(img)
And if I wanted to add text, I could add it as a header (e.g. <h3>My Text</h3>) or as any other html element.
I'm trying to send an HTML email using smtplib. But I need the HTML content to have a table that is populated using values from a dictionary. I did look at the examples on the Python website. But it doesn't explain how to embed Python code within HTML. Any solutions/suggestions?
I also looked at this question. Can I just format it this way?
.format(dict_name)
From your link:
Here’s an example of how to create an HTML message with an alternative
plain text version: 2
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>
"""
and the sending section of it:
# 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()
Edit 2022: for new comers, please advise with python’s latest stable release docs.
What you need is a template engine. That is, you need a python library that reads a file written in both HTML and code, interprets the code written within the HTML file (e.g. code that retrieves values from a dictionary), and then produces an HTML file for you.
The python wiki seems to have some suggestions