name 'search' is not defined In Sublime Texte 3 (search of IMAP) - python

i want to downloap PJ from an email so i write this code
import imaplib, email, os
from time import sleep
user='my_email'
password = 'secret'
imap_url = 'Outlook.office365.com'
con = imaplib.IMAP4_SSL(imap_url)
con.login(user,password)
def get_attachments(msg):
for part in msg.walk():
if part.get_content_maintype()=='multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join(attachment_dir, fileName)
with open(filePath,'wb') as f:
f.write(part.get_payload(decode=True))
attachment_dir = "D:/TOUT/DATANALYSE/email_python/attachement/"
never_stop = True
while never_stop:
last_email_id = search('FROM', "kvaccarin#datanalyse.fr", con)[0].split()[-1]
typ, data = con.fetch(last_email_id, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
get_attachments(msg)
time.sleep(12*60*60)
this code works when i run on Jupyter but when i want to run this code with Sublime Texte i have this error:
NameError: name 'search' is not defined
This fonction search() is not the fonction from re but it's the fonction from IMAP
Someone know how to fix it?

It's the beginning of the answers... but it's something!
Thanks to Max, I understand the error on the first Question, So to fix it I define a new function search_data():
def search_data(key,value,con):
result, data = con.search(None,key,'"{}"'.format(value))
return data
and when I run the same code with the use of this function like that:
import imaplib, email, os
from time import sleep
user='my_email'
password = 'secret'
imap_url = 'Outlook.office365.com'
con = imaplib.IMAP4_SSL(imap_url)
con.login(user,password)
def get_attachments(msg):
for part in msg.walk():
if part.get_content_maintype()=='multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join(attachment_dir, fileName)
with open(filePath,'wb') as f:
f.write(part.get_payload(decode=True))
def search_data(key,value,con):
result, data = con.search(None,key,'"{}"'.format(value))
return data
attachment_dir = "D:/TOUT/DATANALYSE/email_python/attachement/"
never_stop = True
while never_stop:
last_email_id = search_data('FROM', "kvaccarin#datanalyse.fr", con)[0].split()[-1]
typ, data = con.fetch(last_email_id, '(RFC822)')
msg = email.message_from_bytes(data[0][1])
get_attachments(msg)
time.sleep(12*60*60)
there still have an error:
error: command SEARCH illegal in state AUTH, only allowed in states SELECTED
I know it's the beginning of the answer but it perhaps helps to have the entire answer!

Related

how to resolve' NameError: name 'imaplib' is not defined' (python poetry)

I spend a lot of time resolving this problem but I couldn't,
So I want someone to help me.
I'm beginner for python and use poetry.
When I import imaplib I always get an error.
' NameError: name 'imaplib' is not defined'
I know I don't need to install imaplib'.
what should I do then?
This below is my code.
Thank you for your reading and kindness.
I appreciate it.
import imaplib
import email
host = 'imap.gmail.com'
username = 'xxxxxxx#gmail.com'
password = 'xxxxxxxx'
mail = imaplib.IMAP4_SSL(host)
mail.login(username, password)
mail.select('inbox')
_, search_data = mail.search(None, 'UNSEEN')
for num in search_data[0].split():
# print(num)
_, data = mail.fetch(num, '(RFC822)')
# print(data[0])
_, b = data[0]
email_message = email.message_from_bytes(b)
#email_message = email.message_from_string(b)
# print(email_message)
for part in email_message.walk():
if part.get_content_type() == 'text/plain' or part.get_content_type() == 'text/html':
body = part.get_payload(decode=True)
print(body)
print(search_data)

Fetch all emails from gmail of a particular label

I want to fetch all the emails from gmail of a particular label called important. I am using imaplib and python 2.
Below is my code,
import email, getpass, imaplib, os
detach_dir = '.'
user = raw_input("Enter your GMail username:")
pwd = getpass.getpass("Enter your password: ")
# connecting to the gmail imap server
m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login(user,pwd)
m.select("important")
resp, items = m.search(None, "ALL")
items = items[0].split()
print len(items)
for emailid in items:
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
print "["+mail["From"]+"] :" + mail["Subject"]
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = mail["From"] + "_hw1answer"
att_path = os.path.join(detach_dir, filename)
if not os.path.isfile(att_path) :
fp = open(att_path, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
The error is showing,
imaplib.error: command SEARCH illegal in state AUTH, only allowed in states SELECTED
But, if I use INBOX then it is working.
Working when m.select("inbox")
What is the recommended way to achieve it ?
m.select("important") failed.
If you want the special starred folder, it is probably named "[Gmail]/Important". Use the list() command to find the names used by the server.

Python 3 Zip Password Cracker

I am working on a simple zip file password cracker for a school project, and I need it to display the password once it cracks it from the dictionary word list. Whenever I run it, it only extracts the file, and doesn't print anything. How can I fix this to also show the password? Here is my code.
import optparse
import zipfile
from threading import Thread
def extract_zip(zFile, password):
try:
password = bytes(password.encode('utf-8'))
zFile.extractall(pwd=password)
print ("[+] Password Found: " + password + '\n')
except:
pass
def Main():
parser = optparse.OptionParser("useage &prog "+\
"-f <zipfile> -d <dictionary>")
parser.add_option('-f', dest='zname', type='string',\
help='specify zip file')
parser.add_option('-d', dest='dname', type='string',\
help='specify dictionary file')
(options, arg) = parser.parse_args()
if (options.zname == None) | (options.dname == None):
print (parser.usage)
exit(0)
else:
zname = options.zname
dname = options.dname
zFile = zipfile.ZipFile(zname)
passFile = open(dname)
for line in passFile.readlines():
password = line.strip('\n')
t = Thread(target=extract_zip, args=(zFile, password))
t.start()
if __name__ == '__main__':
Main()
The problem is that you're trying to print the encoded password instead of the original password. You can't concatenate bytes to a string. So print the original password, not the result of bytes().
And instead of extracting all the files from the archive, use testzip() to test whether you can decrypt them. But to do this, each thread needs its own ZipFile object. Otherwise they'll set the password used by another thread.
def extract_zip(filename, password):
with ZipFile(filename) as zFile:
try:
password_encoded = bytes(password.encode('utf-8'))
zFile.setpassword(password_encoded)
zFile.testzip()
print ("[+] Password Found: " + password + '\n')
except:
pass
Then change the caller to pass the filename to the thread, not zFile.
import zipfile
from tqdm import tqdm
def chunck(fd,size=65536):
while 1:
x=fd.read(size)
if not x:
break
yield x
def file_len(path):
with open(path,'r',encoding='utf-8',errors='ignore') as fd:
return sum(x.count('\n') for x in chunck(fd))
def linear_zip_crack(zip_path,pwd_path):
ln=file_len(pwd_path)
zp=zipfile.ZipFile(zip_path)
with open(pwd_path,'rb') as fd:
for x in tqdm(fd,total=ln,unit='x'):
try:
zp.extractall(pwd=x.strip())
except:
continue
else:
print(f'pwd={x.decode().strip()}')
exit(0)
print('Not found')
linear_zip_crack('spn.zip','pwds.txt')

Python IMAP4 Don't Mark messages as read

I have a Python script to move messages with a certain subject. The messages get marked as read and I don't want them to be marked as read. What part of the script marks them as read and how do I make it not mark as read?
Also, I'm not too sure what I am doing yet, so if there is any redundant code or errors please let me know.
import getpass
from Crypto.Hash import MD5
import sys
import imaplib
import email
import re
password = getpass.getpass()
match = "redacted"
username = "redacted"
dest = "000"
pattern_uid = re.compile('\d+ \(UID (?P<uid>\d+)\)')
def md5(message):
hash = MD5.new()
hash.update(message)
return hash.hexdigest()
md5 = md5(password)
if md5 == match:
pass
else:
print "Mismatch"
sys.exit()
M = imaplib.IMAP4_SSL("mail.redacted.com", 993)
M.login(username, password)
M.select()
typ, data = M.search(None, 'ALL')
M.select('Inbox')
msgs = M.search(None, 'ALL')[1]
num_messages = len(msgs[0].split())
num_messages += 1
def parse_uid(data):
match = pattern_uid.match(data)
return match.group('uid')
for i in range(1, num_messages):
try:
typ, msg_data = M.fetch(str(i), '(RFC822)')
except:
pass
for response_part in msg_data:
if isinstance(response_part, tuple):
UID = M.fetch(str(i),'UID')
UID = UID[1]
try:
UID = parse_uid(UID[0])
except:
pass
msg = email.message_from_string(response_part[1])
for header in [ 'subject' ]:
if msg[header] == "Redacted":
result = M.uid('COPY', UID, dest)
if result[0] == 'OK':
mov, data = M.uid('STORE', UID, '+FLAGS', '(\Deleted)')
M.expunge()
M.close()
M.logout()
typ, msg_data = M.fetch(str(i), '(RFC822)')
Fetching a message body marks it as read. You'll want to use BODY.PEEK[].
Although, I don't know why you're fetching the whole message just to copy it. Why don't you just fetch the headers? Use BODY.PEEK[HEADERS].

Checking email with Python

I am interested to trigger a certain action upon receiving an email from specific
address with specific subject. In order to be able to do so I need to implement
monitoring of my mailbox, checking every incoming mail (in particular, i use gmail).
what is the easiest way to do that?
Gmail provides the ability to connect over POP, which you can turn on in the gmail settings panel. Python can make connections over POP pretty easily:
import poplib
from email import parser
pop_conn = poplib.POP3_SSL('pop.gmail.com')
pop_conn.user('username')
pop_conn.pass_('password')
#Get messages from server:
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
for message in messages:
print message['subject']
pop_conn.quit()
You would just need to run this script as a cron job. Not sure what platform you're on so YMMV as to how that's done.
Gmail provides an atom feed for new email messages. You should be able to monitor this by authenticating with py cURL (or some other net library) and pulling down the feed. Making a GET request for each new message should mark it as read, so you won't have to keep track of which emails you've read.
While not Python-specific, I've always loved procmail wherever I could install it...!
Just use as some of your action lines for conditions of your choice | pathtoyourscript (vertical bar AKA pipe followed by the script you want to execute in those cases) and your mail gets piped, under the conditions of your choice, to the script of your choice, for it to do whatever it wants -- hard to think of a more general approach to "trigger actions of your choice upon receipt of mails that meet your specific conditions!! Of course there are no limits to how many conditions you can check, how many action lines a single condition can trigger (just enclose all the action lines you want in { } braces), etc, etc.
People seem to be pumped up about Lamson:
https://github.com/zedshaw/lamson
It's an SMTP server written entirely in Python. I'm sure you could leverage that to do everything you need - just forward the gmail messages to that SMTP server and then do what you will.
However, I think it's probably easiest to do the ATOM feed recommendation above.
EDIT: Lamson has been abandoned
I found a pretty good snippet when I wanted to do this same thing (and the example uses gmail). Also check out the google search results on this.
I recently solved this problem by using procmail and python
Read the documentation for procmail. You can tell it to send all incoming email to a python script like this in a special procmail config file
:0:
| ./scripts/ppm_processor.py
Python has an "email" package available that can do anything you could possibly want to do with email. Read up on the following ones....
from email.generator import Generator
from email import Message
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.mime.multipart import MIMEMultipart
https://developers.google.com/gmail/gmail_inbox_feed
Says you have to have a corporate Gmail, but I have come to find that you can read Gmail free versions without issues. I use this code to get my blood pressure results I email or text to a gmail address.
from email.header import decode_header
from datetime import datetime
import os
import pandas as pd
import plotly.graph_objs as go
import plotly
now = datetime.now()
dt_string = now.strftime("%Y.%m.%d %H:%M:%S")
print("date_time:", dt_string)
email_account = '13123#gmail.com'
email_password = '131231231231231231312313F'
email_server = 'imap.gmail.com'
email_port = 993
accept_emails_from = {'j1231312#gmail.com', '1312312#chase.com', '13131231313131#msg.fi.google.com'}
verbose = True
def get_emails():
email_number = 0
local_csv_data = ''
t_date = None
t_date = None
t_systolic = None
t_diastolic = None
t_pulse = None
t_weight = None
try:
mail = imaplib.IMAP4_SSL(email_server)
email_code, email_auth_status = mail.login(email_account, email_password)
if verbose:
print('[DEBUG] email_code: ', email_code)
print('[DEBUG] email_auth_status: ', email_auth_status)
mail.list()
mail.select('inbox')
# (email_code, messages) = mail.search(None, 'ALL')
(email_code, messages) = mail.search(None, '(UNSEEN)') # only get unread emails to process.
subject = None
email_from = None
for email_id in messages[0].split():
email_number += 1
email_code, email_data = mail.fetch(email_id, '(RFC822)')
for response in email_data:
if isinstance(response, tuple): # we only want the tuple ,the bytes is just b .
msg = email.message_from_bytes(response[1])
content_type = msg.get_content_type()
subject, encoding = decode_header(msg["Subject"])[0]
subject = str(subject.replace("\r\n", ""))
if isinstance(subject, bytes):
subject = subject.decode(encoding)
email_from, encoding = decode_header(msg.get("From"))[0]
if isinstance(email_from, bytes):
email_from = email_from.decode(encoding)
if content_type == "text/plain":
body = msg.get_payload(decode=True).decode()
parse_data = body
else:
parse_data = subject
if '>' in email_from:
email_from = email_from.lower().split('<')[1].split('>')[0]
if email_from in accept_emails_from:
parse_data = parse_data.replace(',', ' ')
key = 0
for value in parse_data.split(' '):
if key == 0:
t_date = value
t_date = t_date.replace('-', '.')
if key == 1:
t_time = value
if ':' not in t_time:
numbers = list(t_time)
t_time = numbers[0] + numbers[1] + ':' + numbers[2] + numbers[3]
if key == 2:
t_systolic = value
if key == 3:
t_diastolic = value
if key == 4:
t_pulse = value
if key == 5:
t_weight = value
key += 1
t_eval = t_date + ' ' + t_time
if verbose:
print()
print('--------------------------------------------------------------------------------')
print('[DEBUG] t_eval:'.ljust(30), t_eval)
date_stamp = datetime.strptime(t_eval, '%Y.%m.%d %H:%M')
if verbose:
print('[DEBUG] date_stamp:'.ljust(30), date_stamp)
print('[DEBUG] t_systolic:'.ljust(30), t_systolic)
print('[DEBUG] t_diastolic:'.ljust(30), t_diastolic)
print('[DEBUG] t_pulse:'.ljust(30), t_pulse)
print('[DEBUG] t_weight:'.ljust(30), t_weight)
new_data = str(date_stamp) + ',' + \
t_systolic + ',' + \
t_diastolic + ',' + \
t_pulse + ',' + \
t_weight + '\n'
local_csv_data += new_data
except Exception as e:
traceback.print_exc()
print(str(e))
return False, email_number, local_csv_data
return True, email_number, local_csv_data
def update_csv(local_data):
""" updates csv and sorts it if there is changes made. """
uniq_rows = 0
if os.name == 'posix':
file_path = '/home/blood_pressure_results.txt'
elif os.name == 'nt':
file_path = '\\\\uncpath\\blood_pressure_results.txt'
else:
print('[ERROR] os not supported:'.ljust(30), os.name)
exit(911)
if verbose:
print('[DEBUG] file_path:'.ljust(30), file_path)
column_names = ['00DateTime', 'Systolic', 'Diastolic', 'Pulse', 'Weight']
if not os.path.exists(file_path):
with open(file_path, 'w') as file:
for col in column_names:
file.write(col + ',')
file.write('\n')
# append the new data to file.
with open(file_path, 'a+') as file:
file.write(local_data)
# sort the file.
df = pd.read_csv(file_path, usecols=column_names)
df_sorted = df.sort_values(by=["00DateTime"], ascending=True)
df_sorted.to_csv(file_path, index=False)
# remove duplicates.
file_contents = ''
with open(file_path, 'r') as file:
for row in file:
if row not in file_contents:
uniq_rows += 1
print('Adding: '.ljust(30), row, end='')
file_contents += row
else:
print('Duplicate:'.ljust(30), row, end='')
with open(file_path, 'w') as file:
file.write(file_contents)
return uniq_rows
# run the main code to get emails.
status, emails, my_data = get_emails()
print('status:'.ljust(30), status)
print('emails:'.ljust(30), emails)
# if the new emails received then sort the files.
csv_rows = update_csv(my_data)
print('csv_rows:'.ljust(30), csv_rows)
exit(0)

Categories

Resources