Skip to content

Instantly share code, notes, and snippets.

@nitrocode
Last active December 15, 2015 14:58
Show Gist options
  • Select an option

  • Save nitrocode/50690675c4b91cc3c9f5 to your computer and use it in GitHub Desktop.

Select an option

Save nitrocode/50690675c4b91cc3c9f5 to your computer and use it in GitHub Desktop.
Poll imap for a particular subject and download its attachment
#!/usr/bin/python
# Polls imap server, searches for a string in an unread email's subject, and downloads its attachment.
#
# Use case:
# Someone refuses or does not know how to save an attachment to a webserver so he/she sends
# it via email and so the imap server has to be polled, the email has to be found, and then the attachment
# can be downloaded
#
# Todo: Finish class
# Todo: Commandline arguments
#
# little help from my anonymous friends:
# - seen flag: http://stackoverflow.com/questions/2251977/python-imap-and-gmail-mark-messages-as-seen
# - save attachments from gmail: https://gist.github.com/baali/2633554
# creds
server = "outlook.office365.com"
username = ""
password = ""
# folder to search
search_folder = "INBOX"
# subject search str
search_str = "NPI File"
# number of emails to search for before quitting, limit=0 will search all
limit = 1
# relative area of directory to save attachments to
detach_dir = '/opt/myfiles/'
# directory to save attachments to inside the detach_dir
dir_to_save = 'sampleData'
# overwrite existing files or save as filename.1, filename.2, etc
overwrite = True
import imaplib
import email
import email.header
import os
import datetime
# future class
class ImapPoller:
def __init__(self, server, username, password):
conn = imaplib.IMAP4_SSL(server)
conn.login(username, password)
def select(self, folder="ALL", unseen=True):
pass
def search(self, subject=None, sentfrom=None, sentto=None, attachmentName=None, dlAttachments=False, markAsRead=False):
pass
# create directory if it doesnt exist
if dir_to_save not in os.listdir(detach_dir):
os.mkdir(dir_to_save)
conn = imaplib.IMAP4_SSL(server)
conn.login(username, password)
rv, mailboxes = conn.list()
conn.select(search_folder)
rv, data = conn.search(None, "ALL")
#rv, data = conn.search(None, "UNSEEN")
found = 0
emaillist = data[0].split()
for num in reversed(emaillist):
rv, msgdata = conn.fetch(num, '(BODY.PEEK[])')
#rv, data = conn.fetch(num, '(RFC822)')
if rv != 'OK':
print "ERROR getting message", num
msg = email.message_from_string(msgdata[0][1])
decode = email.header.decode_header(msg['Subject'])[0]
subject = unicode(decode[0], 'utf-8')
#print num, subject
# skip if search_str isn't in subject
# TODO: turn this into a regular expression?
if not search_str in subject:
continue
print '========================================================='
print 'Message %s: %s' % (num, subject)
print 'Raw Date:', msg['Date']
for part in msg.walk():
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join(detach_dir, 'attachments', fileName)
if not overwrite:
newPath = filePath
iNew = 1
while os.path.isfile(newPath):
newPath = filePath + "." + str(iNew)
iNew += 1
filePath = newPath
print("Downloading... " + filePath)
fp = open(filePath, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
# mark as seen
#conn.store(num, '+FLAGS', '\Seen')
found += 1
if limit > 0 and found >= limit:
print("Found " + str(found) + " email(s)")
break
conn.close()
conn.logout()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment