Zarafa spamtrain und UCS

Vielen Dank @fbartels!

Ich habe das Script um folgende Features erweitert:

  • Lernen von Spam UND Ham möglich
  • Lernen aus zwei unabhängigen, im spamd.conf global konfigurierbaren Ordnern (standardmässig “LearnHam” und “LearnSpam” -> wird eine Mail in diesen Ordner verschoben, wird sie entsprechend angelernt
  • Prüfung auf den Spam-Header habe ich entfernt, da sie in diesem Szenario imho nicht mehr nötig ist

 
Das oben genannte funktioniert, allerdings habe ich noch zwei Punkte, bei denen ich eure Hilfe benötige:

  1. Nach dem Anlernen der Mail würde ich diese gerne automatisch in einen anderen Ordner verschieben (LearnHam -> Inbox und LearnSpam -> Junk). Dies dürfte dem gängisten Workflow entsprechen und ist quasi die Bestätigung für das erfolgreiche Lernen. Die notwendige Variable (targetfolder) wird in kopano-spamd.py bereits befüllt, allerdings schlägt die move-Methode auf dem Item-Objekt fehl (Aufruf item.move(targetfolder) > Logfile: ‘Item’ object has no attribute ‘move’). Daher habe ich die entsprechende Zeile (Klasse Checker, Methode Learn) aktuell noch auskommentiert. Gemäss Python-Kopano-Dokumentation sollte diese Methode auf dem Item-Objekt jedoch definiert sein. @fbartels: Können Sie mir hier vielleicht weiterhelfen?
  2. Der Service startet aktuell noch nicht automatisch, sondern muss manuell über die Konsole aufgerufen werden (python /usr/local/bin/kopano-spamd.py). Ich würde jedoch gerne realisieren, dass der Service mit Kopano startet und beim Beenden von Kopano gestoppt wird. Wie lässt sich das am besten realisieren?

 
kopano-spamd.py:

#!/usr/bin/env python
# coding=utf-8
"""
ICS driven spam learning daemon for Kopano / SpamAssasin
See included readme.md for more information.
"""
import shlex
import subprocess
import time
import kopano
from MAPI.Tags import *
from kopano import Config, log_exc

CONFIG = {
	'run_as_user': Config.string(default="kopano"),
	'run_as_group': Config.string(default="kopano"),
	'learncmdspam': Config.string(default="/usr/bin/sudo -u amavis /usr/bin/sa-learn --spam"),
	'learncmdham': Config.string(default="/usr/bin/sudo -u amavis /usr/bin/sa-learn --ham"),
	'spamfolder': Config.string(default="LearnSpam"),
	'hamfolder': Config.string(default="LearnHam")
}


class Service(kopano.Service):
	def main(self):
		server = self.server
		state = server.state
		catcher = Checker(self)
		with log_exc(self.log):
			while True:
				try:
					state = server.sync(catcher, state)
				except Exception as e:
					if e.hr == MAPI_E_NETWORK_ERROR:
						self.log.info('Trying to reconnect to Server in %s seconds' % 5)
					else:
						self.log.info('Error: [%s]' % e)
					time.sleep(5)
				time.sleep(1)


class Checker(object):
	def __init__(self, service):
		self.log = service.log
		self.learncmdspam = service.config['learncmdspam']
		self.learncmdham = service.config['learncmdham']
		self.spamfolder = service.config['spamfolder']
		self.hamfolder = service.config['hamfolder']

	def update(self, item, flags):
		if item.message_class == 'IPM.Note':
			if item.folder == item.store.user.folder(self.spamfolder):
				self.learn(item, 'spam')
			elif item.folder == item.store.user.folder(self.hamfolder):
				self.learn(item, 'ham')

	def learn(self, item, learntype):
		with log_exc(self.log):
			try:
				spameml = item.eml()
				if learntype == 'spam':
					learncmd = self.learncmdspam
					targetfolder = item.store.user.junk
				elif learntype == 'ham':
					learncmd = self.learncmdspam
					targetfolder = item.store.user.inbox
				havespam = True
			except Exception as e:
				self.log.info('Failed to extract eml of email: [%s] [%s]' % (e, item.entryid))
			if havespam and learncmd and targetfolder:
				try:
					p = subprocess.Popen(shlex.split(learncmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
					learning, output_err = p.communicate(spameml)
					self.log.info('[%s] sa-learn %s: %s' % (item.store.user.name, learntype, learning.strip('\n')))
					#item.move(targetfolder)
				except Exception as e:
					self.log.info('sa-learn failed: [%s] [%s]' % (e, item.entryid))


def main():
	parser = kopano.parser('ckpsF')  # select common cmd-line options
	options, args = parser.parse_args()
	service = Service('spamd', config=CONFIG, options=options)
	service.start()


if __name__ == '__main__':
	main()

 
spamd.cfg:

##############################################################
# SPAMD SERVICE SETTINGS

# run as specific user
#run_as_user         = kopano

# run as specific group
#run_as_group        = kopano

# control pid file
pid_file            =   /var/run/kopano/spamd.pid

# run server in this path (when not using the -F switch)
#running_path = /var/lib/kopano

##############################################################
# LOG SETTINGS

# Logging method (syslog, file)
log_method          =   file

# Loglevel (0(none), 1(crit), 2(err), 3(warn), 4(notice), 5(info), 6(debug))
#log_level           =   3

# Logfile for log_method = file, use '-' for stderr
log_file            =   /var/log/kopano/spamd.log

# Log timestamp - prefix each log line with timestamp in 'file' logging mode
log_timestamp       =   1

###############################################################
# SPAMD Specific settings

learncmdspam = /usr/bin/sudo -u amavis /usr/bin/sa-learn --spam
learncmdham = /usr/bin/sudo -u amavis /usr/bin/sa-learn --ham
spamfolder = LearnSpam
hamfolder = LearnHam

 
Installationsanleitung: https://kb.kopano.io/display/WIKI/Kopano-spamd