Im trying to attach an image to my email sender written python - python

Here is my code
import sys
import smtplib
import imghdr
from email.message import EmailMessage
from tkfilebrowser import askopenfilename
from email.mime.base import MIMEBase
from email.encoders import encode_base64
from email import encoders
def send():
msg = EmailMessage()
msg['Subject'] = body
msg['From'] = 'sender#gmail.com'
msg['To'] = 'receiver#gmail.com'
it worked well until i added this below to attach an image
with open('DSC_0020.jpg', 'rb') as f:
mime = MIMEBase('image', 'jpg', filename="DSC_0020.jpg")
mime.add_header('Content-Dispotion', 'attachment', filename="DSC_0020.jpg")
mime.add_header('X-Attachment-Id', '0')
mime.add_header('Content-ID', '<0>')
mime.set_payload(f.read())
encoders.encode_base64(mime)
mime.attach(mime)
msg.set_content('This is a plain text email')
msg.add_alternative("""\
<DOCTYPE html>
<html>
<body>
<h1 style="color:gray;"> This is an HTML Email! </h1>
<img src="body">
</body>
</html>
""", subtype='html')
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login('sender51#gmail.com', 'password')
smtp.send_message(msg)
here is the error i get can someone tell me what im doing wrong
File "C:\Users\my name\AppData\Local\Programs\Python\Python38\lib\email\message.py", line 210, in attach
raise TypeError("Attach is not valid on a message with a"
TypeError: Attach is not valid on a message with a non-multipart payload

The main part of the email message should be of type MIMEMUltipart and then text content should be of type MIMEText as follows:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# and, of course, other imports
msg = MIMEMultipart('alternative') # to support alternatives
msg['Subject'] = body
msg['From'] = 'sender#gmail.com'
msg['To'] = 'receiver#gmail.com'
with open('DSC_0020.jpg', 'rb') as f:
mime = MIMEBase('image', 'jpg', filename="DSC_0020.jpg")
mime.add_header('Content-Disposition', 'attachment', filename="DSC_0020.jpg") # corrected header
mime.add_header('X-Attachment-Id', '0')
mime.add_header('Content-ID', '<0>')
mime.set_payload(f.read())
encode_base64(mime) # improved statement (you can now get rid of following import: from email import encoders)
msg.attach(mime) # corrected statement
# Attach the plain text as first alternative
msg.attach(MIMEText('This is a plain text email', 'plain'))
# Attach html text as second alternative
msg.attach(MIMEText("""\
<DOCTYPE html>
<html>
<body>
<h1 style="color:gray;"> This is an HTML Email! </h1>
<img src="body">
</body>
</html>
""", 'html'))
You had some errors in your file processing block, which I tried to correct. There may have been others I did not catch.

Related

How to add a dynamic content into html for sending mail in Python

I am sending mail with html content using 'smtplib' in python , I want to add dynamic content to that html.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
message = MIMEMultipart("alternative")
message["Subject"] = "Error Notification"
message["From"] = sender
message["To"] = sender
# Create the plain-text and HTML version of your message
html = """\
<html>
<body>
<p>Hi,<br>
<span>Something went wrong !</span><br>
</p>
</body>
</html>
"""
part1 = MIMEText(html, "html")
# Add HTML/plain-text parts to MIMEMultipart message
message.attach(part1)
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message.as_string())
print "Successfully sent email"
except smtplib.SMTPException:
print "Error: unable to send email"
Along with the above html I need to include some of my dynamic contents inside the body tag
Since this is Python you can do really awesome things with strings. Just name certain areas of the html with special names and then use the replace method to replace them with whatever value you want.
html = """\
<html>
<body>
<p>Hi, $(name)<br>
<span> $(error) </span><br>
</p>
</body>
</html>
"""
html = html.replace("$(name)", "John")
html = html.replace("$(error)", "Something went wrong!")
print(html)
To include the dynamic content, just get the data from your data source and concatenate them to the body of the mail as per your need.

Personlized Content for Automated E-mail

