so basically i have this script that runs continuously and when a new email arrives in the inbox with specific text in the subject, it grabs information from the email. I have only managed to get it to pull the subject from the email but I cant get it do get the body of the email no matter what I try, I believe the email body is in HTML so i attempted to use BeautifulSoup to parse the body but that doesnt work at all. Please help!!! :( Here is what i have so far:
import email
import imaplib
from bs4 import BeautifulSoup
import time
import sys
username = 'xxx.xxx#xxx.xx'
password = 'xxxxxx'
mail = imaplib.IMAP4_SSL('imap-mail.outlook.com')
(retcode, capabilities) = mail.login(username, password)
mail.list()
n=0
while True:
mail.select('inbox')
(retcode, messages) = mail.search(None, 'UNSEEN', '(SUBJECT "xxxxxxx-
")', '(FROM "xx.xx#xxxx.xx")')
if retcode == 'OK':
for num in messages[0].split():
n=n+1
print('Processing Email ' + str(n))
typ, data = mail.fetch(num, '(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
original = email.message_from_bytes(response_part[1])
print("Subject: " + original['Subject'])
typ, data = mail.store(num,'+FLAGS','\\Seen')
time.sleep(120)
Comment: The "body" returned by imap.fetch are usually bytes, not a string, which throws an exception
Change to:
msg = email.message_from_bytes(body)
Question: I cant get it do get the body of the email
For example:
import email, imaplib
username = 'xxx.xxx#xxx.xx'
password = 'xxxxxx'
imap = imaplib.IMAP4_SSL('imap-mail.outlook.com')
imap.login(username, password)
imap.select("inbox")
resp, items = imap.search(None, "(UNSEEN)")
for n, num in enumerate(items[0].split(), 1):
resp, data = imap.fetch(num, '(RFC822)')
body = data[0][1]
msg = email.message_from_string(body)
content = msg.get_payload(decode=True)
print("Message content[{}]:{}".format(n, content))
Related
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...
I have an web app (example.com) for sending email. I want to send email to multiple email addresses from the list, which are stored in mailing_list.txt. For this purpose I used python with mechanize module.
This code seems to work, but emails are not delivering.
#!/bin/python
import mechanize
sender = raw_input("Enter sender email : ")
subject = raw_input("Subject : ")
msg = raw_input("Enter message : ")
filename = raw_input("Attachment location e.g. /home/user/test.txt : ")
file_list = []
f = open('/home/user/mailing_list.txt', 'r')
for line in f.xreadlines():
url = "http://example.com/"
file_list.append([line])
br = mechanize.Browser()
br.set_handle_robots(False)
br.set_handle_refresh(False)
br.open(url)
br.form = list(br.forms())[0]
br["from"] = sender
br["to"] = line
br["subject"] = subject
br["msg"] = msg
br.form.add_file(open(filename,'rb'),'text/txt',filename,name='file')
response = br.submit()
responder = response.code
print "Code = " + str(responder)
print "e-mail sent to: " + line
Where could be the problem? From responder I am receiving code 200, and as well I am receiving e-mail sent to each email address from the list/file.
print "Code = " + str(responder)
print "e-mail sent to: " + line
Also if I add lines:
print br["to"]
or/and
print line
I am getting the right response. I mean, it prints current email address from the list.
I can't send in the form on the website data through the python script. The usual feedback form, which works properly when manually filling, but does not send anything if you send a request script. What to do?
The script sending a request to the site:
import requests
import sys
URL = 'http://127.0.0.1:8000/'
client = requests.session()
client.get(URL)
csrftoken = client.cookies['csrftoken']
login_data = dict(lastname='Игин', name='Anton', middlename='Konst', birthday='2017-04-20', telephone='(896) 097-29-02', csrfmiddlewaretoken=csrftoken, next='form_call/')
r = client.post(URL, data=login_data, headers=dict(Referer=URL))
views.py
def form_call(request):
if request.method=='POST':
form = Call_Form(request.POST)
name = request.POST.get('name', '')
lastname = request.POST.get('lastname', '')
middlename = request.POST.get('middlename', '')
birthday = request.POST.get('birthday', '')
telephone = request.POST.get('telephone', '')
if form.is_valid():
mail_host = SMTPMail.objects.all()[0]
rec_list = RecMail.objects.all()
recipients= []
for mail in rec_list:
recipients.append(mail.mail) #Список получателей
message = '''
На сайте вашей структуры NL International появилась новая заявка на звонок! Вот данные, предоставленные новым консультантом:
ФИО:{0} {1} {2}
Дата рождения: {3}
Телефон: {4}'''.format(name,lastname, middlename, birthday, telephone)
subject= 'Заявка на звонок'
send_mail(subject, message, mail_host.mail, recipients, fail_silently=False)
return redirect('/thanks/')
else:
return redirect('/error/')
I am already solved my problem. There is my code:
import requests
import sys
URL = 'http://127.0.0.1:8000/' #address of web page with html form
URL2 = 'http://127.0.0.1:8000/form_call/' #address of view processing form data
client = requests.session()
client.get(URL)
csrftoken = client.cookies['csrftoken']
login_data = dict(lastname='Игин', name='Anton', middlename='Konst testim', birthday='2017-01-20', telephone='896-002-00-02', csrfmiddlewaretoken=csrftoken)
r = client.post(URL2, data=login_data)
I have the following code to get an HTML email as a email.Message object but am unsure how to proceed from here to find the url of the hyperlink given its display name. I have located the url in the payload(0). In addition the email is a href=3D so it doesnt work if i just copy the link and paste into a browser.
import sys
import imaplib
import getpass
import email
import datetime
import email
M = imaplib.IMAP4_SSL('imap.gmail.com')
M.login('email#email.com','password123')
rv,boxes = M.list()
rv,boxes = M.select('Inbox/Test1')
rv, data = M.search(None, 'ALL')
typ, msg_data = M.fetch('1', '(RFC822)')
msg = email.message_from_string(msg_data[0][1])
url_name = 'Click Here'
html_text = msg.get_payload(0)
this will show all href in the message...one can update the parseLinks class to choice their individual string they are interested in.
import imaplib
import email
import quopri
import HTMLParser
class parseLinks(HTMLParser.HTMLParser):
def handle_starttag(self, tag, attrs):
global global_futures_fair_value
if tag == 'a':
for name, value in attrs:
if name == 'href':
print name
print value
M = imaplib.IMAP4_SSL('imap.gmail.com')
M.login('email#email.com','password123')
M.select('Inbox/Test1')
rv, data = M.search(None, 'ALL')
typ, msg_data = M.fetch('1', '(RFC822)')
msg = email.message_from_string(msg_data[0][1])
url_name = 'Click Here'
html_text = msg.get_payload(0)
msg = str(msg.get_payload()[0])
msg = quopri.decodestring(msg)
linkParser = parseLinks()
linkParser.feed(msg)
I have an email body which looks somewhat like .
Now I want to remove all the header from it and just have the conversation email text. How can I do it in python?
I tried email.parser module but that isn't giving me the result which I want.
Please find the below code for more information.
import email
a="""--c66f5985-233d-4e89-b598-6398b60cbe00
Content-Type: multipart/alternative;
differences="Content-Type";
boundary="d5eff9f8-76b3-4320-adfb-1e51add8fa8f"
--d5eff9f8-76b3-4320-adfb-1e51add8fa8f
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
THis is a demo email body
Thanks And Regards,
Ana
"""
b = email.message_from_string(a)
if b.is_multipart():
for payload in b.get_payload():
# if payload.is_multipart(): ...
print (payload.get_payload())
else:
print (b.get_payload())
import imaplib,email
hst = "your.host.adresse.com"
usr = "login"
pwd = "password"
imap = imaplib.IMAP4(hst)
try:
imap.login(usr, pwd)
except Exception as e:
raise IOError(e)
try:
imap.select("Inbox") # Tell Imap where to go
result, data = imap.uid('search', None, "ALL")
latest = data[0].split()[-1]
result, data = imap.uid('fetch', latest, '(RFC822)')
a = data[0][1] # This contains the Mail Data
except Exception as e:
raise IOError(e)
b = email.message_from_string(a)
if b.is_multipart():
for payload in b.get_payload():
b = (payload.get_payload())
else:
b = (b.get_payload())
print b
This removes all the stuff from the mail you don't want in the final text. I've tested this with your code. You didn't show how you import the mail (your a) so i guess that's where you get the decoding problem from.
If you have any trouble with HTML Mails:
from bs4 import BeautifulSoup
soup = BeautifulSoup(b, 'html.parser')
soup = soup.get_text()
print soup
That should do the job for now, but I'd advise you to change the default python parser to lxml or html5lib.