import imaplib, getpass, sys, re class pyMAPCopy: def __init__(self, sourceServer, targetServer, sourceUser, targetUser, sourcePassword, targetPassword): self.sourceServer = sourceServer self.targetServer = targetServer self.sourceUser = sourceUser self.targetUser = targetUser self.sourcePassword = sourcePassword self.targetPassword = targetPassword self.log = open("Log - %s.txt" % sourceUser, "w") self.messagesToCopy = 0 self.messagesCopied = 0 self.messagesFailed = 0 def start(self): self.Msource = imaplib.IMAP4(self.sourceServer) self.Msource.login(self.sourceUser, self.sourcePassword) self.Mtarget = imaplib.IMAP4(self.targetServer) self.Mtarget.login(self.targetUser, self.targetPassword) try: if not self.createFolders(): # No error returned for folder in self.folderQueue: x = "Moving folder: " + folder[2] self.response(x) self.moveFolder(folder) x = "Done moving." self.response(x) x = """ ++++++++++++++++++++++REPORT++++++++++++++++++++++ Total messages to copy: %s Messages copied: %s Messages failed to copy: %s Check the created log file for more information. ++++++++++++++++++++++++++++++++++++++++++++++++++""" % (self.messagesToCopy, self.messagesCopied, self.messagesFailed) self.response(x) finally: self.log.close() self.Msource.logout() self.Mtarget.logout() def response(self, message): print message self.log.write(message + "\n") def getListItemParts(self, listItem): i = 0 waitForClosingBracket = 0 usePart = 0 part = ["", "", "", 0] for c in listItem: if i == 0: if c == "(": waitForClosingBracket = 1 elif waitForClosingBracket: if c == ")": waitForClosingBracket = 0 else: part[0] += c elif c == " ": if usePart == 0: usePart = 1 elif usePart == 1: usePart = 2 else: part[usePart] += c else: part[usePart] += c i += 1 name = part[2] regExpInQuotes = re.compile(r'".*"') regExpContainsSpaces = re.compile(r'.*?\s+.*?') if regExpInQuotes.match(name): if not regExpContainsSpaces.match(name): name = name[1:-1] part[2] = name return part def createFolders(self): self.folderQueue = [] error = 0 eText = "" list = self.Msource.list() targetList = self.Mtarget.list() addQueue = [] for item in list[1]: if error == 0: parts = self.getListItemParts(item) self.folderQueue.append(parts) result, data = self.Msource.select(parts[2], readonly=1) if result != "OK": error = 1 eText = data[0] else: parts[3] = int(data[0]) x = "Folder: " + parts[2] + " (" + str(parts[3]) + ")" self.response(x) present = 0 for i in targetList[1]: p = self.getListItemParts(i) if p[2] == parts[2]: present = 1 if present == 0: addQueue.append(parts[2]) else: x = "Error occured: " + eText self.response(x) if error == 0: sum = 0 for parts in self.folderQueue: sum += parts[3] x = "Total messages in folders: " + str(sum) self.messagesToCopy = sum self.response(x) for folder in addQueue: x = "Creating: " + folder self.response(x) self.Mtarget.create(folder) return error def moveFolder(self, folder): if folder[3] > 0: self.Msource.select(folder[2], readonly=1) result, data = self.Msource.search(None, "ALL") sys.stdout.write("Progress: \r") i = 0 p = 0 self.messageQueue = [] regExUID = re.compile(r".*\(UID (.*)\)") for num in data[0].split(): r, UID = self.Msource.fetch(num, "(UID)") match = regExUID.match(UID[0]) if match.group(1): self.messageQueue.append(match.group(1)) del data for UID in self.messageQueue: try: self.copyMessage(UID, folder[2]) except imaplib.IMAP4.abort: sys.exc_clear() sys.stdout.write("\nConnection reset, attempting to recover.\n") try: self.Msource = imaplib.IMAP4(self.sourceServer) self.Mtarget = imaplib.IMAP4(self.targetServer) self.Msource.login(self.sourceUser, self.sourcePassword) self.Msource.select(folder[2]) self.Mtarget.login(self.targetUser, self.targetPassword) except: pass self.copyMessage(UID, folder[2]) sys.stdout.write("Processing resumed...\n") finally: i += 1 self.messagesCopied += 1 if i%50 == 0: p += 1 sys.stdout.write("Progress: " + p*"." + "\r") sys.stdout.write("\n") else: x = "Skipping because there are no messages in folder." self.response(x) def copyMessage(self, UID, folder): mErr = 0 try: result, message = self.Msource.uid("FETCH", UID, '(RFC822 FLAGS)') except MemoryError: self.response('ERROR: Unrecoverable MemoryError for a message in folder: %s (Message too large?)' % folder) try: self.Msource = imaplib.IMAP4(self.sourceServer) self.Msource.login(self.sourceUser, self.sourcePassword) self.Msource.select(folder) except: pass self.response(' The message that failed is:') r, mes = self.Msource.UID("FETCH", UID, '(BODY[HEADER.FIELDS (SUBJECT)])') self.response(' %s' % mes[0][1]) self.response(' UID: %s' % UID) self.messagesFailed += 1 else: regExFlags = re.compile(r"{\\Answered|\\Flagged|\\Deleted|\\Seen|\\Draft}") flags = regExFlags.findall(message[1]) imapFlags = "" for item in flags: imapFlags += item + " " imapFlags = imapFlags[:-1] imapMessage = message[0][1] del message try: r, dummy = self.Mtarget.append(folder, imapFlags, None, imapMessage) if r != 'OK': self.response('ERROR: Appending message %s failed with status %s ' % (UID, r)) del dummy except imaplib.IMAP4.error: eInfo = sys.exc_info() eType = eInfo[0] eValue = eInfo[1] self.response("ERROR: Message copying of message number %s failed in folder %s" % (UID, folder)) self.response(" The error returned was %s\n" % eValue) self.messagesFailed += 1 if __name__ == "__main__": if len(sys.argv) != 7 and len(sys.argv) != 2: sourceServer = raw_input("Source server name or IP: ") sourceUser = raw_input("Source user: ") sourcePassword = getpass.getpass() targetServer = raw_input("Target server name or IP: ") targetUser = raw_input("Target user: ") targetPassword = getpass.getpass() elif len(sys.argv) == 2: print """Usage: pyMAPCopy.py """ sys.exit() else: sourceServer = sys.argv[1] sourceUser = sys.argv[2] sourcePassword = sys.argv[3] targetServer = sys.argv[4] targetUser = sys.argv[5] targetPassword = sys.argv[6] imapcopy = pyMAPCopy(sourceServer, targetServer, sourceUser, targetUser, sourcePassword, targetPassword) imapcopy.start()