How to search specific e-mail using python imaplib.IMAP4.search() - python

import imaplib,time
T=time.time()
M=imaplib.IMAP4_SSL("imap.gmail.com")
M.login(user,psw)
M.select()
typ, data = M.search(None, 'UNSEEN SINCE T')
for num in string.split(data[0]):
try :
typ, data=M.fetch(num,'(RFC822)')
msg=email.message_from_string(data[0][1])
print msg["From"]
print msg["Subject"]
print msg["Date"]
except Exception,e:
print "hello world"
M.close()
M.logout()
ERROR:
Traceback (most recent call last):
File "mail.py", line 37, in <module>
typ, data = M.search(None, 'UNSEEN SINCE T')
File "/usr/lib/python2.7/imaplib.py", line 627, in search
typ, dat = self._simple_command(name, *criteria)
File "/usr/lib/python2.7/imaplib.py", line 1070, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/usr/lib/python2.7/imaplib.py", line 905, in _command_complete
raise self.error('%s command error: %s %s' % (name, typ, data))
imaplib.error: SEARCH command error: BAD ['Parse command error']
I want to search e-mail since a specific time . Here is my code .But it runs error.Can you give me some advice on how to solve it.thanks a lot!

import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('test#gmail.com', 'test')
mail.list()
# Out: list of "folders" aka labels in gmail.
mail.select("inbox") # connect to inbox.
result, data = mail.search(None, '(FROM "anjali sinha" SUBJECT "test")' )
ids = data[0] # data is a list.
id_list = ids.split() # ids is a space separated string
latest_email_id = id_list[-1] # get the latest
result, data = mail.fetch(latest_email_id, "(RFC822)") # fetch the email body (RFC822) for the given ID
raw_email = data[0][1] # here's the body, which is raw text of the whole email
# including headers and alternate payloads
print raw_email
this eventually worked for me
specyfing labels with conditions

UPDATE: OP has imported imaplib but it's still generating an error message which has not been put into the question.
--
This won't work because you have not imported imaplib.
Try
import smtplib, time, imaplib
instead of
import smtplib, time

Related

how to fix output error in emailcheck python script

iam trying to use a python script to do listener on gmail to get incoming emails with spicific criteria so far everything work well the script so listener and wait for the expected emai but when the email is recived i goten the following error any help will be welcome iam too beginer . already thanks.
the script used:
import time
from itertools import chain
import email
import imaplib
imap_ssl_host = 'imap.gmail.com' # imap.mail.yahoo.com
imap_ssl_port = 993
username = 'USERNAME or EMAIL ADDRESS'
password = 'PASSWORD'
# Restrict mail search. Be very specific.
# Machine should be very selective to receive messages.
criteria = {
'FROM': 'PRIVILEGED EMAIL ADDRESS',
'SUBJECT': 'SPECIAL SUBJECT LINE',
'BODY': 'SECRET SIGNATURE',
}
uid_max = 0
def search_string(uid_max, criteria):
c = list(map(lambda t: (t[0], '"'+str(t[1])+'"'), criteria.items())) + [('UID', '%d:*' % (uid_max+1))]
return '(%s)' % ' '.join(chain(*c))
# Produce search string in IMAP format:
# e.g. (FROM "me#gmail.com" SUBJECT "abcde" BODY "123456789" UID 9999:*)
def get_first_text_block(msg):
type = msg.get_content_maintype()
if type == 'multipart':
for part in msg.get_payload():
if part.get_content_maintype() == 'text':
return part.get_payload()
elif type == 'text':
return msg.get_payload()
server = imaplib.IMAP4_SSL(imap_ssl_host, imap_ssl_port)
server.login(username, password)
server.select('INBOX')
result, data = server.uid('search', None, search_string(uid_max, criteria))
uids = [int(s) for s in data[0].split()]
if uids:
uid_max = max(uids)
# Initialize `uid_max`. Any UID less than or equal to `uid_max` will be ignored subsequently.
server.logout()
# Keep checking messages ...
# I don't like using IDLE because Yahoo does not support it.
while 1:
# Have to login/logout each time because that's the only way to get fresh results.
server = imaplib.IMAP4_SSL(imap_ssl_host, imap_ssl_port)
server.login(username, password)
server.select('INBOX')
result, data = server.uid('search', None, search_string(uid_max, criteria))
uids = [int(s) for s in data[0].split()]
for uid in uids:
# Have to check again because Gmail sometimes does not obey UID criterion.
if uid > uid_max:
result, data = server.uid('fetch', uid, '(RFC822)') # fetch entire message
msg = email.message_from_string(data[0][1])
uid_max = uid
text = get_first_text_block(msg)
print 'New message :::::::::::::::::::::'
print text
server.logout()
time.sleep(1)
the result:
C:\Users\PC Sony>"C:/Users/PC Sony/AppData/Local/Programs/Python/Python38/python.exe" "c:/Users/PC Sony/Desktop/elzero/elzero/# import PySimpleGUI.py"
Traceback (most recent call last):
File "c:/Users/PC Sony/Desktop/elzero/elzero/# import PySimpleGUI.py", line 68, in <module>
result, data = server.uid('fetch', uid, '(RFC822)') # fetch entire message
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 881, in uid
typ, dat = self._simple_command(name, command, *args)
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1205, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "C:\Users\PC Sony\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 963, in _command
data = data + b' ' + arg
TypeError: can't concat int to bytes
result, data = server.uid('fetch', uid, '(RFC822)')
should be changed to
result, data = server.uid('fetch', str(uid), '(RFC822)')
arguments should be of type string or bytes.
source code in imaplib.py
for arg in args:
if arg is None: continue
if isinstance(arg, str):
arg = bytes(arg, "ASCII")
data = data + b' ' + arg

How can I make this python2 function that reads emails run in python3?

I've been following the guide here on how to read emails in python
https://codehandbook.org/how-to-read-email-from-gmail-using-python/
import smtplib
import time
import imaplib
import email
ORG_EMAIL = "#gmail.com"
FROM_EMAIL = "mygmail" + ORG_EMAIL
FROM_PWD = "mypassword"
SMTP_SERVER = "imap.gmail.com"
SMTP_PORT = 993
def read_email_from_gmail():
mail = imaplib.IMAP4_SSL(SMTP_SERVER)
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])
for i in range(latest_email_id,first_email_id, -1):
typ, data = mail.fetch(i, '(RFC822)' )
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
email_subject = msg['subject']
email_from = msg['from']
print('From : ' + email_from + '\n')
print('Subject : ' + email_subject + '\n')
This code was made for python2 and running it with python2 works perfectly, but I would like to work with python3 and so i tried to translate the code. Firstly, I changed all the instances of print foobar to print(foobar).
However Im getting the error 'TypeError: can't concat bytes to int'
Traceback (most recent call last):
File "mymail.py", line 37, in <module>
read_email_from_gmail()
File "mymail.py", line 26, in read_email_from_gmail
typ, data = mail.fetch(i, '(RFC822)' )
File "/usr/lib/python3.5/imaplib.py", line 518, in fetch
typ, dat = self._simple_command(name, message_set, message_parts)
File "/usr/lib/python3.5/imaplib.py", line 1180, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/usr/lib/python3.5/imaplib.py", line 945, in _command
data = data + b' ' + arg
TypeError: can't concat bytes to int
I'm not too familiar with this error. But using the original code from the text in python2 works perfectly with no issues. I kind of understand the error it's saying it can't concatenate bytes with numerics. However Im not sure why this error would occur going from python2 to python3.

How to read email content in Python 3

I've tried many code to access and read email content, for example, about Gmail i only can do authentication and with Outlook i have code that can read email but it's encrypted...but now it only access email and doesn't output with encrypted information. So i need help to solve this. Thanks
Here's the code:
import imaplib
import base64
email_user = input('Email: ')
email_pass = input('Password: ')
M = imaplib.IMAP4_SSL('imap-mail.outlook.com', 993)
M.login(email_user, email_pass)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
num1 = base64.b64decode(num1)
data1 = base64.b64decode(data)
print('Message %s\n%s\n' % (num, data[0][1]))
M.close()
M.logout()
I've checked through your code anyway, and there are a couple of comments. The first one is that commas seem to have been stripped out when you pasted the code in here. I've tried to put them back, so check that my code does match yours. Remember that without access to Outlook, I can't test my suggestions.
import imaplib
import base64
email_user = input('Email: ')
email_pass = input('Password: ')
M = imaplib.IMAP4_SSL('imap-mail.outlook.com', 993)
M.login(email_user, email_pass)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)') # data is being redefined here, that's probably not right
num1 = base64.b64decode(num1) # should this be (num) rather than (num1) ?
data1 = base64.b64decode(data)
print('Message %s\n%s\n' % (num, data[0][1])) # don't you want to print num1 and data1 here?
M.close()
M.logout()
Assuming that's correctly reconstituted, you call your message list data on line 10, but then re-assign the results of calling fetch() to data on line 13.
On line 14, you decode num1, which hasn't been defined yet. I'm not sure that the numbers need decoding though, that seems a bit strange.
On line 16, you're printing the encoded values, not the ones you've decoded. I think you may want something like
import imaplib
import base64
email_user = input('Email: ')
email_pass = input('Password: ')
M = imaplib.IMAP4_SSL('imap-mail.outlook.com', 993)
M.login(email_user, email_pass)
M.select()
typ, message_numbers = M.search(None, 'ALL') # change variable name, and use new name in for loop
for num in message_numbers[0].split():
typ, data = M.fetch(num, '(RFC822)')
# num1 = base64.b64decode(num) # unnecessary, I think
print(data) # check what you've actually got. That will help with the next line
data1 = base64.b64decode(data[0][1])
print('Message %s\n%s\n' % (num, data1))
M.close()
M.logout()
Hope that helps.
use data[0][1].decode('utf-8')
It will work. I was also facing the same problem. It worked for me.
You just need to enable the less secure apps in your Gmail account if it is not enabled you will get an authentication error even if your code is all right. I was also getting so I researched and got this error

Why is there a Imaplib.abort EOF error after 10 correctly crawled messages?

