POP3 E-Mail Konten bereinigen

Wer POP3 Konten automatisiert bereinigen muss findet leider nicht viel Software darfür. Ich musste für einen Kunden ein Setup finden, bei dem er von mehreren Geräten Mails lesen kann und der Gelesen und Gelöscht Status nur jeweils das aktuelle Gerät betrifft.

Die Lösung dafür sind mehrere POP3 Konten mit einer Weiterleitung der Hauptadresse auf die jeweiligen Konten und ein python Script dass entweder per Datum oder anhand der Anzahl die alten E-Mails löscht.

Beispiel Setup:

  • E-Mailkonten anlegen
    • Haupt Konto:
      • mail@meine.domain
      • Weiterleitung auf die Unterkonten einrichten
    • Unterkonten:
      • mail-iphone@meine.domain
      • mail-ipad@meine.domain
      • mail-homeoffice@meine.domain
  • Script anlegen und Konfiguration erstellen
    • Unterkonten in der mail-clean.cfg eintragen
    • Hauptkonto sollte per Mailprogramm bereinigt werden (Löschen vom Server nach 30 Tagen beispielsweise)
  • Konten in den jeweiligen Geräten anlegen
    • SMTP Konto immer von mail@meine.domain verwenden
    • POP3 Konto das jeweilige Unterkonto oder das Hauptkonto
  • Und nicht zu Vergessen – Backup der Mails sollte man auch haben!

python Script mail-clean.py:

#!/usr/bin/python
import ConfigParser
import codecs
import getopt
import json
import poplib
import sys
from email.utils import parsedate_tz
import datetime
from datetime import date, timedelta

config = 'mail-clean.cfg'
DEBUG = False

def usage():
	"""usage"""
	print '-c --config /path/to/config'
	print '-D --debug'


def main():
	global config, DEBUG
	try:
		opts, args = getopt.getopt(sys.argv[1:], 'Dc:', \
			['DEBUG', 'config='])
	except getopt.GetoptError as err:
		print err
		usage()
		sys.exit()
	for opt, var in opts:
		if opt in ('-D', '--debug'):
			DEBUG = True
			print 'Setting DEBUG mode on'
		elif opt in ('-c', '--config'):
			if DEBUG:
				print 'config file: ' + var
			config = var
		else:
			usage()
			sys.exit()
	
	parser = ConfigParser.ConfigParser(allow_no_value=True)
	parser.readfp(codecs.open(config, 'rw', 'utf-8-sig'))
	server = parser.get('mail-clean', 'server')
	port = int(parser.get('mail-clean', 'port'))
	if DEBUG:
		print 'Server: ' + server + ':' + str(port)
	userlist = json.loads(parser.get('mail-clean', 'userlist'))
	for i,val in userlist.items():
		if DEBUG:
			print 'id: %s' % i
		if 'timespan_days' in val:
			try:
				clean_timespan(server,port,val['user'],val['passwd'],val['timespan_days'])
			except:
				print "Failed to process user %s" % val['user']
		elif 'max_messages' in val:
			try:
				clean_max_messages(server,port,val['user'],val['passwd'],val['max_messages'])
			except:
				print "Failed to process user %s" % val['user']
		else:
			print "Invalid parameters"


def clean_timespan(server, port, user, passwd, max_timespan_days):
	global DEBUG
	if DEBUG:
		print 'clean_timespan(%d) user: %s' % (max_timespan_days, user)
	if port == 995:
		pop = poplib.POP3_SSL(server, port)
	else:
		pop = poplib.POP3(server, port)
	pop.user(user)
	pop.pass_(passwd)
	stat = pop.stat()
	if DEBUG:
		print "Status: %d message(s), %d bytes" % stat
	poplist = pop.list()
	max_date = datetime.datetime.now() - timedelta(days=max_timespan_days)
	if DEBUG:
		print "Delete messages before %s" % max_date
	if poplist[0].startswith('+OK') :
		msglist = poplist[1]
		for msgspec in msglist :
			msgnum = int(msgspec.split(' ')[0])
			ml = pop.top(str(msgnum), '0')[1]
			date = 0
			for line in ml:
				if not str.lower(line).startswith('date:'):
					continue
				date_hdr = str.strip(line[5:])
				try:
					(y, month, d, h, min, sec, _, _, _, tzoffset) = parsedate_tz(date_hdr)
					date = datetime.datetime(y, month, d, h, min, sec)
					break
				except (TypeError):
					print "TypeError: " + date_hdr
					continue
				except (ValueError):
					print "ValueError: " + date_hdr
					continue
			if (date == 0):
				print "ERROR - %d, %s" % msgnum, date
				# Mail mit defektem Datum loeschen?
				#pop.dele(msgnum)
			else:
				if date <= max_date:
					if DEBUG:
						print "Deleting msg %d at date %s\r" % (msgnum, date)
					pop.dele(msgnum)
				else:
					if DEBUG:
						print "NOT Deleting msg %d at date %s\r" % (msgnum, date)
					break
		else :
			print "No messages for", user
	else :
	    print "Couldn't list messages: status", poplist[0]
	pop.quit()

def clean_max_messages(server, port, user, passwd, max_messages):
	global DEBUG
	print 'clean_max_messages(%d) user: %s' % (max_messages, user)
	if port == 995:
		pop = poplib.POP3_SSL(server, port)
	else:
		pop = poplib.POP3(server, port)
	pop.user(user)
	pop.pass_(passwd)
	stat = pop.stat()
	if DEBUG:
		print "Status: %d message(s), %d bytes" % stat
	num_messages = stat[0]
	if (num_messages>max_messages):
		poplist = pop.list()
		if poplist[0].startswith('+OK') :
			count = num_messages-max_messages
			pos = 0
			msglist = poplist[1]
			for msgspec in msglist :
				msgnum = int(msgspec.split(' ')[0])
				if DEBUG:
					print "Deleting msg %d\r" % msgnum
				pop.dele(msgnum)
				pos = pos + 1
				if pos == count:
					break
			else :
				print "No messages for", user
		else :
		    print "Couldn't list messages: status", poplist[0]
	else:
		if DEBUG:
			print "Nothing to to < max_messages"
	pop.quit()

if __name__ == '__main__':
        main()

Konfiguration mail-clean.cfg

[mail-clean]
server = localhost
port = 995
userlist = {"timespan example": {"user":"user", "passwd":"pass", "timespan_days":365},"max message example": {"user":"user", "passwd":"pass", "max_messages":2000}}

Aufruf des Scripts unter Linux per Cron und unter Windows mit der Aufgabenplanung - Anleitungen dazu finden sich im Internet.

Share

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

ws5p

Bitte geben Sie den Text vor: