Skip to content

Instantly share code, notes, and snippets.

@paskal
Created September 25, 2015 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paskal/9e236b77e6146c1e24bf to your computer and use it in GitHub Desktop.
Save paskal/9e236b77e6146c1e24bf to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
#
# imap_cleaner.py
#
# Copyright 2012 Konstantin Shcherban <k.scherban@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Version: 0.3
# 12.10.2012
from __future__ import division
from imaplib import IMAP4_SSL
import os
import sys
import string
import socket
import getpass
import datetime
import optparse
def err_time():
print "Error! Incorrect date provided"
print "Date should be like: 11-Sep-2001"
sys.exit()
def chunks(l, n):
# yields successive n-sized chunks from l.
for i in xrange(0, len(l), n):
yield l[i:i+n]
if __name__ == '__main__':
# command line options definition
parser = optparse.OptionParser("usage: %prog [options]")
parser.add_option(
"-s", "--server", dest="mserver",
help="mail server IP/hostname")
parser.add_option(
"-p", "--port", dest="port",
help="mail server port, default 993",
default=993)
parser.add_option(
"-u", "--username", dest="muser",
help="mail account username")
parser.add_option(
"-f", "--folder", dest="mfolder",
help="mail account folder [optional] default INBOX")
parser.add_option(
"-t", "--time-before", dest="mtime",
help="search messages before this date [optional] default month defore today\nex: 11-Sep-2001")
(options, args) = parser.parse_args()
# checking mandatory options
if options.mserver is None or options.muser is None:
parser.error(
"Error! Mail server and mail user parameters are mandatory.")
# getting list of months for further date check
months = []
for i in range(1, 13):
months.append((datetime.date(2001, i, 1).strftime('%b')))
# checking time
monthbefore = (
datetime.date.today() - datetime.timedelta(365/12)).strftime("%d-%b-%Y")
if options.mtime is not None:
time_split = options.mtime.split('-')
if len(time_split) != 3:
err_time()
else:
if time_split[0].isdigit() is False:
err_time()
else:
if int(time_split[0]) < 1 or int(time_split[0]) > 32:
err_time()
elif time_split[1] not in months:
err_time()
elif time_split[2].isdigit() is False:
err_time()
else:
mtime = options.mtime
else:
mtime = monthbefore
mserver = options.mserver
muser = options.muser
password = getpass.getpass("Password: ")
# connecting now to imap server
print "Connecting to %s..." % (mserver)
# here we set default timeout to 15 seconds in order not to wait much
socket.setdefaulttimeout(15)
try:
m = IMAP4_SSL(mserver, options.port)
m.login(muser, password)
except Exception, e:
print "Error!", e
sys.exit()
print "Connected"
# here we restore timeout to 300 seconds
socket.setdefaulttimeout(300)
# trying custom folder
if options.mfolder is not None:
mfolder = options.mfolder
if m.select(mfolder)[0] == 'NO':
print "Error! Folder %s does not exist" % mfolder
sys.exit()
else:
mfolder = 'INBOX'
# selecting folder
typ, data = m.select(mfolder)
print "Folder", mfolder, "selected"
print "Searching for messages..."
# let's find some old messages
typ, [data] = m.search(None, '(BEFORE %s)' % (mtime))
try:
mcount = ','.join(data.split(' '))
except:
print "No messages found"
sys.exit()
last_message = mcount.split(',')[-1]
if not last_message:
print "Nothing to remove"
sys.exit()
print "Will be removed", last_message, "messages"
answer = raw_input("Are you sure? (y/n): ")
if answer.lower() == 'y':
print "Deleting messages..."
else:
print "Exiting"
sys.exit()
# 300 can be changed to lower or higher value, depending on server settings
# some server have restricted STORE values
"""for i in list(chunks(mcount, 300)):
num = i[0] + ":" + i[-1]
m.store(num, '+FLAGS', r'(\\Deleted)')
sys.stderr.write(
'\rdone {0:.2f}%'.format((int(i[-1])/int(mcount[-1])*100)))"""
num = "1:{0}".format(last_message)
try:
m.store(num, '+FLAGS', '\\Deleted')
except:
pass
typ, response = m.expunge()
m.expunge()
typ, [data] = m.search(None, '(BEFORE %s)' % (mtime))
# exit
print "Done"
m.close()
m.logout()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment