Projects
Kolab:Winterfell
pykolab
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 65
View file
pykolab.spec
Changed
@@ -33,7 +33,7 @@ Summary: Kolab Groupware Solution Name: pykolab -Version: 0.8.12 +Version: 0.8.13 Release: 1%{?dist} License: GPLv3+ Group: Applications/System @@ -42,8 +42,6 @@ Source0: pykolab-%{version}.tar.gz Source1: pykolab.logrotate -Patch0001: 0001-Fix-resolving-referrals.patch - BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildArch: noarch
View file
0001-Fix-resolving-referrals.patch
Deleted
@@ -1,25 +0,0 @@ -From 814ffc770e3a696606b6ee1c58b4099d1a80071f Mon Sep 17 00:00:00 2001 -From: "Jeroen van Meeuwen (Kolab Systems)" <vanmeeuwen@kolabsys.com> -Date: Thu, 13 Jun 2019 13:08:40 +0200 -Subject: [PATCH] Fix resolving referrals - ---- - pykolab/auth/ldap/__init__.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/pykolab/auth/ldap/__init__.py b/pykolab/auth/ldap/__init__.py -index 3a30621..466f425 100644 ---- a/pykolab/auth/ldap/__init__.py -+++ b/pykolab/auth/ldap/__init__.py -@@ -846,7 +846,7 @@ class LDAP(pykolab.base.Base): - ) - - # Remove referrals -- _entry_dns = [_e for _e in _results if _e[0] is not None] -+ _entry_dns = [_e[0] for _e in _results if _e[0] is not None] - - return _entry_dns - --- -2.20.1 -
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +pykolab (0.8.13-0~kolab1) unstable; urgency=low + + * Release of version 0.8.13 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Thu, 20 Jun 2019 01:49:00 +0100 + pykolab (0.8.12-0~kolab5) unstable; urgency=low * Release of version 0.8.12
View file
debian.series
Changed
@@ -1,2 +1,1 @@ cyrus-imapd.conf-cert-paths.patch -p1 -0001-Fix-resolving-referrals.patch -p1
View file
pykolab-0.8.13.tar.gz/.flake8
Added
@@ -0,0 +1,18 @@ +[flake8] +exclude = + .git, + __pycache__, + docs/source/conf.py + +ignore = + # 'something' imported but unused + F401, + # 'from module import *' used: unable to detect undefined names + F403, + # name may be undefined, or defined from star imports: module + F405, + # line break before binary operator + W503 + +max-complexity = 18 +max-line-length = 100
View file
pykolab-0.8.13.tar.gz/.pylintrc
Added
@@ -0,0 +1,11 @@ +[MASTER] +disable= + cyclic-import, + duplicate-code, + missing-docstring, + unused-argument, + unused-wildcard-import, + wildcard-import + +function-rgx=[a-z_][a-z0-9_]{2,90}$ +init-hook="import sys; sys.path.insert(0, './data/')"
View file
pykolab-0.8.12.tar.gz/conf/kolab.conf -> pykolab-0.8.13.tar.gz/conf/kolab.conf
Changed
@@ -428,9 +428,51 @@ result_attribute = mail [wallace] -modules = resources, invitationpolicy, footer -footer_text = /etc/kolab/footer.text -footer_html = /etc/kolab/footer.html +; List the modules to load and apply, in order. +; +; Available modules include; +; +; * resources +; * invitationpolicy +; * footer +; * signature +; +modules = resources, invitationpolicy + +; Footer module settings +;footer_text = /etc/kolab/footer.text +;footer_html = /etc/kolab/footer.html + +; Signature module settings +; +; Two modes: write out the exact signature in /etc/kolab/ as html and/or text, +; or use rules. +; +; If files are configured, rules do not apply. If files are configured, a +; fallback is /etc/kolab/signature_default.{html,txt}. +; +; signature_file_html = /etc/kolab/signature.d/%(mail)s.html +; signature_file_text = /etc/kolab/signature.d/%(mail)s.txt +; +; A list of dicts, with each dict holding an attribute name ("o", "cn", +; "entrydn"), and a regular expression to be matched against the attribute +; value. +; +; The module takes the first match, and uses the "html" and "text" files as +; templates. +; +;signature_rules = [ +; { +; "entrydn": "uid=.*,ou=IT,ou=People,dc=example,dc=org", +; "html": "/etc/kolab/signature_IT.html", +; "text": "/etc/kolab/signature_IT.txt" +; }, +; { +; "entrydn": "uid=.*,ou=Finance,ou=People,dc=example,dc=org", +; "html": "/etc/kolab/signature_Finance.html", +; "text": "/etc/kolab/signature_Finance.txt" +; } +; ] ; default settings for kolabInvitationPolicy LDAP attribute on user records kolab_invitation_policy = ACT_ACCEPT_IF_NO_CONFLICT:example.org, ACT_MANUAL
View file
pykolab-0.8.13.tar.gz/conf/signature_IT.html
Added
@@ -0,0 +1,13 @@ +<br clear="all"/> +<hr> +This is an example HTML signature. + +<p style="font-size: small; color: gray;"> +%(o)s + +%(manager:cn)s + +M: %(mobile)s +T: %(telephonenumber)s +W: https://it.services.inc +</p>
View file
pykolab-0.8.13.tar.gz/conf/signature_IT.txt
Added
@@ -0,0 +1,9 @@ +This is an example TEXT signature. + +%(o)s + +%(manager:cn)s + +M: %(mobile)s +T: %(telephonenumber)s +W: https://it.services.inc
View file
pykolab-0.8.12.tar.gz/configure.ac -> pykolab-0.8.13.tar.gz/configure.ac
Changed
@@ -1,4 +1,4 @@ -AC_INIT([pykolab], 0.8.12) +AC_INIT([pykolab], 0.8.13) AC_SUBST([RELEASE], 1) AC_CONFIG_SRCDIR(pykolab/constants.py.in)
View file
pykolab-0.8.12.tar.gz/pykolab/auth/ldap/__init__.py -> pykolab-0.8.13.tar.gz/pykolab/auth/ldap/__init__.py
Changed
@@ -846,7 +846,7 @@ ) # Remove referrals - _entry_dns = [_e for _e in _results if _e[0] is not None] + _entry_dns = [_e[0] for _e in _results if _e[0] is not None] return _entry_dns
View file
pykolab-0.8.12.tar.gz/pykolab/setup/setup_ldap.py -> pykolab-0.8.13.tar.gz/pykolab/setup/setup_ldap.py
Changed
@@ -417,6 +417,7 @@ schema_error = True if os.path.isfile('/bin/systemctl'): + subprocess.call(['/bin/systemctl', 'restart', 'dirsrv.target']) subprocess.call(['/bin/systemctl', 'restart', 'dirsrv@' + _input['hostname']]) time.sleep(20) elif os.path.isfile('/sbin/service'): @@ -429,6 +430,7 @@ log.error(_("Could not start the directory server service.")) if os.path.isfile('/bin/systemctl'): + subprocess.call(['/bin/systemctl', 'enable', 'dirsrv.target']) subprocess.call(['/bin/systemctl', 'enable', 'dirsrv@' + _input['hostname']]) elif os.path.isfile('/sbin/chkconfig'): subprocess.call(['/sbin/chkconfig', 'dirsrv', 'on'])
View file
pykolab-0.8.12.tar.gz/pykolab/setup/setup_roundcube.py -> pykolab-0.8.13.tar.gz/pykolab/setup/setup_roundcube.py
Changed
@@ -112,7 +112,9 @@ log.error("Roundcube installation path not found.") return - if os.access(rcpath + 'skins/enterprise/', os.R_OK): + if os.access(rcpath + 'skins/kolab/', os.R_OK): + rc_settings['skin'] = 'kolab' + elif os.access(rcpath + 'skins/enterprise/', os.R_OK): rc_settings['skin'] = 'enterprise' elif os.access(rcpath + 'skins/chameleon/', os.R_OK): rc_settings['skin'] = 'chameleon'
View file
pykolab-0.8.12.tar.gz/wallace/__init__.py -> pykolab-0.8.13.tar.gz/wallace/__init__.py
Changed
@@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com) +# Copyright 2010-2019 Kolab Systems AG (http://www.kolabsys.com) # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # @@ -17,6 +17,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +from __future__ import print_function + import asyncore from distutils import version import grp @@ -31,31 +33,33 @@ import tempfile from threading import _Timer import time -import traceback import pykolab from pykolab import utils from pykolab.translate import _ +from modules import cb_action_ACCEPT + +# pylint: disable=invalid-name log = pykolab.getLogger('pykolab.wallace') conf = pykolab.getConf() -from modules import cb_action_ACCEPT -def pickup_message(filepath, *args, **kw): +def pickup_message(filepath, *args, **kwargs): wallace_modules = args[0] - if kw.has_key('module'): + + if 'module' in kwargs: # Cause the previous modules to be skipped - wallace_modules = wallace_modules[(wallace_modules.index(kw['module'])+1):] + wallace_modules = wallace_modules[(wallace_modules.index(kwargs['module']) + 1):] log.debug(_("Wallace modules: %r") % (wallace_modules), level=8) # Execute the module - if kw.has_key('stage'): - modules.execute(kw['module'], filepath, stage=kw['stage']) + if 'stage' in kwargs: + modules.execute(kwargs['module'], filepath, stage=kwargs['stage']) else: - modules.execute(kw['module'], filepath) + modules.execute(kwargs['module'], filepath) # After all modules are executed, continue with a call to # accept the message and re-inject in to Postfix. @@ -64,11 +68,18 @@ for module in wallace_modules: try: result_filepath = modules.execute(module, filepath) - except: - log.error(_("Module %s.execute() failed on message %r with error: %s" % (module, filepath, traceback.format_exc()))) + except Exception: + log.error( + "Module %s.execute() failed on message %r with error: %s" % ( + module, + filepath, + traceback.format_exc() + ) + ) + result_filepath = False - if not result_filepath == None and not result_filepath == False: + if result_filepath is not None and result_filepath is not False: filepath = result_filepath else: # A module has returned False or None @@ -80,26 +91,38 @@ if continue_with_accept: cb_action_ACCEPT('wallace', filepath) + def modules_heartbeat(wallace_modules): lastrun = 0 - while True: + while not multiprocessing.current_process().finished.is_set(): try: for module in wallace_modules: try: modules.heartbeat(module, lastrun) - except: - log.error(_("Module %s.heartbeat() failed with error: %s" % (module, traceback.format_exc()))) + except Exception: + log.error( + "Module %s.heartbeat() failed with error: %s" % ( + module, + traceback.format_exc() + ) + ) lastrun = int(time.time()) - time.sleep(60) - except (SystemExit, KeyboardInterrupt), e: - log.info("Terminating heartbeat process") + multiprocessing.current_process().finished.wait(60) + + except (SystemExit, KeyboardInterrupt) as errmsg: + log.warning("Exiting %s, %s" % (multiprocessing.current_process().name, errmsg)) break -def worker_process(*args, **kw): - log.debug(_("Worker process %s initializing") % (multiprocessing.current_process().name), level=1) +def worker_process(*args, **kwargs): + import signal + signal.signal(signal.SIGINT, signal.SIG_IGN) + log.debug("Worker process %s initializing" % (multiprocessing.current_process().name), level=1) + + +# pylint: disable=too-few-public-methods class Timer(_Timer): def run(self): while True: @@ -109,92 +132,99 @@ self.finished.set() -class WallaceDaemon(object): + +class WallaceDaemon: def __init__(self): self.current_connections = 0 self.max_connections = 24 + self.parent_pid = None self.pool = None daemon_group = conf.add_cli_parser_option_group(_("Daemon Options")) daemon_group.add_option( - "--fork", - dest = "fork_mode", - action = "store_true", - default = False, - help = _("Fork to the background.") - ) + "--fork", + dest="fork_mode", + action="store_true", + default=False, + help=_("Fork to the background.") + ) daemon_group.add_option( - "-b", "--bind", - dest = "wallace_bind_address", - action = "store", - default = "localhost", - help = _("Bind address for Wallace.") - ) + "-b", "--bind", + dest="wallace_bind_address", + action="store", + default="localhost", + help=_("Bind address for Wallace.") + ) daemon_group.add_option( - "-g", - "--group", - dest = "process_groupname", - action = "store", - default = "kolab", - help = _("Run as group GROUPNAME"), - metavar = "GROUPNAME" - ) + "-g", "--group", + dest="process_groupname", + action="store", + default="kolab", + help=_("Run as group GROUPNAME"), + metavar="GROUPNAME" + ) daemon_group.add_option( - "--threads", - dest = "max_threads", - action = "store", - default = 4, - type = int, - help = _("Number of threads to use.") - ) + "--threads", + dest="max_threads", + action="store", + default=4, + type=int, + help=_("Number of threads to use.") + ) daemon_group.add_option( - "-p", "--pid-file", - dest = "pidfile", - action = "store", - default = "/var/run/wallaced/wallaced.pid", - help = _("Path to the PID file to use.") - ) + "-p", "--pid-file", + dest="pidfile", + action="store", + default="/var/run/wallaced/wallaced.pid", + help=_("Path to the PID file to use.") + ) daemon_group.add_option( - "--port", - dest = "wallace_port", - action = "store", - default = 10026, - type = int, - help = _("Port that Wallace is supposed to use.") - ) + "--port", + dest="wallace_port", + action="store", + default=10026, + type=int, + help=_("Port that Wallace is supposed to use.") + ) daemon_group.add_option( - "-u", - "--user", - dest = "process_username", - action = "store", - default = "kolab", - help = _("Run as user USERNAME"), - metavar = "USERNAME" - ) + "-u", "--user", + dest="process_username", + action="store", + default="kolab", + help=_("Run as user USERNAME"), + metavar="USERNAME" + ) conf.finalize_conf() utils.ensure_directory( - os.path.dirname(conf.pidfile), - conf.process_username, - conf.process_groupname - ) + os.path.dirname(conf.pidfile), + conf.process_username, + conf.process_groupname + ) + + if conf.debuglevel >= 9: + mp_logger = multiprocessing.get_logger() + mp_logger.setLevel(multiprocessing.SUBDEBUG) + mp_logger.debug('Python multi-processing logger started') import modules modules.__init__() self.modules = conf.get_list('wallace', 'modules') - if self.modules == None: + if not self.modules: self.modules = [] def do_wallace(self): + self.parent_pid = os.getpid() + if version.StrictVersion(sys.version[:3]) >= version.StrictVersion("2.7"): self.pool = multiprocessing.Pool(conf.max_threads, worker_process, (), 1) else: @@ -215,20 +245,23 @@ s.bind((conf.wallace_bind_address, conf.wallace_port)) bound = True - except Exception, e: + + # pylint: disable=broad-except + except Exception: log.warning( - _("Could not bind to socket on port %d on bind " + \ - "address %s") % ( - conf.wallace_port, - conf.wallace_bind_address - ) + _("Could not bind to socket on port %d on bind address %s") % ( + conf.wallace_port, + conf.wallace_bind_address ) + ) while not shutdown: try: s.shutdown(socket.SHUT_RDWR) shutdown = True - except Exception, e: + + # pylint: disable=broad-except + except Exception: log.warning(_("Could not shut down socket")) time.sleep(1) @@ -238,39 +271,59 @@ s.listen(5) - self.timer = Timer(180, self.pickup_spool_messages) + self.timer = Timer(180, self.pickup_spool_messages, args=[], kwargs={'sync': True}) + self.timer.daemon = True self.timer.start() # start background process to run periodic jobs in active modules - self.heartbeat = multiprocessing.Process(target=modules_heartbeat, args=[self.modules]) - self.heartbeat.daemon = True - self.heartbeat.start() + try: + self.heartbeat = multiprocessing.Process( + target=modules_heartbeat, + name='Wallace_Heartbeat', + args=[self.modules] + ) + + self.heartbeat.finished = multiprocessing.Event() + self.heartbeat.daemon = True + self.heartbeat.start() + except Exception as errmsg: + log.error("Failed to start heartbeat daemon: %s" % (errmsg)) + finally: + log.debug( + "Wallace heartbeat is %s" % ('not alive', 'alive')[self.heartbeat.is_alive()], + level=8 + ) try: while 1: while self.current_connections >= self.max_connections: + log.debug("Out of connections.") time.sleep(0.5) pair = s.accept() log.info(_("Accepted connection")) - if not pair == None: + if pair is not None: self.current_connections += 1 connection, address = pair - channel = SMTPChannel(self, connection, address) + SMTPChannel(self, connection, address) asyncore.loop() - except Exception, errmsg: + # pylint: disable=broad-except + except Exception: traceback.print_exc() s.shutdown(1) s.close() # shut down hearbeat process self.heartbeat.terminate() + self.timer.cancel() + self.timer.join() def data_header(self, mailfrom, rcpttos): COMMASPACE = ', ' + return "X-Kolab-From: " + mailfrom + "\r\n" + \ - "X-Kolab-To: " + COMMASPACE.join(rcpttos) + "\r\n" + "X-Kolab-To: " + COMMASPACE.join(rcpttos) + "\r\n" def pickup_spool_messages(self, sync=False): # Mind you to include the trailing slash @@ -281,7 +334,6 @@ for filename in files: messages.append((root, filename)) - for root, filename in messages: filepath = os.path.join(root, filename) @@ -296,7 +348,8 @@ log.debug("File is in locks directory. Skipping %s" % (filepath), level=8) continue - except Exception, errmsg: + # pylint: disable=broad-except + except Exception as errmsg: log.error("Error: %s. Skipping %s" % (errmsg, filepath)) continue @@ -374,7 +427,7 @@ # @TODO: and add line separator (\n or \r\n?) # we should make sure there's only one line separator between # kolab headers and the original message (data) - os.write(fp, header); + os.write(fp, header) os.write(fp, data) os.close(fp) @@ -384,20 +437,56 @@ return "250 OK Message %s queued" % (filename) - def reload_config(self, *args, **kw): + def reload_config(self, *args, **kwargs): pass - def remove_pid(self, *args, **kw): - if os.access(conf.pidfile, os.R_OK): - os.remove(conf.pidfile) + def remove_pid(self, *args, **kwargs): + try: + if os.getpid() == self.parent_pid: + log.debug("Stopping process %s" % multiprocessing.current_process().name, level=8) - if self.pool is not None: - self.pool.close() - self.pool.join() + log.debug(_("Terminating processes pool"), level=8) + self.pool.close() - raise SystemExit + if hasattr(self, 'timer'): + if not self.timer.finished.is_set(): + log.debug("Canceling Wallace Timer", level=8) + self.timer.finished.set() + self.timer.cancel() - def run(self): + log.debug(_("Terminating heartbeat process"), level=8) + self.heartbeat.finished.set() + self.heartbeat.terminate() + + self.pool.close() + self.pool.join(5) + self.timer.join(5) + self.heartbeat.join(5) + + if os.access(conf.pidfile, os.R_OK): + log.warning(_("Removing PID file %s") % conf.pidfile) + os.remove(conf.pidfile) + + log.warning("Exiting!") + sys.exit() + + else: + sys.exit(0) + + except Exception as errmsg: + log.debug( + "Exception while trying to stop %s: %s" % ( + multiprocessing.current_process().name, errmsg + ), + level=8 + ) + + sys.exit(1) + + sys.exit(0) + + # pylint: disable=too-many-locals + def run(self): # noqa: C901 """ Run the Wallace daemon. """ @@ -408,7 +497,7 @@ try: (ruid, euid, suid) = os.getresuid() (rgid, egid, sgid) = os.getresgid() - except AttributeError, errmsg: + except AttributeError: ruid = os.getuid() rgid = os.getgid() @@ -418,27 +507,25 @@ # Get group entry details try: ( - group_name, - group_password, - group_gid, - group_members - ) = grp.getgrnam(conf.process_groupname) + group_name, + group_password, + group_gid, + group_members + ) = grp.getgrnam(conf.process_groupname) except KeyError: - print >> sys.stderr, _("Group %s does not exist") % ( - conf.process_groupname - ) + print(_("Group %s does not exist") % (conf.process_groupname)) sys.exit(1) # Set real and effective group if not the same as current. if not group_gid == rgid: log.debug( - _("Switching real and effective group id to %d") % ( - group_gid - ), - level=8 - ) + _("Switching real and effective group id to %d") % ( + group_gid + ), + level=8 + ) os.setregid(group_gid, group_gid) @@ -446,35 +533,33 @@ # Means we haven't switched yet. try: ( - user_name, - user_password, - user_uid, - user_gid, - user_gecos, - user_homedir, - user_shell - ) = pwd.getpwnam(conf.process_username) + user_name, + user_password, + user_uid, + user_gid, + user_gecos, + user_homedir, + user_shell + ) = pwd.getpwnam(conf.process_username) except KeyError: - print >> sys.stderr, _("User %s does not exist") % ( - conf.process_username - ) + print(_("User %s does not exist") % (conf.process_username)) sys.exit(1) - # Set real and effective user if not the same as current. if not user_uid == ruid: log.debug( - _("Switching real and effective user id to %d") % ( - user_uid - ), - level=8 - ) + _("Switching real and effective user id to %d") % ( + user_uid + ), + level=8 + ) os.setreuid(user_uid, user_uid) - except: + # pylint: disable=broad-except + except Exception: log.error(_("Could not change real and effective uid and/or gid")) try: @@ -517,24 +602,24 @@ self.write_pid() self.do_wallace() - except SystemExit, e: - exitcode = e + except SystemExit as errmsg: + exitcode = errmsg except KeyboardInterrupt: exitcode = 1 log.info(_("Interrupted by user")) - except AttributeError, e: + except AttributeError: exitcode = 1 traceback.print_exc() - print >> sys.stderr, _("Traceback occurred, please report a bug at https://issues.kolab.org") + print(_("Traceback occurred, please report a bug.")) - except TypeError, e: + except TypeError as errmsg: exitcode = 1 traceback.print_exc() - log.error(_("Type Error: %s") % e) + log.error(_("Type Error: %s") % errmsg) except: exitcode = 2 traceback.print_exc() - print >> sys.stderr, _("Traceback occurred, please report a bug at https://issues.kolab.org") + print(_("Traceback occurred, please report a bug.")) sys.exit(exitcode) @@ -550,4 +635,4 @@ fp.write("%d\n" % (pid)) fp.close() else: - print >> sys.stderr, _("Could not write pid file %s") % (conf.pidfile) + print(_("Could not write pid file %s") % (conf.pidfile))
View file
pykolab-0.8.13.tar.gz/wallace/module_signature.py
Added
@@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +# Copyright 2010-2019 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, either version 3 of the License, 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 General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import json +import os +import re +import tempfile + +from email.encoders import encode_quopri +from email.parser import Parser +from email.utils import getaddresses + +import modules +import pykolab + +from pykolab.auth import Auth +from pykolab.translate import _ + +# pylint: disable=invalid-name +log = pykolab.getLogger('pykolab.wallace') +conf = pykolab.getConf() + +mybasepath = '/var/spool/pykolab/wallace/signature/' + + +def __init__(): + modules.register('signature', execute, description=description()) + + +def description(): + return """Append a signature to messages.""" + + +def set_part_content(part, content): + # Reset old encoding and use quoted-printable (#5414) + del part['Content-Transfer-Encoding'] + part.set_payload(content) + encode_quopri(part) + + return True + + +def attr_resolve(sender_info, attr): + try: + attr, attr_val = attr.split(':') + except ValueError: + return None + + auth = Auth() + auth.connect() + + values = [] + + if not isinstance(sender_info[attr], list): + sender_info[attr] = [sender_info[attr]] + + for sender_attr_val in sender_info[attr]: + values.append(auth.get_entry_attribute(None, sender_attr_val, attr_val)) + + return ", ".join(values) + + +# pylint: disable=too-many-branches,too-many-locals,too-many-statements +def execute(*args, **kw): # noqa: C901 + if not os.path.isdir(mybasepath): + os.makedirs(mybasepath) + + for stage in ['incoming', 'ACCEPT']: + if not os.path.isdir(os.path.join(mybasepath, stage)): + os.makedirs(os.path.join(mybasepath, stage)) + + # TODO: Test for correct call. + filepath = args[0] + + if 'stage' in kw: + log.debug(_("Issuing callback after processing to stage %s") % (kw['stage']), level=8) + log.debug(_("Testing cb_action_%s()") % (kw['stage']), level=8) + if hasattr(modules, 'cb_action_%s' % (kw['stage'])): + log.debug(_("Attempting to execute cb_action_%s()") % (kw['stage']), level=8) + exec('modules.cb_action_%s(%r, %r)' % (kw['stage'], 'signature', filepath)) + return + + log.debug(_("Executing module signature for %r, %r") % (args, kw), level=8) + + new_filepath = os.path.join( + '/var/spool/pykolab/wallace/signature/incoming', + os.path.basename(filepath) + ) + + os.rename(filepath, new_filepath) + filepath = new_filepath + + # parse message + message = Parser().parse(open(filepath, 'r')) + + sender_address = [ + address for displayname, address in getaddresses(message.get_all('X-Kolab-From')) + ][0] + + auth = Auth() + auth.connect() + + sender_dn = auth.find_recipient(sender_address) + if not sender_dn: + exec('modules.cb_action_%s(%r, %r)' % ('ACCEPT', 'signature', filepath)) + return + + sender_info = auth.get_entry_attributes(None, sender_dn, ['*', 'entrydn', 'manager']) + + log.debug("Sender info: %r" % (sender_info), level=7) + + signature_rules = conf.get_raw('wallace', 'signature_rules') + + if signature_rules: + signature_rules = json.loads(signature_rules) + + log.debug("Signature rules: %r" % (signature_rules), level=7) + + signature_html = None + signature_text = None + + sig_html_conf = conf.get_raw('wallace', 'signature_file_html') + sig_text_conf = conf.get_raw('wallace', 'signature_file_text') + + if sig_html_conf and sig_text_conf: + _sig_html_conf = sig_html_conf % sender_info + _sig_text_conf = sig_text_conf % sender_info + + if not os.path.exists(_sig_html_conf): + _sig_html_conf = '/etc/kolab/signature.d/default.html' + + if not os.path.exists(_sig_text_conf): + _sig_text_conf = '/etc/kolab/signature.d/default.txt' + + if os.path.exists(_sig_html_conf): + signature_html = open(_sig_html_conf, 'r').read() + + if os.path.exists(_sig_text_conf): + signature_text = open(_sig_text_conf, 'r').read() + + if not signature_html and not signature_text: + for signature_rule in signature_rules: + try: + for attr, regex in signature_rule.iteritems(): + if attr == "html": + if not os.path.exists(signature_rule['html']): + raise ValueError + continue + + if attr == "text": + if not os.path.exists(signature_rule['text']): + raise ValueError + continue + + if attr in sender_info and re.match(regex, sender_info[attr], flags=re.IGNORECASE): + success = False + + while not success: + try: + signature_html = open(signature_rule['html'], 'r').read() % sender_info + signature_text = open(signature_rule['text'], 'r').read() % sender_info + + success = True + + except KeyError as errmsg: + sender_info[errmsg] = attr_resolve(sender_info, errmsg) + except ValueError: + continue + + if signature_html is None and signature_text is None: + exec('modules.cb_action_%s(%r, %r)' % ('ACCEPT', 'signature', filepath)) + return + + signature_added = False + + try: + _signature_added = message.get("X-Wallace-Signature") + + # pylint: disable=broad-except + except Exception: + pass + + if _signature_added == "YES": + exec('modules.cb_action_%s(%r, %r)' % ('ACCEPT','signature', filepath)) + return + + for part in message.walk(): + disposition = None + + try: + content_type = part.get_content_type() + + # pylint: disable=broad-except + except Exception: + continue + + try: + disposition = part.get("Content-Disposition") + + # pylint: disable=broad-except + except Exception: + pass + + log.debug("Walking message part: %s; disposition = %r" % (content_type, disposition), level=8) + + if disposition is not None: + continue + + if content_type == "text/plain": + content = part.get_payload(decode=True) + content += "\n\n-- \n%s" % (signature_text) + signature_added = set_part_content(part, content) + + elif content_type == "text/html": + content = part.get_payload(decode=True) + append = "\n<!-- signature appended by Wallace -->\n" + signature_html + if "</body>" in content: + content = content.replace("</body>", append + "</body>") + else: + content = "<html><body>" + content + append + "</body></html>" + signature_added = set_part_content(part, content) + + if signature_added: + log.debug("Signature attached.", level=8) + message.add_header("X-Wallace-Signature", "YES") + + (fp, new_filepath) = tempfile.mkstemp(dir="/var/spool/pykolab/wallace/signature/ACCEPT") + os.write(fp, message.as_string()) + os.close(fp) + os.unlink(filepath) + + exec('modules.cb_action_%s(%r, %r)' % ('ACCEPT','signature', new_filepath))
View file
pykolab-0.8.12.tar.gz/wallace/modules.py -> pykolab-0.8.13.tar.gz/wallace/modules.py
Changed
@@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com) +# Copyright 2010-2019 Kolab Systems AG (http://www.kolabsys.com) # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # @@ -17,6 +17,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +from __future__ import print_function + import os import sys import time @@ -45,6 +47,7 @@ modules = {} + def __init__(): # We only want the base path modules_base_path = os.path.dirname(__file__) @@ -55,15 +58,16 @@ for filename in filenames: if filename.startswith('module_') and filename.endswith('.py'): - module_name = filename.replace('.py','') + module_name = filename.replace('.py', '') name = module_name.replace('module_', '') - #print "exec(\"from %s import __init__ as %s_register\"" % (module_name,name) + # print("exec(\"from %s import __init__ as %s_register\")" % (module_name,name)) exec("from %s import __init__ as %s_register" % (module_name, name)) exec("%s_register()" % (name)) for dirname in dirnames: register_group(modules_path, dirname) + def list_modules(*args, **kw): """ List modules @@ -75,8 +79,8 @@ if isinstance(module, tuple): module_group, module = module __modules[module_group] = { - module: modules[(module_group,module)] - } + module: modules[(module_group, module)] + } else: __modules[module] = modules[module] @@ -84,38 +88,45 @@ _modules.sort() for _module in _modules: - if __modules[_module].has_key('function'): + if 'function' in __modules[_module]: # This is a top-level module - if not __modules[_module]['description'] == None: - print "%-25s - %s" % (_module.replace('_','-'),__modules[_module]['description']) + if __modules[_module]['description'] is not None: + print("%-25s - %s" % (_module.replace('_', '-'), __modules[_module]['description'])) else: - print "%-25s" % (_module.replace('_','-')) + print("%-25s" % (_module.replace('_', '-'))) for _module in _modules: - if not __modules[_module].has_key('function'): + if 'function' not in __modules[_module]: # This is a nested module - print "\n" + _("Module Group: %s") % (_module) + "\n" + print("\n" + _("Module Group: %s") % (_module) + "\n") ___modules = __modules[_module].keys() ___modules.sort() for __module in ___modules: - if not __modules[_module][__module]['description'] == None: - print "%-4s%-21s - %s" % ('',__module.replace('_','-'),__modules[_module][__module]['description']) + if __modules[_module][__module]['description'] is not None: + print( + "%-4s%-21s - %s" % ( + '', + _module.replace('_', '-'), + __modules[_module][__module]['description'] + ) + ) + else: - print "%-4s%-21s" % ('',__module.replace('_','-')) + print("%-4s%-21s" % ('', __module.replace('_', '-'))) + def execute(name, *args, **kw): - if not modules.has_key(name): + if name not in modules: log.error(_("No such module %r in modules %r (1).") % (name, modules)) sys.exit(1) - if not modules[name].has_key('function') and \ - not modules[name].has_key('group'): - log.error(_("No such module %r in modules %r (2).") %(name, modules)) + if 'function' not in modules[name] and 'group' not in modules[name]: + log.error(_("No such module %r in modules %r (2).") % (name, modules)) sys.exit(1) try: return modules[name]['function'](*args, **kw) - except Exception, errmsg: + except Exception as errmsg: log.exception(_("Module %r - Unknown error occurred; %r") % (name, errmsg)) def heartbeat(name, *args, **kw): @@ -156,35 +167,35 @@ success = True break - except smtplib.SMTPServerDisconnected, errmsg: + except smtplib.SMTPServerDisconnected as errmsg: log.error("SMTP Server Disconnected Error, %r" % (errmsg)) - except smtplib.SMTPConnectError, errmsg: + except smtplib.SMTPConnectError as errmsg: # DEFER log.error("SMTP Connect Error, %r" % (errmsg)) - except smtplib.SMTPDataError, errmsg: + except smtplib.SMTPDataError as errmsg: # DEFER log.error("SMTP Data Error, %r" % (errmsg)) - except smtplib.SMTPHeloError, errmsg: + except smtplib.SMTPHeloError as errmsg: # DEFER log.error("SMTP HELO Error, %r" % (errmsg)) - except smtplib.SMTPRecipientsRefused, errmsg: + except smtplib.SMTPRecipientsRefused as errmsg: # REJECT, send NDR log.error("SMTP Recipient(s) Refused, %r" % (errmsg)) - except smtplib.SMTPSenderRefused, errmsg: + except smtplib.SMTPSenderRefused as errmsg: # REJECT, send NDR log.error("SMTP Sender Refused, %r" % (errmsg)) - except Exception, errmsg: + except Exception as errmsg: log.exception(_("smtplib - Unknown error occurred: %r") % (errmsg)) try: smtp.quit() - except Exception, errmsg: + except Exception as errmsg: log.error("smtplib quit() error - %r" % errmsg) time.sleep(10) @@ -231,7 +242,7 @@ #now = datetime.datetime.now() #delta = now - fileage - #print "file:", filepath, "fileage:", fileage, "now:", now, "delta(seconds):", delta.seconds + #print("file:", filepath, "fileage:", fileage, "now:", now, "delta(seconds):", delta.seconds) #if delta.seconds > 1800: ## TODO: Send NDR back to user
View file
pykolab-0.8.12.tar.gz/wallace/wallace.systemd -> pykolab-0.8.13.tar.gz/wallace/wallace.systemd
Changed
@@ -10,7 +10,7 @@ EnvironmentFile=/etc/sysconfig/wallace ExecStart=/usr/sbin/wallaced $FLAGS --pid-file /run/wallaced/wallaced.pid ExecReload=/bin/kill -HUP $MAINPID -ExecStop=/bin/kill -TERM $MAINPID +ExecStop=/bin/kill -KILL $MAINPID [Install] WantedBy=multi-user.target
View file
pykolab.dsc
Changed
@@ -2,7 +2,7 @@ Source: pykolab Binary: pykolab, kolab-cli, kolab-conf, kolab-saslauthd, kolab-server, kolab-telemetry, kolab-xml, wallace Architecture: all -Version: 0.8.12-0~kolab5 +Version: 0.8.13-0~kolab1 Maintainer: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Uploaders: Paul Klos <kolab@klos2day.nl> Homepage: http://www.kolab.org @@ -40,5 +40,5 @@ pykolab deb python optional wallace deb python optional Files: - 00000000000000000000000000000000 0 pykolab-0.8.12.tar.gz + 00000000000000000000000000000000 0 pykolab-0.8.13.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.