summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-11-10 17:04:55 +0000
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-11-10 17:04:55 +0000
commit8eddcc101d0b2f1a6e80df0110b0a504003925f1 (patch)
tree564d47c1ab770f31ddbad8d1984d2776acaa7817
parenta70c6d6fc211fab8f0329c3bccc0c136e552738c (diff)
downloadpykolab-8eddcc101d0b2f1a6e80df0110b0a504003925f1.tar.gz
Initial sieve script management command-line invocations
-rw-r--r--pykolab/Makefile.am4
-rw-r--r--pykolab/cli/sieve/__init__.py0
-rw-r--r--pykolab/cli/sieve/cmd_list.py104
-rw-r--r--pykolab/cli/sieve/cmd_put.py93
-rw-r--r--pykolab/cli/sieve/cmd_refresh.py286
-rw-r--r--pykolab/cli/sieve/cmd_test.py129
6 files changed, 616 insertions, 0 deletions
diff --git a/pykolab/Makefile.am b/pykolab/Makefile.am
index 15f95ea..5ef6974 100644
--- a/pykolab/Makefile.am
+++ b/pykolab/Makefile.am
@@ -15,6 +15,10 @@ pykolab_clidir = $(pythondir)/$(PACKAGE)/cli
pykolab_cli_PYTHON = \
$(wildcard cli/*.py)
+pykolab_clisievedir = $(pythondir)/$(PACKAGE)/cli/sieve
+pykolab_clisieve_PYTHON = \
+ $(wildcard cli/sieve/*.py)
+
pykolab_clitelemetrydir = $(pythondir)/$(PACKAGE)/cli/telemetry
pykolab_clitelemetry_PYTHON = \
$(wildcard cli/telemetry/*.py)
diff --git a/pykolab/cli/sieve/__init__.py b/pykolab/cli/sieve/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pykolab/cli/sieve/__init__.py
diff --git a/pykolab/cli/sieve/cmd_list.py b/pykolab/cli/sieve/cmd_list.py
new file mode 100644
index 0000000..e89a42e
--- /dev/null
+++ b/pykolab/cli/sieve/cmd_list.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 3 or, at your option, any later version
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+import sys
+import time
+from urlparse import urlparse
+
+import pykolab
+
+from pykolab.auth import Auth
+from pykolab.cli import commands
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+def __init__():
+ commands.register('list', execute, group='sieve', description=description())
+
+def description():
+ return """List a user's sieve scripts."""
+
+def execute(*args, **kw):
+ try:
+ address = conf.cli_args.pop(0)
+ except:
+ address = utils.ask_question(_("Email Address"))
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient(address)
+
+ # Get the main, default backend
+ backend = conf.get('kolab', 'imap_backend')
+
+ if len(address.split('@')) > 1:
+ domain = address.split('@')[1]
+ else:
+ domain = conf.get('kolab', 'primary_domain')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_backend'):
+ backend = conf.get(domain, 'imap_backend')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_uri'):
+ uri = conf.get(domain, 'imap_uri')
+ else:
+ uri = conf.get(backend, 'uri')
+
+ hostname = None
+ port = None
+
+ result = urlparse(uri)
+
+ if hasattr(result, 'hostname'):
+ hostname = result.hostname
+ else:
+ scheme = uri.split(':')[0]
+ (hostname, port) = uri.split('/')[2].split(':')
+
+ port = 4190
+
+ # Get the credentials
+ admin_login = conf.get(backend, 'admin_login')
+ admin_password = conf.get(backend, 'admin_password')
+
+ import sievelib.managesieve
+
+ sieveclient = sievelib.managesieve.Client(hostname, port, conf.debuglevel > 8)
+ sieveclient.connect(None, None, True)
+ result = sieveclient._plain_authentication(admin_login, admin_password, address)
+ if not result:
+ print "LOGIN FAILED??"
+
+ sieveclient.authenticated = True
+
+ result = sieveclient.listscripts()
+
+ if result == None:
+ print "No scripts"
+ sys.exit(0)
+
+ (active, scripts) = result
+
+ print "%s (active)" % (active)
+ for script in scripts:
+ print script
+
diff --git a/pykolab/cli/sieve/cmd_put.py b/pykolab/cli/sieve/cmd_put.py
new file mode 100644
index 0000000..b514653
--- /dev/null
+++ b/pykolab/cli/sieve/cmd_put.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 3 or, at your option, any later version
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+import pykolab
+
+from pykolab.auth import Auth
+from pykolab.cli import commands
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+import time
+from urlparse import urlparse
+
+def __init__():
+ commands.register('put', execute, group='sieve', description=description())
+
+def description():
+ return """Put a script to a user's list of sieve scripts."""
+
+def execute(*args, **kw):
+ try:
+ address = conf.cli_args.pop(0)
+ except:
+ address = utils.ask_question(_("Email Address"))
+
+ script_to_put = conf.cli_args.pop(0)
+
+ script_put_name = conf.cli_args.pop(0)
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient(address)
+
+ # Get the main, default backend
+ backend = conf.get('kolab', 'imap_backend')
+
+ if len(address.split('@')) > 1:
+ domain = address.split('@')[1]
+ else:
+ domain = conf.get('kolab', 'primary_domain')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_backend'):
+ backend = conf.get(domain, 'imap_backend')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_uri'):
+ uri = conf.get(domain, 'imap_uri')
+ else:
+ uri = conf.get(backend, 'uri')
+
+ hostname = None
+ port = None
+
+ result = urlparse(uri)
+
+ if hasattr(result, 'hostname'):
+ hostname = result.hostname
+ else:
+ scheme = uri.split(':')[0]
+ (hostname, port) = uri.split('/')[2].split(':')
+
+ port = 4190
+
+ # Get the credentials
+ admin_login = conf.get(backend, 'admin_login')
+ admin_password = conf.get(backend, 'admin_password')
+
+ import sievelib.managesieve
+
+ sieveclient = sievelib.managesieve.Client(hostname, port, False)
+ sieveclient.connect(None, None, True)
+ sieveclient._plain_authentication(admin_login, admin_password, address)
+ sieveclient.authenticated = True
+
+ sieveclient.putscript(script_put_name, open(script_to_put, "r").read())
diff --git a/pykolab/cli/sieve/cmd_refresh.py b/pykolab/cli/sieve/cmd_refresh.py
new file mode 100644
index 0000000..f34c65c
--- /dev/null
+++ b/pykolab/cli/sieve/cmd_refresh.py
@@ -0,0 +1,286 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 3 or, at your option, any later version
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+import pykolab
+
+from pykolab import utils
+from pykolab.auth import Auth
+from pykolab.cli import commands
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+import sys
+import time
+from urlparse import urlparse
+
+def __init__():
+ commands.register('refresh', execute, group='sieve', description=description())
+
+def description():
+ return """Refresh a user's managed and contributed sieve scripts."""
+
+def execute(*args, **kw):
+ try:
+ address = conf.cli_args.pop(0)
+ except:
+ address = utils.ask_question(_("Email Address"))
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient(address)
+
+ # Get the main, default backend
+ backend = conf.get('kolab', 'imap_backend')
+
+ if len(address.split('@')) > 1:
+ domain = address.split('@')[1]
+ else:
+ domain = conf.get('kolab', 'primary_domain')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_backend'):
+ backend = conf.get(domain, 'imap_backend')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_uri'):
+ uri = conf.get(domain, 'imap_uri')
+ else:
+ uri = conf.get(backend, 'uri')
+
+ hostname = None
+ port = None
+
+ result = urlparse(uri)
+
+ if hasattr(result, 'hostname'):
+ hostname = result.hostname
+ else:
+ scheme = uri.split(':')[0]
+ (hostname, port) = uri.split('/')[2].split(':')
+
+ port = 4190
+
+ # Get the credentials
+ admin_login = conf.get(backend, 'admin_login')
+ admin_password = conf.get(backend, 'admin_password')
+
+ import sievelib.managesieve
+
+ sieveclient = sievelib.managesieve.Client(hostname, port, conf.debuglevel > 8)
+ sieveclient.connect(None, None, True)
+ sieveclient._plain_authentication(admin_login, admin_password, address)
+ sieveclient.authenticated = True
+
+ result = sieveclient.listscripts()
+
+ if result == None:
+ active = None
+ scripts = []
+ else:
+ active, scripts = result
+
+
+ print "Found the following scripts: %s" % (','.join(scripts))
+ print "And the following script is active: %s" % (active)
+
+ mgmt_required_extensions = []
+
+ mgmt_script = """#
+# MANAGEMENT
+#
+"""
+
+ user = auth.get_entry_attributes(domain, user, ['*'])
+
+ #
+ # Delivery to Folder
+ #
+ dtf_active_attr = conf.get('sieve', 'deliver_to_folder_active')
+ if not dtf_active_attr == None:
+ if user.has_key(dtf_active_attr):
+ dtf_active = utils.true_or_false(user[dtf_active_attr])
+ else:
+ dtf_active = False
+ else:
+ # TODO: Not necessarily de-activated, the *Active attributes are
+ # not supposed to charge this - check the deliver_to_folder_attr
+ # attribute value for a value.
+ dtf_active = False
+
+ if dtf_active:
+ dtf_folder_name_attr = conf.get('sieve', 'deliver_to_folder_attr')
+ if not dtf_folder_name_attr == None:
+ if user.has_key(dtf_folder_name_attr):
+ dtf_folder = user[dtf_folder_name_attr]
+ else:
+ log.warning(_("Delivery to folder active, but no folder name attribute available for user %r") % (user))
+ dtf_active = False
+ else:
+ log.error(_("Delivery to folder active, but no folder name attribute configured"))
+ dtf_active = False
+
+ #
+ # Folder name to delivery spam to.
+ #
+ # Global or local.
+ #
+ sdf_filter = True
+ sdf = conf.get('sieve', 'spam_global_folder')
+
+ if sdf == None:
+ sdf = conf.get('sieve', 'spam_personal_folder')
+ if sdf == None:
+ sdf_filter = False
+
+ #
+ # Mail forwarding
+ #
+ forward_active = None
+ forward_addresses = []
+ forward_keepcopy = None
+ forward_uce = None
+
+ forward_active_attr = conf.get('sieve', 'forward_address_active')
+ if not forward_active_attr == None:
+ if user.has_key(forward_active_attr):
+ forward_active = utils.true_or_false(user[forward_active_attr])
+ else:
+ forward_active = False
+
+ if not forward_active == False:
+ forward_address_attr = conf.get('sieve', 'forward_address_attr')
+ if user.has_key(forward_address_attr):
+ if isinstance(user[forward_address_attr], basestring):
+ forward_addresses = [ user[forward_address_attr] ]
+ elif isinstance(user[forward_address_attr], str):
+ forward_addresses = [ user[forward_address_attr] ]
+ else:
+ forward_addresses = user[forward_address_attr]
+
+ forward_keepcopy_attr = conf.get('sieve', 'forward_keepcopy_active')
+ if not forward_keepcopy_attr == None:
+ if user.has_key(forward_keepcopy_attr):
+ forward_keepcopy = utils.true_or_false(user[forward_keepcopy_attr])
+ else:
+ forward_keepcopy = False
+
+ forward_uce_attr = conf.get('sieve', 'forward_uce_active')
+ if not forward_uce_attr == None:
+ if user.has_key(forward_uce_attr):
+ forward_uce = utils.true_or_false(user[forward_uce_attr])
+ else:
+ forward_uce = False
+
+ print mgmt_script
+
+ if forward_active:
+ mgmt_required_extensions.append('redirect')
+
+ if dtf_active:
+ mgmt_required_extensions.append('fileinto')
+
+ if sdf_filter:
+ mgmt_required_extensions.append('fileinto')
+
+ import sievelib.factory
+
+ mgmt_script = sievelib.factory.FiltersSet("MANAGEMENT")
+
+ for required_extension in mgmt_required_extensions:
+ mgmt_script.require(required_extension)
+
+ if forward_active:
+ if forward_uce:
+ if forward_keepcopy:
+ mgmt_script.addfilter('forward-uce-keepcopy', ['true'], [("redirect", ":copy", forward_addresses)])
+ else:
+ mgmt_script.addfilter('forward-uce', ['true'], [("redirect", forward_addresses)])
+ else:
+ if forward_keepcopy:
+ mgmt_script.addfilter('forward-keepcopy', [("X-Spam-Status", ":matches", "No,*")], [("redirect", ":copy", forward_addresses)])
+ else:
+ mgmt_script.addfilter('forward', [("X-Spam-Status", ":matches", "No,*")], [("redirect", forward_addresses)])
+
+ if sdf_filter:
+ mgmt_script.addfilter('spam_delivery_folder', [("X-Spam-Status", ":matches", "Yes,*")], [("fileinto", "INBOX/Spam"), ("stop")])
+
+ #if dtf_active:
+
+ print mgmt_script.__str__()
+
+ result = sieveclient.putscript("MANAGEMENT", mgmt_script.__str__())
+
+ if not result:
+ print "Putting in script MANAGEMENT failed...?"
+ else:
+ print "Putting in script MANAGEMENT succeeded"
+
+ user_script = """#
+# User
+#
+
+require ["include"];
+"""
+
+ for script in scripts:
+ if not script in [ "MASTER", "MANAGEMENT", "USER" ]:
+ print "Including script %s in USER" % (script)
+ user_script = """%s
+
+include :personal "%s";
+""" % (user_script, script)
+
+ result = sieveclient.putscript("USER", user_script)
+ if not result:
+ print "Putting in script USER failed...?"
+ else:
+ print "Putting in script USER succeeded"
+
+ result = sieveclient.putscript("MASTER", """#
+# MASTER
+#
+# This file is authoritative for your system and MUST BE KEPT ACTIVE.
+#
+# Altering it is likely to render your account dysfunctional and may
+# be violating your organizational or corporate policies.
+#
+# For more information on the mechanism and the conventions behind
+# this script, see http://wiki.kolab.org/KEP:14
+#
+
+require ["include"];
+
+# OPTIONAL: Includes for all or a group of users
+# include :global "all-users";
+# include :global "this-group-of-users";
+
+# The script maintained by the general management system
+include :personal "MANAGEMENT";
+
+# The script(s) maintained by one or more editors available to the user
+include :personal "USER";
+""")
+
+ if not result:
+ print "Putting in script MASTER failed...?"
+ else:
+ print "Putting in script MASTER succeeded"
+
+ sieveclient.setactive("MASTER")
diff --git a/pykolab/cli/sieve/cmd_test.py b/pykolab/cli/sieve/cmd_test.py
new file mode 100644
index 0000000..d396aa2
--- /dev/null
+++ b/pykolab/cli/sieve/cmd_test.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+# Copyright 2010-2012 Kolab Systems AG (http://www.kolabsys.com)
+#
+# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 3 or, at your option, any later version
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+import pykolab
+
+from pykolab.auth import Auth
+from pykolab.cli import commands
+from pykolab.translate import _
+
+log = pykolab.getLogger('pykolab.cli')
+conf = pykolab.getConf()
+
+import time
+from urlparse import urlparse
+
+
+def __init__():
+ commands.register('test', execute, group='sieve', description=description())
+
+def description():
+ return """Syntactically check a user's sieve scripts."""
+
+def execute(*args, **kw):
+ try:
+ address = conf.cli_args.pop(0)
+ except:
+ address = utils.ask_question(_("Email Address"))
+
+ auth = Auth()
+ auth.connect()
+
+ user = auth.find_recipient(address)
+
+ # Get the main, default backend
+ backend = conf.get('kolab', 'imap_backend')
+
+ if len(address.split('@')) > 1:
+ domain = address.split('@')[1]
+ else:
+ domain = conf.get('kolab', 'primary_domain')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_backend'):
+ backend = conf.get(domain, 'imap_backend')
+
+ if conf.has_section(domain) and conf.has_option(domain, 'imap_uri'):
+ uri = conf.get(domain, 'imap_uri')
+ else:
+ uri = conf.get(backend, 'uri')
+
+ hostname = None
+ port = None
+
+ result = urlparse(uri)
+
+ if hasattr(result, 'hostname'):
+ hostname = result.hostname
+ else:
+ scheme = uri.split(':')[0]
+ (hostname, port) = uri.split('/')[2].split(':')
+
+ port = 4190
+
+ # Get the credentials
+ admin_login = conf.get(backend, 'admin_login')
+ admin_password = conf.get(backend, 'admin_password')
+
+ import sievelib.managesieve
+
+ sieveclient = sievelib.managesieve.Client(hostname, port, True)
+ sieveclient.connect(None, None, True)
+ sieveclient._plain_authentication(admin_login, admin_password, address)
+ sieveclient.authenticated = True
+
+ active, scripts = sieveclient.listscripts()
+
+ print "%s (active)" % (active)
+
+ _all_scripts = [ active ] + scripts
+ _used_scripts = [ active ]
+ _included_scripts = []
+
+ _a_script = sieveclient.getscript(active)
+
+ print _a_script
+
+ import sievelib.parser
+
+ _a_parser = sievelib.parser.Parser(debug=True)
+ _a_parsed = _a_parser.parse(_a_script)
+
+ #print "%r" % (_a_parsed)
+
+ if not _a_parsed:
+ print _a_parser.error
+
+ print "%r" % (_a_parser.result)
+
+ for _a_command in _a_parser.result:
+ print _a_command.name, _a_command.arguments
+ if len(_a_command.children) > 0:
+ for _a_child in _a_command.children:
+ print " ", _a_child.name, _a_child.arguments
+
+ if _a_command.name == "include":
+ if _a_command.arguments["script"].strip('"') in scripts:
+ print "OK"
+ _used_scripts.append(_a_command.arguments["script"].strip('"'))
+ else:
+ print "Not OK"
+
+ for script in scripts:
+ print script
+