Is there a way to send HTML-formatted email using Python's win32com.client (which utilizes Outlook 2007/2010). The format I'm using now looks like this:
import win32com.client
olMailItem = 0x0
obj = win32com.client.Dispatch("Outlook.Application")
newMail = obj.CreateItem(olMailItem)
newMail.Subject = "the subject"
newMail.Body = "body text"
newMail.To = "recipient#example.com"
attachment1 = "c:\\mypic.jpg"
newMail.Attachments.Add(attachment1)
newMail.Send()
This will send an email using Outlook, sent from the currently authenticated user, to the specified recipient, with a subject, content, and attached image.
I want to be able to send an inline image, which can be achieved using an "Embedded" attachment, or simply to link to and image using HTML, or embed an image using HTML and a Base64-encoded image.
HTML is my preferred approach, but any HTML I add to the body is formatted and encoded as plain text (e.g. < becomes <). Is there a way to tell Outlook the body content is HTML and should be parsed as such?
This is the way to make the body in html format
newMail.HTMLBody = htmltext
Related
I am trying to send an email using Python smtplib.
My objective is to include the below info in email
Attachment file #works fine
Paste the contents of a table in message body #works fine
Write a few lines about the table (as text) in message body # not works. instead stores as an attachment
So, I tried the below code
message = MIMEMultipart()
message['Subject'] = 'For your review - files'
message['From'] = 'user2#org.com'
message['To'] = 'user1#org.com'
# code to paste table contents in outlook message window - works fine
body_content = output # this has the pretty table - html table
message.attach(MIMEText(body_content, "html"))
# code to paste the written text in outlook message window - not works. instead of writing the text in outlook body,it stores as an attachment
written_text = """\
Hi,
How are you?"""
message.attach(MIMEText(written_text, "plain"))
# code to attach an csv file to a outlook email - works fine
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
)
message.attach(part)
msg_body = message.as_string()
server = SMTP('internal.org.com', 2089)
server.sendmail(message['From'], message['To'], msg_body)
print("mail sent successfully")
server.quit()
The problem in my code is that it creates a text file (containing the message "Hi, How are you") and sends as an attachment?
But I want "Hi, How are you" as a text message in the main Outlook message window.
The immediate problem is that many email clients assume that text body parts after the first are attachments. You can experiment with adding an explicit Content-Disposition: inline to the part(s) you want rendered as part of the main message, but is there a reason these need to be separate body parts in the first place? Combining the text fragments into a single body part would perhaps make more sense here.
More fundamentally, your email code was written for an older Python version. The email module in the standard library was overhauled in Python 3.6 to be more logical, versatile, and succinct; new code should target the (no longer very) new EmailMessage API. Probably throw away this code and start over with modern code from the Python email examples documentation.
from email.message import EmailMessage
message = EmailMessage()
message['Subject'] = 'For your review - files'
message['From'] = 'user2#org.com'
message['To'] = 'user1#org.com'
message.set_content(output, subtype="html")
written_text = """\
Hi,
How are you?"""
message.add_attachment(
written_text, subtype="plain",
disposition="inline")
with open(filename, "rb") as attachment:
message.add_attachment(
attachment.read(),
maintype="application", subtype="octet-stream",
filename=filename)
with SMTP('internal.org.com', 2089) as server:
server.send_message(message)
print("mail sent successfully")
server.quit()
If the final attachment is really a CSV file, specifying it as application/octet-stream is a bit misleading; the proper MIME type would be text/csv (see also What MIME type should I use for CSV?)
Right now I am using below code:
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = 'to address'
mail.Subject = 'Message subject'
mail.Body = 'Message body'
mail.HTMLBody = '<h2>HTML Message body</h2>'# this field is optional
**mail.Attachments.Add('C:\Users\MA299445\Downloads\screenshot.png')**
mail.Send()
I am able to attach a picture but I want to paste this picture in e-mail body.
Thanks in advance
You can use <img> HTML tag:
encoded_image = base64.b64encode(image_file.getvalue()).decode("utf-8")
html = '<img src="data:image/png;base64,%s"/>' % encoded_image
And you can put the tag inside your HTML content.
Don't forget to import required modules:
import base64
Create an attachment and set the PR_ATTACH_CONTENT_ID property (DASL name "http://schemas.microsoft.com/mapi/proptag/0x3712001F") using Attachment.PropertyAccessor.SetProperty.
Your HTML body (MailItem.HTMLBody property) would then need to reference that image attachment through the cid:
<img src="cid:xyz"/>
where xyz is the value of the PR_ATTACH_CONTENT_ID property.
Look at an existing message with OutlookSpy (I am its author) - click IMessage button, go to the GetAttachmentTable tab, double click on an attachment to see its properties.
attachment = mail.Attachments.Add("C:\Users\MA299445\Downloads\screenshot.png")
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "MyId1")
mail.HTMLBody = "<html><body>Test image <img src=""cid:MyId1""></body></html>"
I am looking to send an image embedded in HTML to send out to a list of senders.
I need to use win32com.client, SMTP is blocked. The image is saved as png and is originally a matplotlib bar chart.
The script successfully sends out the email the recipients cannot see the image embedded in the email. However, I can see the image when I send the email to myself.
I tried to attach the image to the email, still no luck.
email = """<body>
<p><img src="C:\output.png"></p>
</body>
"""
import win32com.client
olMailItem = 0x0
obj = win32com.client.Dispatch("Outlook.Application")
newMail = obj.CreateItem(olMailItem)
newMail.Subject = "the subject"
newMail.HTMLBody = email
newMail.To = "my_email#co.com;outside_email#co.com"
attachment1 = "C:\output.png"
newMail.Attachments.Add(attachment1)
newMail.Send()
Any help greatly appreciated!
In order to display the image in the mail body, use the below code:
mail.Attachments.Add(file_location + 'test.png')
mail.HTMLBody = "<html><body> <img src='cid:test.png'> </body></html>";
Basically if you want to display an attached image in the mail body, you have to refer to it using img src = 'cid:name' , or else it won't be shown.
The distribution list and I have a shared drive. I saved the file in the shared drive and now the receivers of the message can see the image in the email.
I had a similar issue, sending images through the body. Below I have attached the code that fixed it for me.
Code:
email.Display(False) ;
email.Send()
I want to use the following python code to automize some reporting
from win32com import client
obj = client.Dispatch("Outlook.Application")
newMail = obj.CreateItem(0x0)
newMail.Subject = "This is the subject"
...
newMail.Body = "This is the text I want to send in the mail body"
But doing it this way deletes the signature. The following code
...
newMail.Body = "This is the text I want to send in the mail body" + newMail.Body
preserves the signature, but destroys the formating. Not acceptable for compliance reasons.
Is there a way to prepend text to the mail body to circumvent the termination of the signatures format?
tmp = newMail.Body.split('<body>')
# split by a known HTML tag with only one occurrence then rejoin
newMail.Body = '<body>'.join([tmp[0],yourString + tmp[1]])
I'm trying to send a PDF attachment with an email body that summarises the contents of the PDF file. The email body is in both HTML and plaintext.
I'm using the following code to build the email email message object:
#Part A
logging.debug(" Building standard email with HTML and Plain Text")
msg = MIMEMultipart("alternative")
msg.attach(MIMEText(email_obj.attachments["plain_text"], "plain", _charset="utf-8"))
msg.attach(MIMEText(email_obj.attachments["html_text"], "html", _charset="utf-8"))
#Part B
logging.debug(" Adding PDF report")
pdf_part = MIMEApplication(base64.decodestring(email_obj.attachments["pdf_report"]), "pdf")
pdf_part.add_header('Content-Disposition', 'attachment', filename="pdf_report.pdf")
logging.debug(" Attaching PDF report")
msg.attach(pdf_part)
My problem is that my email body disappears if I attach the PDF. If I comment out the code that attaches the PDF (Part B), the email body appears.
Unless I'm mistaken, it looks as though my PDF attachment is overwriting the email body.
Such a message should have a more complex structure. The message itself contains two "top-level" MIME parts and has content-type "multipart/mixed". The first of these MIME part has type of "multipart/alternative" with two subparts, one for plain text and another for HTML. The second of the main parts is PDF attachment
pdfAttachment = MIMEApplication(pdf, _subtype = "pdf")
pdfAttachment.add_header('content-disposition', 'attachment', filename = ('utf-8', '', 'payment.pdf'))
text = MIMEMultipart('alternative')
text.attach(MIMEText("Some plain text", "plain", _charset="utf-8"))
text.attach(MIMEText("<html><head>Some HTML text</head><body><h1>Some HTML Text</h1> Another line of text</body></html>", "html", _charset="utf-8"))
message = MIMEMultipart('mixed')
message.attach(text)
message.attach(pdfAttachment)
message['Subject'] = 'Test multipart message'
f = open("message.msg", "wb")
f.write(bytes(message.as_string(), 'utf-8'))
f.close()
You may try to open a "source view" of a message in your favorite mail program (mail user agent) and see yourself (Ctrl-U in Thunderbird)