Sending out a e-mail that allows me to edit personalized content within the body of the e-mail. For example I would like to input the the 5 digit ext of a users phone. Then have it formatted into the body of the e-mail. Here is my code.
def instruct(send):
pass
import smtplib
from email.mime.text import MIMEText
from email.message import EmailMessage
email_user = 'E-mailaddress'
email_send = input('Enter address to Send e-mail to: ')
digits = input('Enter users 5 digit Phone Ext: ') #Users phone ext
subject = 'Voice Mail Instructions '
msg = EmailMessage()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
#body of e-mail with formatted e-mail message
signature = """\
<html>
<body>
<p>Hi,<br>
Attached Below are instructions for setting up voice mail at your {ext}. Please let me know if you have any questions.<br>
<br>
Thanks<br>
</p>
</body>
</html>
"""
msg.format(ext=digits)
msg.set_content(signature)
filename = 'mypdf.pdf'
with open(filename, 'rb') as content_file:
content = content_file.read()
msg.add_attachment(content, maintype='application/pdf', subtype='pdf', filename=filename)
text = msg.as_string()
server = smtplib.SMTP('mailserver',25)
server.sendmail(email_user, email_send,text)
server.quit
if I am understanding the question correctly, you want to alter the text to include the 5 digit number input by the user, in which case, try:
#body of e-mail with formatted e-mail message
signature = """\
<html>
<body>
<p>Hi,<br>
Attached Below are instructions for setting up voice mail at your extension: {}. Please let me know if you have any questions.<br>
<br>
Thanks<br>
</p>
</body>
</html>
""".format(digits)

send html email with embedded image using python script

