Friday, May 31, 2013

GMail cleanup

This Python script cleans All Mail GMail folder by moving emails to Trash if there are more than 33 emails from same sender or email is more than 55 days old (values can be adjusted by editing code). IMAP must be enabled in order to work.
#!/usr/bin/env python
from datetime import datetime, timedelta
from email.utils import parsedate, parseaddr
import imaplib
import re
import socket

socket.setdefaulttimeout(30)

IMAP_SERVER = 'imap.gmail.com'
IMAP_PORT = 993


def main():
    clean('email1@gmail.com', 'password1')
    clean('email2@gmail.com', 'password2')


def clean(user, pwd):
    mbox = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
    rc, resp = mbox.login(user, pwd)
    print rc, resp
    r, data = mbox.select("[Gmail]/All Mail")
    assert r == 'OK'
    r, data = mbox.expunge()
    assert r == 'OK'
    r, (ids,) = mbox.search(None, 'ALL')
    assert r == 'OK'
    r, data = mbox.fetch(
        '1:*',
        '(INTERNALDATE FLAGS BODY.PEEK[HEADER.FIELDS (FROM)])')
    assert r == 'OK'
    threads = {}
    for row in data:
        if row == ')':
            continue
        uid_date, subject = row
        m = re.compile(
            r'(\d+) \(INTERNALDATE "(.*)" FLAGS \((.*)\) '
            'BODY\[HEADER\.FIELDS\ \(FROM\)\]\ \{\d+\}').match(uid_date)
        assert m, uid_date
        uid, date, flags = m.groups()
        if '\\Flagged' in flags:
            continue
        date = parsedate(date)
        uid = int(uid)
        _, frm = parseaddr(subject)
        threads.setdefault(frm, []).append((date, uid))
    uids = []
    for key, lst in sorted(threads.items(), key=lambda x: len(x[1])):
        # date descending
        lst.sort(reverse=True)
        for no, (date, uid) in enumerate(lst):
            if no > 33 or datetime.now() - datetime(*date[:6]) > timedelta(55):
                print key, date, uid
                uids.append(uid)
    # uids.sort(reverse=True)
    print len(uids)
    if uids:
        r, data = mbox.store(
            #','.join(str(uid) for uid in uids), '+FLAGS', '\\Deleted')
            ','.join(str(uid) for uid in uids), '+X-GM-LABELS', '\\Trash')
        assert r == 'OK'
    r, data = mbox.expunge()
    assert r == 'OK'
    print 'ok'
    mbox.close()
    mbox.logout()


if __name__ == '__main__':
    main()