How to reference variable in python html email? - python

I am trying to send an email with python and i have a variable ("string") from my flask route which i would like to reference in my email html.
#app.route('/edit', methods=['GET','POST'])
def edit():
...
s_list = S.query.all()
strings = '\n'.join([str(s) for s in s_list])
global string
string = str(strings)
print(string)
However, nothing appears in the variable part when the email is sent. I tried to print it on terminal and could see the results.
Can anyone let me know what am i doing wrongly please?
message = MIMEMultipart("alternative")
message["Subject"] = "Thank you."
message["From"] = sender_email
message["To"] = user_mail
# Write the plain text part
text = "Thank you for your submission! " + string
# write the HTML part
html = """\
<html>
<head></head>
<body>
<p>Thank you for your submission! <br>
""" + string + """
<br></br>
</p>
</body>
</html>
""".format(string=string)
# convert both parts to MIMEText objects and add them to the MIMEMultipart message
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")
message.attach(part1)
message.attach(part2)

Related

Sending a pandas Dataframe using smtplib

I've seen a lot of threads here about this topic, however, none regarding this specific question.
I am sending a email with a pandas dataframe (df) as an html using pandas built in df.to_html() method. The email sends successfully. However, the df is displayed in the email as html, not in the desired table format. Can anyone offer assistance on how to ensure the df is displayed as a table, not in html in the email? The code is below:
import requests
import pandas as pd
import smtplib
MY_LAT =
MY_LNG =
API_KEY = ""
parameters = {
"lat": MY_LAT,
'lon': MY_LNG,
'exclude': "",
"appid": API_KEY
}
df = pd.read_csv("OWM.csv")
response = requests.get("https://api.openweathermap.org/data/2.5/onecall", params=parameters)
response.raise_for_status()
data = response.json()
consolidated_weather_12hour = []
for i in range(0, 12):
consolidated_weather_12hour.append((data['hourly'][i]['weather'][0]['id']))
hour7_forecast = []
for hours in consolidated_weather_12hour:
weather_id = df[df.weather_id == hours]
weather_description = weather_id['description']
for desc in weather_description.iteritems():
hour7_forecast.append(desc[1])
times = ['7AM', '8AM', '9AM', '10AM', '11AM', '12PM', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM']
col_header = ["Description of Expected Weather"]
weather_df = pd.DataFrame(data=hour7_forecast, index=times, columns=col_header)
my_email = ""
password = ""
html_df = weather_df.to_html()
with smtplib.SMTP("smtp.gmail.com", 587) as connection:
connection.starttls() # Makes connection secure
connection.login(user=my_email, password=password)
connection.sendmail(from_addr=my_email, to_addrs="",
msg=f"Subject: 12 Hour Forecast Sterp"
"""\
<html>
<head></head>"
<body>
{0}
<body>
</html>
""".format(html_df))
just use df.to_html() to convert it into an html table that you can include in your html email
then when you send the mail you must set the mimetype to html
smtp = smtplib.SMTP("...")
msg = MIMEMultipart('alternative')
msg['Subject'] = subject_line
msg['From'] = from_addr
msg['To'] = ','.join(to_addrs)
# Create the body of the message (a plain-text and an HTML version).
part1 = MIMEText(plaintext, 'plain')
part2 = MIMEText(html, 'html')
smtp.sendmail(from_addr, to_addrs, msg.as_string())
you can use the library html2text to convert your html to markdown for clients that do not support html content (not many these days) if you do not feel like writing the plaintext on your own
as an aside... using jinja when you are working with html tends to simplify things...

how to break line in list in python email

I am trying to query a list from my Flask database and then send it out as a html email. However, i am unable to break them into different lines.
for example, instead of:
a
b
c
i get abc currently in the email. i've tried adding "\n" in the loop but it doesnt seem to work. does anyone know how i can break it into different rows?
def mail():
sender_email = "xx#gmail.com"
message = MIMEMultipart("alternative")
message["Subject"] = "xx"
message["From"] = sender_email
message["To"] = user_mail
add = '\n'
list = Lines.query.all()
for s in list:
add += str(s.title) + '\r\n'
print(add)
# Write the plain text part
text = "Thank you for submitting a xx! Here are the lines submitted: " + add
# write the HTML part
html = """\
<html>
<head><head style="margin:0;padding:0;">
<table role="presentation" style="width:100%;border-collapse:collapse;border:20;border-spacing:20;background:#cc0000;">
<tr>
<td align="center" style="padding:20;color:#ffffff;">
Your xxxxx was submitted!
</td>
</tr>
</table>
</head>
<p>Thank you for submitting a xx! Here are the lines submitted for your reference:<br><br>
""" + add + """
<br></br>
</p>
</html>
"""
# convert both parts to MIMEText objects and add them to the MIMEMultipart message
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")
message.attach(part1)
message.attach(part2)
...
server.sendmail("xx#gmail.com", user_mail, message.as_string())
return redirect(url_for('complete'))
I believe what you're looking for is this:
list = Lines.query.all()
for s in list:
add += str(s.title) + '<br>'
or (using format vs string concatenation):
list = Lines.query.all()
for s in list:
add += '{}<br>'.format(str(s.title))
or (python 3.6+ f strings):
list = Lines.query.all()
for s in list:
add += f"{s.title}<br>"
\n is not for HTML, but <br> is.
You can use an empty string and keep adding in the loop.
str = ""
for s in list:
str += f"{s.title}\n"

Python email library does not add all MIME text parts

I added piece of code in my program. Why is it not working?
Below is the sample code:
wrapper = MIMEMultipart('mixed')
text1 = "this is a sample text"
text2 = "this is a sample msg"
part1 = MIMEText(text1, "plain")
part2 = MIMEText(text2, "plain")
wrapper.attach(part1)
wrapper.attach(part2)
output:
Part1 value is coming in msg body but part2 value is coming as attachment in mail. Why part2 value is not coming in msg body?
Send the message as a string. Try the below code. It works for me:
wrapper = MIMEMultipart('mixed')
text1 = "this is a sample text"
text2 = "this is a sample msg"
#change the message type to html type
part1 = MIMEText(text1, "html")
part2 = MIMEText(text2, "html")
#create the message to send
wrapper.attach(part1)
wrapper.attach(part2)
#finally send the message by converting it to string
server.sendmail(from, recipients, wrapper.as_string())

Is it possible to iterate a dict in python for use in a html email

I am trying to send a email notification, and I would like to send dynamic data(for testing purposes my dictionary is static). How ever when I iterate trough my dictionary only one value shows up in the email. Any help would be greatly appreciated!!!
Here is my email.py
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# me == my email address
# you == recipient's email address
me = "test_email#mydomain.com"
you = "test_email_user#mydomain.com"
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you
justin = "Justin"
p = {u'Contracts that need signed by: Justin': [[u'/contracts/26203', u'/contracts/26194', u'/contracts/26199', u'/contracts/26173']]}
for a in p.keys():
b = p['Contracts that need signed by: Justin']
for c, d in enumerate(b):
e = d
for f in e:
html = """\
<html>
<head></head>
<body>
<p>Contracts that need signed by """ + justin + """<br>
How are you?<br>
Here is the link you wanted.
</p>
</body>
</html>
"""
part2 = MIMEText(html, 'html')
msg.attach(part2)
s = smtplib.SMTP('localhost')
s.sendmail(me, you, msg.as_string())
s.quit()
Here is the email I get ^
Contracts that need signed by Justin
How are you?
Here is the link you wanted.
Which I want it to look like this
Contracts that need signed by Justin
How are you?
#EACH OF THE LINKS WOULD BE THE NEXT VALUE IN MY DICTONARY.
Here is the link1 you wanted.
Here is the link2 you wanted.
Here is the link3 you wanted.
Here is the link4 you wanted.
You are overwriting the html variable over and over again.
You have to add always 1 line in the for loop like this:
justin = "Justin"
p = {u'Contracts that need signed by: Justin': [[u'/contracts/26203', u'/contracts/26194', u'/contracts/26199', u'/contracts/26173']]}
for a in p.keys():
b = p['Contracts that need signed by: Justin']
for c, d in enumerate(b):
e = d
html = """\
<html>
<head></head>
<body>
<p>Contracts that need signed by """ + justin + """<br>
How are you?<br>
"""
for f in e:
html = html + """Here is the link you wanted. \n"""
html = html + """</p>
</body>
</html>
"""
part2 = MIMEText(html, 'html')
print part2
The problem is you overwrite html variable on each iteration.
You can use string formatting for your problem:
for c, d in enumerate(b):
e = d
html = """\
<html>
<head></head>
<body>
<p>Contracts that need signed by """ + justin + """<br>
How are you?<br>
{0}
</p>
</body>
</html>
"""
s = []
for f in e:
print(f)
s.append('Here is the <a href="http://contract.mydomain.com/{0}>link</a> you wanted.'.format(f))
print(s)
html = html.format('\n'.join(s))
print(html)
output:
<html>
<head></head>
<body>
<p>Contracts that need signed by aaa<br>
How are you?<br>
Here is the <a href="http://contract.mydomain.com//contracts/26203>link</a> you wanted.
Here is the <a href="http://contract.mydomain.com//contracts/26194>link</a> you wanted.
Here is the <a href="http://contract.mydomain.com//contracts/26199>link</a> you wanted.
Here is the <a href="http://contract.mydomain.com//contracts/26173>link</a> you wanted.
</p>
</body>
</html>

Python - sending HTML Mail with Variables

I wanted to make a small cronmailer for my personal use. And here's the part wich do not work
# Create the body of the message (a plain-text and an HTML version).
text = "LOG OUTPUT: " + sys.argv[1] + "\n"
logdata = open(sys.argv[2], "rb")
for row in logdata:
text = text + row
html = """\
<html>
<head></head>
<body>
<p>LOG OUTPUT: {0} <br> {1}
</p>
</body>
</html>
""".format(unicode(str(sys.argv[1]),'utf-8'), unicode(str(logdata),'utf-8'))
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
msg.attach(part1)
msg.attach(part2)
server = smtplib.SMTP(str(server) + ":" + str(port))
server.starttls()
server.login(username,password)
server.sendmail(emailfrom, emailto, msg.as_string())
server.quit()
I get the mail. With the Plain Text and the attachment (left the code out, cause it works). But not the HTML part. The only thing I get there is:
<html>
<head></head>
<body>
<p>LOG OUTPUT: test
Thanks for any help and a Happy New Year
Here are likely-better ways to build that html string (in Python 2):
import cgi
text = "LOG OUTPUT: " + sys.argv[1] + "\n"
with open(sys.argv[2], "rb") as f:
text += f.read()
html = """\
<html>
<head></head>
<body>
<p>LOG OUTPUT: {0}<br/>
<pre>{1}</pre>
</p>
</body>
</html>""".format(unicode(str(sys.argv[1]), 'utf-8'),
unicode(cgi.escape(text), 'utf-8'))
Note that in Python 3 the escaping function is html.escape (so you'd better not name your own variable html as it will clash:-), but for Python 2, where the escaping function is the peculiarly named cgi.escape, this should be OK.

Categories

Resources