I need to Copy every mail from my 'inbox'+sub folders to 2 new folders, one for short subjects and another for the long ones.
The crawl always abort after the 10th mail, and I need to repeat the process for 10 000 of them.. if someone had a solution I would be very grateful, here is my code :
import imaplib, getpass, re, email
pattern_uid = re.compile(b'\d+ \(UID (?P<uid>\d+)\)')
def parse_mailbox(data):
flags, b, c = data.partition(' ')
separator, b, name = c.partition(' ')
return (flags, separator.replace('"', ''), name.replace('"', ''))
def connect(email):
imap = imaplib.IMAP4_SSL("outlook.office365.com",993)
password = "*******"
imap.login(email, password)
return imap
def disconnect(imap):
imap.logout()
def parse_uid(data):
match = pattern_uid.match(data)
return match.group('uid')
if __name__ == '__main__':
imap = connect('************')
rv,data = imap.list()
# print(data)
if rv == 'OK':
for mbox in data:
flags,separator,name = parse_mailbox(bytes.decode(mbox))
print(name)
if 'HasNoChildren' in flags and '2' in name:
name = name.replace('/ Inbox','Inbox')
rv2, data2 = imap.select('"'+name+'"')
print(rv2)
resp, items = imap.search(None, 'All')
email_ids = items[0].split()
# print(items)
print(email_ids)
# Assuming that you are moving the latest email.
# for mail in email_ids:
# if
print(len(email_ids))
for i in range(0,len(email_ids)):
print('NOUVEAU MESSAGE \n')
print(email_ids[i])
resp, data = imap.fetch(email_ids[i], "(UID)")
rv,sujet = imap.fetch(email_ids[i],("(RFC822)"))
varSubject= ""
for response_part in sujet:
if isinstance(response_part, tuple):
msg = email.message_from_bytes(response_part[1])
varSubject = msg['subject']
break
print(varSubject)
print(i)
print(type(data[0]))
print(data[0])
try :
msg_uid = parse_uid(data[0])
except AttributeError:
continue
num = ""
dossier = ""
if len(varSubject) <= 20:
dossier = 'INBOX/sujets_courts'
imap.create(dossier)
elif len(varSubject) > 20:
dossier = 'INBOX/sujets_longs'
imap.create(dossier)
print(varSubject+'******'+dossier)
print(msg_uid)
result = imap.uid('COPY', msg_uid, dossier)
# if result[0] == 'OK':
# mov, data = imap.uid('STORE', msg_uid , '+FLAGS', '(\Deleted)')
# imap.expunge()
disconnect(imap)
The email and the password are substituted by '****'
Thanks a lot :)
console output :
Traceback (most recent call last):
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1011, in _command_complete
typ, data = self._get_tagged_response(tag)
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1131, in _get_tagged_response
self._get_response()
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1039, in _get_response
resp = self._get_line()
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1143, in _get_line
raise self.abort('socket error: EOF')
imaplib.abort: socket error: EOF
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "movemail.py", line 44, in <module>
resp, data = imap.fetch(email_ids[i], "(UID)")
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 526, in fetch
typ, dat = self._simple_command(name, message_set, message_parts)
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1188, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "C:\Users\lschaub\AppData\Local\Programs\Python\Python36-32\lib\imaplib.py", line 1013, in _command_complete
raise self.abort('command: %s => %s' % (name, val))
imaplib.abort: command: FETCH => socket error: EOF
OK I figured out that the problem comes from the creation of an already-created folder, but I could not find any folder.exists() look-a-like method in the imaplib doc...

How can i download a gmail attachment based on subject? ERROR : "No route to host" when connecting to imap.gmail.com

This is my first python code, so please excuse me.
This is what i wrote.
import imaplib
import email
import os
import getpass
email = 'br******#******.com'
password = getpass.getpass('Enter your password: ')
mail = 'imap.gmail.com'
flag = '(RFC822)'
svdir = 'c:/Users/'
m = imaplib.IMAP4(mail)
m.login(email,password)
m.select('inbox')
typ, msgs = m.search(None, 'subject:resume has:attachment')
msgs = msgs[0].split()
for emailid in msgs:
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1]
mail = email.message_from_string(email_body)
if mail.get_content_maintype() != 'multipart':
continue
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename=part.get_filename()
if filename is not None:
sv_path = os.path.join(svdir, filename)
if not os.path.isfile(sv_path):
print (sv_path)
fp = open(sv_path, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
But i'm getting this as error.
Traceback (most recent call last):
File "/Users/Documents/Fetch_Attchments.py", line 12, in <module>
m = imaplib.IMAP4(mail)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 197, in __init__
self.open(host, port)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 294, in open
self.sock = self._create_socket()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/imaplib.py", line 284, in _create_socket
return socket.create_connection((self.host, self.port))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 711, in create_connection
raise err
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/socket.py", line 702, in create_connection
sock.connect(sa)
OSError: [Errno 65] No route to host
I filtering messages by subject and getting the attachment saved to particular location. Kindly note that the subject condition will filter only one message.
Gmail does not allow connecting on a plain text port. SSL/TLS is required.
You will need:
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)

Categories

Resources