Expunge - Skript für IMAP-Server

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hallo Leute, ich hab ein kleines Problem und nicht die Fähigkeit es zu lösen, da ich das IMAP - Protokoll nicht wirklich kenne. Mein Uni-Mailaccount ist nahezu voll weil mir ein Kommilitone sehr große Anhänge geschickt hat. Nun werden bei IMAP ja Nachrichten nicht direkt gelöscht, sondern nur via FLAG als gelöscht markiert und nicht mehr im Client angezeigt. Kann mir jemand ein Skript bauen, dass einfach nur mal schnell ein Login auf einen IMAP Server durchführt und auf jeden dort vorhandenen Ordner ein Expunge-Kommando absetzt? Ich habe leider schon erfolglos Google bemüht um entsprechende Codeabschnitte zu finden und inzwischen auch via offlineimap mal den ganzen account gesichert. Leider finde ich nix was mir hilft, aber so schwer kann das theoretisch doch nicht sein, oder? Wie gesagt, ich kenne das Protokoll nicht (benutze es aber ganz gerne in verschiedenen Clients auf meinen daheim und in der Uni verteilten Rechner :) und kann mir deswegen leider nicht selber helfen...

viele Grüße und danke!
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hab mir nun doch helfen können, zumindest für meinen Servertyp (Cyrus IMAP4 2.2.12) ... Bitte allerdings um Bestätigung, obs auch bei anderen funktioniert ;)

Code: Alles auswählen

#!/usr/bin/python
import getpass
import imaplib
import re

#python >=2.4
#MBOX=re.compile("""\s+(?P<quote>["'])?(?P<foldername>[^"']+)(?(quote)["'])\Z""")
#python <2.4
MBOX=re.compile("""\s+["']?(?P<foldername>[^"']+)["']?\Z""")

SERVERNAME = ""
USERNAME = ""
PASSWD = ""

def parsefolders(response_list):
	l = []
	for line in response_list:
		m=MBOX.search(line)
		if m is None:
			continue
		l.append(m.group("foldername"))
	return l

if __name__ == "__main__":
	if not SERVERNAME:
		SERVERNAME = raw_input("Server: ")
	if not USERNAME:
		USERNAME = raw_input("User: ")
	if not PASSWD:
		PASSWD = getpass.getpass("Password: ")
	server=imaplib.IMAP4_SSL(SERVERNAME)
	server.debug=4
	try:
		server.login_cram_md5(USERNAME,PASSWD)
	except imaplib.IMAP4.error:
		server.login(USERNAME,PASSWD)
	folder_response=server.list()
	assert folder_response[0].upper() == "OK"
	folders = parsefolders(folder_response[1])
	for folder in folders:
		server.select(folder)
		server.expunge()
	server.logout()
gibt zum Beispiel diese nette Ausgabe:

Code: Alles auswählen

