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"
Related
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)
Here my situation: I am currently retrieving all my outlook (2016) mails from my Inbox, and more specificcaly I am retrieving a table:
¦ Product ¦ Currency ¦ Tenor (months) ¦ Code 1 ¦
¦ MyItem ¦ USD ¦ 12 ¦ AAA01 ¦
My goal is to catch the body of each of them to then store them in a MsSQL Server.
I had difficulties to understand the 'Multipart' term, now with couples of (long) hours it's more clear.
So for now my process is:
going through all my mails in the Inbox
Creating a list of mails' Id
For all the Id I have in this list, I am checking if the mail is a Multipart one.
If Yes -> I retrieve the body with body = part.get_payload(decode=True)
If No -> I retrieve the body with body = b.get_payload(decode=True)
So in both case I use the get_payload(decode=True).
When my mail is "Multipart", it appears in my debugger as a simple text:
Product
Currency
Tenor (months)
Code 1
MyItem
USD
12
AAA01
When my mail isn't a Multipart, it appears in my debugger with HTML tags:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>
<body>
<table>
<tr>
<td><b>Product</b></td>
<td><b>Currency</b></td>
<td><b>Tenor (months)</b></td>
<td><b>Code 1</b></td>
</tr>
<tr>
<td>MyItem</td>
<td>USD</td>
<td>12</td>
<td>AAA01</td>
</tr>
</table>
</body>
</html>
How can I retrieve body of Multipart's mails with HTML tag also and not as simple text ?
I need HTML tag to identify each header and its corresponding value to use Beautiful Soup and Insert all those data into my MSSQL Server ?
Thanks for your help to let me understand better MIMEMultipart !
Here my (messy) python code:
#app.route('/ps_rfq_imap', methods=['GET', 'POST'])
def ps_rfq_imap():
#Connection to IMAP/OULTLOOK
url = 'outlook.mycompayny.com'
mailbox = imaplib.IMAP4_SSL(url,993)
user,password = ('mymail#mycompany.com','mypassword')
mailbox.login(user,password)
mailbox.list() # Lists all labels in GMail
mailbox.select('INBOX') # Connected to inbox.
#giving list id, not outlook ones, but uid ones
typ, data = mailbox.search(None,'ALL')
#Get all the uid outlook of all emails
#typ, data = mailbox.uid('search', None,'ALL')
ids = data[0]
id_list = ids.split()
print id_list
#get the most recent email id
latest_email_id = int( id_list[-1] )
for i in range( latest_email_id, latest_email_id-(latest_email_id), -1 ):
print 'EMAIL ID:'
print i
typ, data = mailbox.fetch( i, '(RFC822)')
msg=str(email.message_from_string(data[0][1]))
b = email.message_from_string(msg)
body = ""
if b.is_multipart():
email_from = b['from']
email_subject = b['subject']
print 'FROM:'
print email_from
print 'SUBJECT'
print email_subject
for part in b.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
body = part.get_payload(decode=True) # decode
print '******************************* MULTIPART body content***********************************'
print body
break
elif ctype == 'text/html':
print 'HTML PART'
continue
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
email_from = b['from']
email_subject = b['subject']
print 'FROM:'
print email_from
print 'SUBJECT'
print email_subject
body = b.get_payload(decode=True)
print '******************************* SIMMMMMMPPPPLLLLEEEE***********************************'
print body
return body
EDIT: here myupdated code to only catch the HTML part of my email, in case it can help somebody:
typ, data = mailbox.fetch( i, '(RFC822)')
msg=str(email.message_from_string(data[0][1]))
b = email.message_from_string(msg)
body = ""
if b.is_multipart():
email_from = b['from']
email_subject = b['subject']
for part in b.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
continue
elif ctype == 'text/html':
print 'HTML PART'
body = part.get_payload(decode=True) # decode
soup = BeautifulSoup(body)
metaTag = soup.find_all('meta')
if metaTag is not None:
print 'WE HAVE FOUND THE BODY******************** Time to process it with BS for getting the value of the table'
soup = BeautifulSoup(body, "html.parser")
tables = soup.findChildren('table')
continue
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
continue
Best Regards,
I am using Python34 to send messages via email. A part of the message is tabular. The column aligment gets all messed up in the email. Here is an illustration of how I am adding tables to the message:
import email.message
import smtplib
rows = [['A','EEEEE','A'],
['BB','DDDD','BB'],
['CCC','CCC','CCC'],
['DDDD','BB','DDDD'],
['EEEEE','A','EEEEE']]
msg_text = ""
for row in rows:
msg_text += "{:<8}{:<8}{:<8}\n".format(row[0], row[1], row[2])
msg = email.message.Message()
msg['Subject'] = 'Subject'
msg['From'] = 'sender#from'
msg['To'] = 'receiver#to'
msg.add_header('Content-Type','text/plain')
msg.set_payload(msg_text)
smtp_connection = smtplib.SMTP('HHHHUB02', 25, timeout=120)
smtp_connection.sendmail(msg['From'], msg['To'], msg.as_string())
print(msg.as_string())
It looks like this on my terminal:
terminal print screen
It looks like this on my email:
email print screen
How to keep string formatting when sending an email.message via smtplib?
(solution)
With the code below I was able to combine text and tables in an htlm message that preserved table alignment.
from email.mime.text import MIMEText
import smtplib
html_font_style = 'style="font-size: 13px; font-family: calibri"'
message = '<!DOCTYPE html>\n'
message += '<html>\n'
message += '<body>\n'
text = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \n"
text += "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB \n"
text_html = "<p {}> {} </p>\n".format(html_font_style, text.replace('\n', '\n<br /> '))
table_html = '<table {}>\n'.format(html_font_style)
table_data = [['A','EEEEE','A'],
['BB','DDDD','BB'],
['CCC','CCC','CCC'],
['DDDD','BB','DDDD'],
['EEEEE','A','EEEEE']]
for data in table_data:
table_html += ' <tr>\n'
table_html += ' <td> '
table_html += ' </td> <td> '.join(data)
table_html += ' </td>'
table_html += ' </tr>\n'
table_html += '</table>\n'
message = message + text_html + table_html
message += '</body>\n'
message += '</html>\n'
msg = MIMEText(message, 'html')
msg['Subject'] = 'Subject'
msg['From'] = 'sender#from'
msg['To'] = 'receiver#to'
smtp_connection = smtplib.SMTP('HHHHUB02', 25, timeout=120)
smtp_connection.sendmail(msg['From'], msg['To'], msg.as_string())
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>
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.