#!/usr/bin/python

import imaplib
import threading

folder = 'test'
threads = 10

username = 'user1'
password = 'pass'
hostname = 'localhost'
port = 143
ssl = False

def connect():
    if ssl:
        return imaplib.IMAP4_SSL(hostname, port)
    else:
        return imaplib.IMAP4(hostname, port)
    
def upload_message(conn, folder, rfc):
    stat, result = conn.append(folder, None, None, rfc)
    return conn.untagged_responses['APPENDUID'][-1].split(' ')[1]

def delete_messages(conn, folder, ids):
    stat, result = conn.uid('STORE', ids, '+FLAGS', '(\Deleted)')
    stat, result = conn.uid('EXPUNGE', ids)

def irritate():
    rfc = open('testmail.eml').read()
    conn = connect()
    # set to 4 to see all imap commands sent
    conn.debug = 0
    conn.login(username, password)
    conn.create(folder)
    conn.select(folder)
    batch = 3
    loop = 5
    for x in xrange(loop):
        print "[%s] starting loop %d" % (threading.current_thread().name, x)
        uids = []
        for y in xrange(batch):
            uid = upload_message(conn, folder, rfc)
            print "[%s] saved message %s" % (threading.current_thread().name, uid)
            uids.append(uid)
        ids = ','.join(uids)
        delete_messages(conn, folder, ids)
        print "[%s] deleted messages: %s" % (threading.current_thread().name, ids)
    conn.logout()

def cleanup():
    conn = connect()
    conn.login(username, password)
    conn.delete(folder)
    conn.logout()

def check_folder():
    conn = connect()
    conn.login(username, password)
    stat, result = conn.select(folder)
    folder_size = int(result[0])
    stat, result = conn.uid('FETCH', '1:*', '(FLAGS)')
    try:
        result.remove(None)
    except: pass
    if folder_size:
        print "Threading test went wrong, bug found"
    else:
        print "Threading test went ok, bug not found"
    print 'Folder size: %d, messages: %r' % (folder_size, result)
    conn.logout()

if __name__ == '__main__':
    cleanup()
    jobs = []
    for _ in xrange(threads):
        jobs.append(threading.Thread(target=irritate))
    for job in jobs:
        job.start()
    print '%d threads started, waiting for them to finish' % (len(jobs))
    for job in jobs:
        job.join()
    check_folder()

        
            
