Here is my code:
conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login('username', 'password')
conn.select()
typ, data = conn.search(None, "ALL")
parser1 = HeaderParser()
for num in data[0].split():
typ, data = conn.fetch(num, '(RFC822)')
header_data = str(data[1][0])
msg = email.message_from_string(header_data)
print(msg.keys())
print(msg['Date'])
Why am i getting "[]" for the printout of msg.keys() and "None" for the msg['Date']. No error messages. However, if i comment out the last 4 lines of code, and type print(data), then all the headers get printed? Im using python 3.4
conn.fetch returns tuples of message part envelope and data. For some reason -- I'm not sure why -- it may also return a string, such as ')'. So instead of hard-coding data[1][0], it's better (more robust) to just loop through the tuples in data and parse the message parts:
typ, msg_data = conn.fetch(num, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
For example,
import imaplib
import config
import email
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login(config.GMAIL_USER2, config.GMAIL_PASS2)
try:
conn.select()
typ, data = conn.search(None, "ALL")
print(data)
for num in data[0].split():
typ, msg_data = conn.fetch(num, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
part = response_part[1].decode('utf-8')
msg = email.message_from_string(part)
print(msg.keys())
print(msg['Date'])
finally:
try:
conn.close()
except:
pass
finally:
conn.logout()
Much of this code comes from Doug Hellman's imaplib tutorial.
Related
I am trying to read an email in Gmail that has a specific subject and get the OTP value within the email. I am using imaplib
import imaplib
def get_CreateAccount_OTP(self, email_type):
gmail = imaplib.IMAP4_SSL("imap.gmail.com", 993)
gmail.login(self.gmail_username, self.gmail_password)
gmail.select('Inbox', readonly=True)
type, data = gmail.search(None, '(SUBJECT "Here\'s your Texas by Texas email verification.")')
I got the type returned as Ok, but the data as below
data = {list: 1} [b'']
0 = {bytes: 0} b''
__len__ = {int} 1
After that line, it's not going into the below "for loop"
for num in data[0].split():
typ, data = gmail.fetch(num, '(RFC822)')
raw_email = data[0][1]
raw_email_string = raw_email.decode('utf-8')
email_message = str(email.message_from_string(raw_email_string))
email_message_list = email_message.split('\n')
RE_TIME_STAMP_PATTERN = re.compile((r'\d{6}'))
for line in email_message_list:
print(line)
if 'Your sign-in verification code is ' in line:
self.OTP = re.findall(RE_TIME_STAMP_PATTERN, line)[0]
break
self.log.info("OTP:",self.OTP)
return self.OTP
Note: I am new to Python and learning it slowly. Please bare with my silly questions
Thanks in advance
I found the issue that the string has special char and the implib is not converting the char to Unicode. So I have to remove the word that has the special char in my string.
import imaplib
def get_CreateAccount_OTP(self, email_type):
subject="your Texas by Texas email verification."
gmail = imaplib.IMAP4_SSL("imap.gmail.com", 993)
gmail.login(self.gmail_username, self.gmail_password)
gmail.select('Inbox', readonly=True)
type, data = gmail.search(None, '(UNSEEN SUBJECT "%s")' % subject)
for num in data[0].split():
typ, data = gmail.fetch(num, '(RFC822)')
raw_email = data[0][1]
raw_email_string = raw_email.decode('utf-8')
email_message = str(email.message_from_string(raw_email_string))
email_message_list = email_message.split('\n')
RE_TIME_STAMP_PATTERN = re.compile((r'\d{6}'))
for line in email_message_list:
print(line)
if 'Your sign-in verification code is ' in line:
self.OTP = re.findall(RE_TIME_STAMP_PATTERN, line)[0]
break
self.log.info("OTP:",self.OTP)
return self.OTP
This question already has an answer here:
How to read email using Python 3
(1 answer)
Closed 3 years ago.
I want to only print the sender name and message of a received gmail in Python. I tried the code given below. Please help me with that.
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('raskarakash2017#gmail.com', '02426236032')
mail.list()
mail.select('inbox')
typ, data = mail.search(None, 'ALL')
for num in data[0].split():
typ, data = mail.fetch(num, '(RFC822)')
print ('Message %s\n%s\n' % (num, data[0][1]))
mail.close()
mail.logout()
This code prints the whole information of the gmail, but I don't need that.
I think you are looking for it:
import imaplib
import email
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('raskarakash2017#gmail.com', '02426236032')
mail.list()
mail.select('inbox')
typ, data = mail.search(None, 'ALL')
for num in data[0].split():
typ, data = mail.fetch(num, '(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
varSubject = msg['subject']
varFrom = msg['from']
#remove the brackets around the sender email address
varFrom = varFrom.replace('<', '')
varFrom = varFrom.replace('>', '')
#add ellipsis (...) if subject length is greater than 35 characters
if len( varSubject ) > 35:
varSubject = varSubject[0:32] + '...'
print '[' + varFrom.split()[-1] + '] ' + varSubject
mail.close()
mail.logout()
Details are here : link
While am trying to parse the body of an email, the body will get as
VCBJTkZPUk1BVElPTjwvdGQ+Cgk8L3RyPgoJPHRyPjx0ZD4mbmJzcDs8L3RkPjwvdHI+Cgk8dHI+
And when I try to decode it separately, it works successfully
import base64
data="VCBJTkZPUk1BVElPTjwvdGQ+Cgk8L3RyPgoJPHRyPjx0ZD4mbmJzcDs8L3RkPjwvdHI+Cgk8dHI+"
print(base64.b64decode((data)))
Output:
b'T INFORMATION</td>\n\t</tr>\n\t<tr><td> </td></tr>\n\t<tr>'
But while i tried the same in my mail parsing script, it doesnt works
try:
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(FROM_EMAIL,FROM_PWD)
mail.select('inbox')
type, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()
first_email_id = int(id_list[0])
latest_email_id = int(id_list[-1])
print(id_list)
print(first_email_id)
print(latest_email_id)
for i in data[0].decode().split(' '):
print(i)
typ, data = mail.fetch(i, '(RFC822)' )
data=(data[0][1])
print(base64.b64decode(data))
except Exception as e:
print(str(e))
The output is getting as follows:
b"\r\xe9b\xbd\xea\xdeu:-\xa2|\xa9\xae\x8b^rH&j)\\\"
Is there any way to decode this ?
I have this code (below) that shows me all emails in my email account. It also shows the whole email, including all the metadata (which I dont want). Is there a way to just print the To, From, Subject and Message only? This is in Python as well. Thanks.
Code:
import getpass, imaplib
import os
email = raw_input('Email: ')
password = getpass.getpass()
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
print('Logging in as ' + email + '...')
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
print ('Message %s\n%s\n' % (num, data[0][1]))
M.close()
M.logout()
You can use email.parser.Parser() from standard module to parse mail and get headers
from __future__ import print_function
import imaplib
import getpass
import os
from email.parser import Parser
email = raw_input('Email: ')
password = getpass.getpass()
print('Logging in as', email, '...')
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
#print ('Message %s\n%s\n' % (num, data[0][1]))
header = Parser().parsestr(data[0][1])
print('From:', header['From'])
print('To:', header['To'])
print('Subject:', header['Subject'])
print('Body:')
for part in header.get_payload():
print(part.as_string()[:150], '.....')
#break # to test only first message
M.close()
M.logout()
For anyone else who wants to know, this is the working code:
from __future__ import print_function
import imaplib
import getpass
import os
from email.parser import Parser
email = raw_input('Email: ')
password = getpass.getpass()
print('Logging in as', email, '...\n')
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
## To view whole email, uncomment next line
## print ('Message %s\n%s\n' % (num, data[0][1]))
header = Parser().parsestr(data[0][1])
print('To:', header['Delivered-To'])
print('From:', header['From'])
print('Subject:', header['Subject'])
print('Body:', header.get_payload(), '\n')
M.close()
M.logout()
Hope this helps :) Big thanks to #furas!
I have been working on this and am missing the mark.
I am able to connect and get the mail via imaplib.
msrv = imaplib.IMAP4(server)
msrv.login(username,password)
# Get mail
msrv.select()
#msrv.search(None, 'ALL')
typ, data = msrv.search(None, 'ALL')
# iterate through messages
for num in data[0].split():
typ, msg_itm = msrv.fetch(num, '(RFC822)')
print msg_itm
print num
But what I need to do is get the body of the message as plain text and I think that works with the email parser but I am having problems getting it working.
Does anyone have a complete example I can look at?
Thanks,
To get the plain text version of the body of the email I did something like this....
xxx= data[0][1] #puts message from list into string
xyz=email.message_from_string(xxx)# converts string to instance of message xyz is an email message so multipart and walk work on it.
#Finds the plain text version of the body of the message.
if xyz.get_content_maintype() == 'multipart': #If message is multi part we only want the text version of the body, this walks the message and gets the body.
for part in xyz.walk():
if part.get_content_type() == "text/plain":
body = part.get_payload(decode=True)
else:
continue
Here is a minimal example from the docs:
import getpass, imaplib
M = imaplib.IMAP4()
M.login(getpass.getuser(), getpass.getpass())
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
print 'Message %s\n%s\n' % (num, data[0][1])
M.close()
M.logout()
In this case, data[0][1] contains the message body.