Page tree
Skip to end of metadata
Go to start of metadata

These scripts and tools are provided to help you manage your Kopano system. They are provided as a free service for Kopano users, without warranty of any kind.

Please be aware that usage is at your own risk!

From Kopano Core 8.6 we will provide a kopano-spamd, which works in a different way, ie it does not learn or train directly instead writing the spam emls in a directory so you can use another script to handle these.

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

    'run_as_user': Config.string(default="kopano"),
    'run_as_group': Config.string(default="kopano"),
    'learncmd': Config.string(default="/usr/bin/sudo -u amavis /usr/bin/sa-learn --spam")

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

class Checker(object):
    def __init__(self, service):
        self.log = service.log
        self.learncmd = service.config['learncmd']

    def update(self, item, flags):
        if item.message_class == 'IPM.Note':
            if item.folder == and not item.header('x-spam-flag') == 'YES':

    def learn(self, item):
        with log_exc(self.log):
                spameml = item.eml()
                havespam = True
            except Exception as e:
      'Failed to extract eml of email: [%s] [%s]' % (e, item.entryid))
            if havespam:
                    p = subprocess.Popen(shlex.split(self.learncmd), stdin=subprocess.PIPE, stdout=subprocess.PIPE)
                    learning, output_err = p.communicate(spameml)
          '[%s] sa-learn: %s' % (, learning.strip('\n')))
                except Exception as e:
          '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)

if __name__ == '__main__':

Spam learning daemon for Kopano / SpamAssasin

Messages (if they do not have the X-Spam = YES flag) dragged into the Junk folder will be taught to SpamAssassin's sa-learn command.

Uses ICS for near realtime learning.

Tested on a system which also runs amavisd-new, hence the user for sa-learn is also amavis.

Sudo setup

Add the following line to allow the Kopano user to only run /usr/bin/sa-learn --spam as the user amavis

kopano ALL=(amavis) NOPASSWD: /usr/bin/sa-learn --spam



Copy the provided spamd.cfg in /etc/kopano/.

If needed edit it to suit your needs.

Copy the to /usr/local/bin/

Start the, check /var/log/kopano/spamd.log to see if all went fine.

Now drag some Spam into your Junk box and check the log !

  • No labels