I am newbie to Python. I wanted to send html based email with company logo embedded on top left to the email body.
With the following code the email is absolutely working but not attaching the embedded image anymore. Not sure where i did mistake. Can anyone please help me out here.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.MIMEImage import MIMEImage
msg = MIMEMultipart('alternative')
msg['Subject'] = "My text dated %s" % (today)
msg['From'] = sender
msg['To'] = receiver
html = """\
<html>
<head></head>
<body>
<img src="cid:image1" alt="Logo" style="width:250px;height:50px;"><br>
<p><h4 style="font-size:15px;">Some Text.</h4></p>
</body>
</html>
"""
# The image file is in the same directory as the script
fp = open('logo.png', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
msgImage.add_header('Content-ID', '<image1>')
msg.attach(msgImage)
part2 = MIMEText(html, 'html')
msg.attach(part2)
mailsrv = smtplib.SMTP('localhost')
mailsrv.sendmail(sender, receiver, msg.as_string())
mailsrv.quit()
I figured out the issue. Here is the updated code for your referance.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.MIMEImage import MIMEImage
msg = MIMEMultipart('related')
msg['Subject'] = "My text dated %s" % (today)
msg['From'] = sender
msg['To'] = receiver
html = """\
<html>
<head></head>
<body>
<img src="cid:image1" alt="Logo" style="width:250px;height:50px;"><br>
<p><h4 style="font-size:15px;">Some Text.</h4></p>
</body>
</html>
"""
# Record the MIME types of text/html.
part2 = MIMEText(html, 'html')
# Attach parts into message container.
msg.attach(part2)
# This example assumes the image is in the current directory
fp = open('logo.png', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# Define the image's ID as referenced above
msgImage.add_header('Content-ID', '<image1>')
msg.attach(msgImage)
# Send the message via local SMTP server.
mailsrv = smtplib.SMTP('localhost')
mailsrv.sendmail(sender, receiver, msg.as_string())
mailsrv.quit()
In case you want something simple:
from redmail import EmailSender
email = EmailSender(host="smtp.myhost.com", port=1)
email.send(
sender="me#example.com",
subject="Example email",
receivers=["you#example.com"],
html="""
<h1>Hi, take a look at this image:</h1>
{{ my_image }}
""",
body_images={"my_image": "path/to/image.png"}
)
The image is embedded to the HTML using Jinja and it creates the img tag automatically. You may also directly pass bytes, matplotlib.Figure or PIL.Image.Image to body_images as well if you prefer those formats.
In case you want more control on the image's properties, like change the width and height:
email.send(
sender="me#example.com",
subject="Example email",
receivers=["you#example.com"],
html="""
<h1>Hi, take a look at this image:</h1>
<img src="{{ my_image.src }}" width=500 height=350>
""",
body_images={"my_image": "path/to/image.png"}
)
Pip install it from PyPI:
pip install redmail
There is a lot the library can do: include attachments from various forms, prettify and embed tables to HTML body, load templates from disk, parametrize etc. It is also well tested (100 % test coverage) and documented. I'm the author of the library and sorry for the self-promotion. I think it's awesome and worth sharing.
Documentation: https://red-mail.readthedocs.io/en/latest/index.html
Source code: https://github.com/Miksus/red-mail

How to embed .png into HTML email?

I'm currently using the following code to send an email (which contains a report) to users 3 times per day. I'd like to add in a graph to this email but can't seem to figure out how.
def HTML_Email(subject, to, html, files, filename):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from os.path import basename
import email
import email.mime.application
# Create message container - the correct MIME type is
multipart/alternative.
msg = MIMEMultipart('mixed')
msg['Subject'] = subject
msg['From'] = "ChicagoGISScripts#mobilitie.com"
msg['To'] = ", ".join(to)
# Record the MIME types of both parts - text/plain and text/html
part2 = MIMEText(html, 'html')
# create PDF attachment
fp=open(files,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype="xlsx")
fp.close()
att.add_header('Content-Disposition','attachment',filename=filename)
# Attach parts into message container.
msg.attach(att)
msg.attach(part2)
# Send the message via local SMTP server.
user = 'ausername'
pwd = 'apassword'
s = smtplib.SMTP('smtp.office365.com',587)
s.ehlo()
s.starttls()
s.ehlo()
s.login(user,pwd)
s.sendmail(msg['From'], to, msg.as_string())
s.quit()
Typically I'll use something like this to go along with it, but I'm trying to include a .png that's stored locally on my computer. is not working to embed an image into the body of the email, what am I missing here?
html = """\
<html>
<head></head>
<body>
<p><font face ="Gotham, monospace">Some HTML,<br><br>
<img src="C:\\Users\\Me\\Desktop\\graphs.png"></img></font>
</p>
</body>
</html>
"""
Because you aren't hosting the image on a server, you won't be able to embed it in an email using a normal link. Try encoding the .png file into a data uri and setting that as the src
EDIT
Look at this other answer to see how to do this in python
EDIT 2
The resulting html should look like this
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
Exactly what RemedialBear said. You have to host the email on a server and have an absolute src in your email body.
Instead of:
<img src="C:\\Users\\Me\\Desktop\\graphs.png">
You need:
<img src="http://www.somedomain.com/images/graphs.png" alt="Name' />

How do I send a html content in mail body using python?

I am sending a mail by reading an excel file using pandas as dataframe. Then I am converting that dataframe using df.to_html with CSS style wrapped. Below is my code.
from email.mime.text import MIMEText
import email.message
import numpy as np
import pandas as pd
import email
import smtplib
import xlrd
filename = 'exl_sheet.xls'
df = pd.read_excel(filename)
html_string = '''
<html>
<head><title>HTML Pandas Dataframe with CSS</title></head>
<link rel="stylesheet" type="text/css" href="df_style.css"/>
<body>
{table}
</body>
</html>.
'''
df_html = html_string.format(table=df.to_html(classes='mystyle'))
sender = "sender#gmail.com"
receiver = "receiver#gmail.com"
password = 'xxxxxxxxx'
server = 'smtp.gmail.com:587'
msg = email.message.EmailMessage()
msg['Subject'] = 'Train Data'
msg['From'] = sender
msg['To'] = receiver
msg = MIMEText(df_html, 'html')
print(msg)
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(sender, password)
server.sendmail(sender, receiver, msg)
server.quit()
The output of print(msg) is :
enter image description here
However, the message I am receiving is as below :
enter image description here
That is I am not receiving the table with style. Please suggest.
First, I believe that only inline styles are supported on email -- at least that's all you can depend on across all email clients. For example, Gamil strips out all <head> and <body> tags. Try adding style parameters to your HTML tags, for example:
<span style="color: red;">I am red</span>
Even if you could have external style sheets, you specified: href="df_style.css", which is a relative URL. If you sent that email to me, would I have that stylesheet on my PC? You would need to make it an absolute URL, such as href="http://demo.com/df_syle.css". Keep this in mind when you reference other items in your email, such as images.

Categories