milan@maxserver:~/Python$ python expunge.py 
Server: xyz
User: xyz
Password: 
  01:19.87 > MFKB1 AUTHENTICATE CRAM-MD5
  01:22.94 < MFKB1 NO no mechanism available
  01:22.94 NO response: no mechanism available
  01:22.94 > MFKB2 LOGIN "xyz" "xyz"
  01:23.01 < MFKB2 OK User logged in
  01:23.01 > MFKB3 LIST "" *
  01:23.10 < * LIST (\HasChildren) "." "INBOX"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.Drafts"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.GMX-xyz"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.GMX-xyz"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.Junk"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.Trash"
  01:23.10 < * LIST (\HasNoChildren) "." "INBOX.sent-mail"
  01:23.10 < MFKB3 OK Completed (0.020 secs 8 calls)
  01:23.10 > MFKB4 SELECT INBOX
  01:23.18 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk Junk $MDNSent $Forwarded $label1 $label4)
  01:23.18 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk Junk $MDNSent $Forwarded $label1 $label4 \*)]  
  01:23.18 < * 516 EXISTS
  01:23.18 < * 0 RECENT
  01:23.18 < * OK [UNSEEN 405]  
  01:23.18 < * OK [UIDVALIDITY 1139220031]  
  01:23.18 < * OK [UIDNEXT 6877]  
  01:23.18 < MFKB4 OK [READ-WRITE] Completed
  01:23.18 > MFKB5 EXPUNGE
  01:23.27 < * 516 EXISTS
  01:23.27 < * 0 RECENT
  01:23.27 < MFKB5 OK Completed
  01:23.27 > MFKB6 SELECT INBOX.Drafts
  01:23.37 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
  01:23.38 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)]  
  01:23.38 < * 1 EXISTS
  01:23.38 < * 0 RECENT
  01:23.38 < * OK [UIDVALIDITY 1157111367]  
  01:23.38 < * OK [UIDNEXT 38]  
  01:23.38 < MFKB6 OK [READ-WRITE] Completed
  01:23.38 > MFKB7 EXPUNGE
  01:23.46 < * 1 EXPUNGE
  01:23.46 < * 0 EXISTS
  01:23.46 < * 0 RECENT
  01:23.46 < MFKB7 OK Completed
  01:23.46 > MFKB8 SELECT INBOX.GMX-xyz
  01:23.55 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen Junk NonJunk)
  01:23.55 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen Junk NonJunk \*)]  
  01:23.55 < * 6 EXISTS
  01:23.55 < * 0 RECENT
  01:23.55 < * OK [UIDVALIDITY 1154172951]  
  01:23.55 < * OK [UIDNEXT 111]  
  01:23.55 < MFKB8 OK [READ-WRITE] Completed
  01:23.55 > MFKB9 EXPUNGE
  01:23.64 < * 6 EXISTS
  01:23.64 < * 0 RECENT
  01:23.64 < MFKB9 OK Completed
  01:23.64 > MFKB10 SELECT INBOX.GMX-xyz
  01:23.74 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk $Forwarded $MDNSent Junk)
  01:23.74 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk $Forwarded $MDNSent Junk \*)]  
  01:23.74 < * 56 EXISTS
  01:23.74 < * 0 RECENT
  01:23.74 < * OK [UIDVALIDITY 1154172943]  
  01:23.74 < * OK [UIDNEXT 404]  
  01:23.74 < MFKB10 OK [READ-WRITE] Completed
  01:23.74 > MFKB11 EXPUNGE
  01:23.84 < * 56 EXISTS
  01:23.84 < * 0 RECENT
  01:23.84 < MFKB11 OK Completed
  01:23.84 > MFKB12 SELECT INBOX.Junk
  01:23.93 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen Junk NonJunk)
  01:23.94 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen Junk NonJunk \*)]  
  01:23.94 < * 12 EXISTS
  01:23.94 < * 0 RECENT
  01:23.94 < * OK [UIDVALIDITY 1143660398]  
  01:23.94 < * OK [UIDNEXT 1038]  
  01:23.94 < MFKB12 OK [READ-WRITE] Completed
  01:23.94 > MFKB13 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 1 EXPUNGE
  01:24.14 < * 0 EXISTS
  01:24.15 < * 0 RECENT
  01:24.15 < MFKB13 OK Completed
  01:24.15 > MFKB14 SELECT INBOX.Trash
  01:24.25 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk Junk $MDNSent $Forwarded)
  01:24.25 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen NonJunk Junk $MDNSent $Forwarded \*)]  
  01:24.25 < * 2 EXISTS
  01:24.25 < * 2 RECENT
  01:24.25 < * OK [UNSEEN 1]  
  01:24.26 < * OK [UIDVALIDITY 1139220031]  
  01:24.26 < * OK [UIDNEXT 6181]  
  01:24.26 < MFKB14 OK [READ-WRITE] Completed
  01:24.26 > MFKB15 EXPUNGE
  01:24.33 < * 2 EXISTS
  01:24.33 < * 2 RECENT
  01:24.33 < MFKB15 OK Completed
  01:24.33 > MFKB16 SELECT INBOX.sent-mail
  01:24.43 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $Forwarded)
  01:24.43 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $Forwarded \*)]  
  01:24.43 < * 44 EXISTS
  01:24.43 < * 0 RECENT
  01:24.43 < * OK [UIDVALIDITY 1175509729]  
  01:24.43 < * OK [UIDNEXT 53]  
  01:24.44 < MFKB16 OK [READ-WRITE] Completed
  01:24.44 > MFKB17 EXPUNGE
  01:24.53 < * 44 EXISTS
  01:24.53 < * 0 RECENT
  01:24.53 < MFKB17 OK Completed
  01:24.53 > MFKB18 LOGOUT
  01:24.59 < * BYE LOGOUT received
  01:24.59 BYE response: LOGOUT received
  01:24.59 < MFKB18 OK Completed
EDIT: Servertyp & Version eingefügt
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

wahrscheinlich letzter Post, habe noch ein paar debug ausgaben hinzugefügt :D wäre trotzdem nett, wenn mir jemand bestätigen könnte, dass es bei ihm auch läuft. vor allem wegen dem parsen der Ordnerstruktur hab ich bedenken, da ich da nicht sicher bin, was das Protokoll genau vorsieht.

Code: Alles auswählen

#!/usr/bin/python
import getpass
import imaplib
import re

#python >=2.4
#MBOX=re.compile("""\s+(?P<quote>["'])?(?P<foldername>[^"']+)(?(quote)["'])\Z""")
#python <2.4
MBOX=re.compile("""\s+["']?(?P<foldername>[^"']+)["']?\Z""")

SERVERNAME = ""
USERNAME = ""
PASSWD = ""

def parsefolders(response_list):
	l = []
	for line in response_list:
		m=MBOX.search(line)
		if m is None:
			continue
		l.append(m.group("foldername"))
	return l

if __name__ == "__main__":
	counter = 0
	if not SERVERNAME:
		SERVERNAME = raw_input("server: ")
	if not USERNAME:
		USERNAME = raw_input("user: ")
	if not PASSWD:
		PASSWD = getpass.getpass("password: ")
	server=imaplib.IMAP4_SSL(SERVERNAME)
#	server.debug=4
	try:
		server.login_cram_md5(USERNAME,PASSWD)
	except imaplib.IMAP4.error:
		server.login(USERNAME,PASSWD)
	print "logged in..."
	folder_response=server.list()
	assert folder_response[0].upper() == "OK"
	folders = parsefolders(folder_response[1])
	print "got folders:", ", ".join(['"%s"' % folder for folder in folders])
	for folder in folders:
		server.select(folder)
		print 'processing folder "%s" ...' % folder
		typ,data = server.expunge()
		lenght=len(data)
		if lenght > 0 and data[0] != None:
			print "\tpermanently removed %i mails." % lenght
			counter += lenght
		else:
			print "\tno mails permanently removed."
	server.logout()
	print "logged out. altogether, removed %i mails permanently." % counter
gibt den output:

Code: Alles auswählen

milan@maxserver:~$ python Python/expunge.py 
server: xyz
user: xyz2
password: 
logged in...
got folders: "INBOX", "INBOX.Drafts", "INBOX.GMX-xyz3", "INBOX.GMX-xyz4", "INBOX.Junk", "INBOX.Trash", "INBOX.sent-mail"
processing folder "INBOX" ...
	no mails permanently removed.
processing folder "INBOX.Drafts" ...
	no mails permanently removed.
processing folder "INBOX.GMX-xyz3" ...
	no mails permanently removed.
processing folder "INBOX.GMX-xyz4" ...
	no mails permanently removed.
processing folder "INBOX.Junk" ...
	no mails permanently removed.
processing folder "INBOX.Trash" ...
	no mails permanently removed.
processing folder "INBOX.sent-mail" ...
	no mails permanently removed.
logged out. altogether, removed 0 mails permanently.
Antworten