Projects
Kolab:Winterfell
pykolab
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 37
View file
pykolab.spec
Changed
@@ -29,7 +29,7 @@ Summary: Kolab Groupware Solution Name: pykolab -Version: 0.8.7 +Version: 0.8.8 Release: 1%{?dist} License: GPLv3+ Group: Applications/System @@ -71,7 +71,11 @@ BuildRequires: python-kolab BuildRequires: python-kolabformat BuildRequires: python-ldap +%if 0%{?fedora} > 24 +BuildRequires: python2-nose +%else BuildRequires: python-nose +%endif BuildRequires: python-pep8 BuildRequires: python-pyasn1 BuildRequires: python-pyasn1-modules @@ -580,6 +584,9 @@ %attr(0700,%{kolab_user},%{kolab_group}) %dir %{_var}/spool/pykolab/wallace %changelog +* Thu Mar 8 2018 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> - 0.8.8-1 +- Release of version 0.8.8 + * Tue Dec 13 2016 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> - 0.8.7-1 - Release of version 0.8.7
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +pykolab (0.8.8-0~kolab1) unstable; urgency=low + + * Upstream release of version 0.8.8 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Thu, 8 Mar 2018 01:49:00 +0100 + pykolab (0.8.7-0~kolab2) unstable; urgency=low * pykolab requires now python-pymysql because /usr/lib/postfix/kolab_smtp_access_policy needs module pymysql on Ubuntu Xenial
View file
pykolab-0.8.7.tar.gz/configure.ac -> pykolab-0.8.8.tar.gz/configure.ac
Changed
@@ -1,4 +1,4 @@ -AC_INIT([pykolab], 0.8.7) +AC_INIT([pykolab], 0.8.8) AC_SUBST([RELEASE], 1) AC_CONFIG_SRCDIR(pykolab/constants.py.in)
View file
pykolab-0.8.7.tar.gz/pykolab/auth/ldap/__init__.py -> pykolab-0.8.8.tar.gz/pykolab/auth/ldap/__init__.py
Changed
@@ -232,6 +232,24 @@ return False + except ldap.NO_SUCH_OBJECT: + log.error( + _("Invalid DN, username and/or password for '%s'.") % ( + bind_dn + ) + ) + + return False + + except ldap.INVALID_CREDENTIALS: + log.error( + _("Invalid DN, username and/or password for '%s'.") % ( + bind_dn + ) + ) + + return False + except Exception, errmsg: log.error(_("Exception occurred: %r") % (errmsg)) log.error(_("%s") % (traceback.format_exc())) @@ -246,6 +264,9 @@ level=8 ) + # Remove referrals + _result_data = [_e for _e in _result_data if _e[0] is not None] + if len(_result_data) == 1: (entry_dn, entry_attrs) = _result_data[0] @@ -1432,8 +1453,13 @@ bind_pw = self.config_get('service_bind_pw') if bind_dn is not None: - log.debug(_("Binding with bind_dn: %s and password: %s") - % (bind_dn, '*' * len(bind_pw))) + log.debug( + _("Binding with bind_dn: %s and password: %s") % ( + bind_dn, + '*' * len(bind_pw) + ), + level=8 + ) # TODO: Binding errors control try: @@ -1449,8 +1475,21 @@ return False + except ldap.NO_SUCH_OBJECT: + log.error( + _("Invalid DN, username and/or password for '%s'.") % ( + bind_dn + ) + ) + + return False + except ldap.INVALID_CREDENTIALS: - log.error(_("Invalid DN, username and/or password.")) + log.error( + _("Invalid DN, username and/or password for '%s'.") % ( + bind_dn + ) + ) return False @@ -1474,7 +1513,12 @@ log.error(_("%s") % (traceback.format_exc())) return False except ldap.INVALID_CREDENTIALS: - log.error(_("Invalid DN, username and/or password.")) + log.error( + _("Invalid DN, username and/or password for '%s'.") % ( + bind_dn + ) + ) + return False else: log.debug(_("bind_priv() called but already bound"), level=8) @@ -2036,7 +2080,7 @@ ) if not self.imap.has_folder(imap_mailbox): - self.imap_user_mailbox_create( + self.imap.user_mailbox_create( entry[result_attribute] )
View file
pykolab-0.8.7.tar.gz/pykolab/imap/__init__.py -> pykolab-0.8.8.tar.gz/pykolab/imap/__init__.py
Changed
@@ -33,6 +33,7 @@ log = pykolab.getLogger('pykolab.imap') conf = pykolab.getConf() + class IMAP(object): def __init__(self): # Pool of named IMAP connections, by hostname @@ -44,12 +45,15 @@ def cleanup_acls(self, aci_subject): lm_suffix = "" - log.info(_("Cleaning up ACL entries for %s across all folders") % (aci_subject)) + log.info( + _("Cleaning up ACL entries for %s across all folders") % ( + aci_subject + ) + ) if len(aci_subject.split('@')) > 1: lm_suffix = "@%s" % (aci_subject.split('@')[1]) - shared_folders = self.imap.lm( "shared/*%s" % (lm_suffix) ) @@ -72,17 +76,38 @@ # ... loop through them and ... for folder in folders: - # ... list the ACL entries - acls = self.imap.lam(folder) - - # For each ACL entry, see if we think it is a current, valid entry - for acl_entry in acls.keys(): - # If the key 'acl_entry' does not exist in the dictionary of valid - # ACL entries, this ACL entry has got to go. - if acl_entry == aci_subject: - # Set the ACL to '' (effectively deleting the ACL entry) - log.debug(_("Removing acl %r for subject %r from folder %r") % (acls[acl_entry],acl_entry,folder), level=8) - self.set_acl(folder, acl_entry, '') + # ... list the ACL entries -- but only if the folder still exists + if self.imap.has_folder(folder): + acls = self.imap.lam(folder) + + # For each ACL entry, see if we think it is a current, valid + # entry + for acl_entry in acls.keys(): + # If the key 'acl_entry' does not exist in the dictionary + # of valid ACL entries, this ACL entry has got to go. + if acl_entry == aci_subject: + # Set the ACL to '' (effectively deleting the ACL + # entry) + log.debug( + _( + "Removing acl %r for subject %r from folder %r" + ) % ( + acls[acl_entry], + acl_entry, + folder + ), + level=8 + ) + + self.set_acl(folder, acl_entry, '') + else: + log.debug( + _("Folder %r disappeared (ACL cleanup for %r") % ( + folder, + aci_subject + ), + level=8 + ) def connect(self, uri=None, server=None, domain=None, login=True): """ @@ -508,36 +533,12 @@ folder_name = "user%s%s" % (self.get_separator(), mailbox_base_name) log.info(_("Creating new mailbox for user %s") %(mailbox_base_name)) - max_tries = 10 - success = False - while not success and max_tries > 0: - success = self.create_folder(folder_name, server) - if not success: - self.disconnect() - max_tries -= 1 - time.sleep(1) - self.connect() + success = self._create_folder_waiting(folder_name, server) if not success: log.error(_("Could not create the mailbox for user %s, aborting." % (mailbox_base_name))) return False - # In a Cyrus IMAP Murder topology, wait for the murder to have settled - if self.imap_murder(): - self.disconnect() - self.connect() - - created = False - last_log = time.time() - while not created: - created = self.has_folder(folder_name) - if not created: - if time.time() - last_log > 5: - log.info(_("Waiting for the Cyrus IMAP Murder to settle...")) - last_log = time.time() - - time.sleep(0.5) - _additional_folders = None if not hasattr(self, 'domain'): @@ -628,7 +629,6 @@ last_log = time.time() while not success: try: - self.disconnect() self.connect(login=False, server=server) self.login_plain(admin_login, admin_password, user) @@ -654,28 +654,11 @@ log.error(_("Correcting additional folder name from %r to %r") % (folder_name, "%s%s" % (personal, folder_name))) folder_name = "%s%s" % (personal, folder_name) - try: - self.create_folder(folder_name) - created = False - last_log = time.time() - while not created: - created = self.has_folder(folder_name) - if not created: - if time.time() - last_log > 5: - log.info(_("Waiting for the Cyrus IMAP Murder to settle...")) - if time.time() - last_log > 30: - log.warning(_("Waited for 30 seconds, going to reconnect")) - self.disconnect() - self.connec() - last_log = time.time() + success = self._create_folder_waiting(folder_name) - time.sleep(0.5) - except: - log.warning(_("Mailbox already exists: %s") % (folder_name)) - if conf.debuglevel > 8: - import traceback - traceback.print_exc() + if not success: + log.warning(_("Failed to create folder: %s") % (folder_name)) continue if additional_folders[additional_folder].has_key("annotations"): @@ -782,6 +765,50 @@ except: log.error(_("Could not rename %s to reside on partition %s") % (folder_name, partition)) + def _create_folder_waiting(self, folder_name, server=None): + """ + Create a folder and wait to make sure it exists + """ + + created = False + + try: + max_tries = 10 + while not created and max_tries > 0: + created = self.create_folder(folder_name, server) + if not created: + self.disconnect() + max_tries -= 1 + time.sleep(1) + self.connect() + + # In a Cyrus IMAP Murder topology, wait for the murder to have settled + if created and self.imap_murder(): + success = False + last_log = time.time() + reconnect_counter = 0 + while not success: + success = self.has_folder(folder_name) + if not success: + if time.time() - last_log > 5: + reconnect_counter += 1 + log.info(_("Waiting for the Cyrus IMAP Murder to settle...")) + if reconnect_counter == 6: + log.warning(_("Waited for 15 seconds, going to reconnect")) + reconnect_counter = 0 + self.disconnect() + self.connect() + + last_log = time.time() + + time.sleep(0.5) + except: + if conf.debuglevel > 8: + import traceback + traceback.print_exc() +
View file
pykolab-0.8.7.tar.gz/pykolab/imap/cyrus.py -> pykolab-0.8.8.tar.gz/pykolab/imap/cyrus.py
Changed
@@ -173,8 +173,8 @@ _mailfolder = self.parse_mailfolder(mailfolder) - prefix = _mailfolder['path_parts'].pop(0) - mbox = _mailfolder['path_parts'].pop(0) + prefix = _mailfolder['path_parts'][0] + mbox = _mailfolder['path_parts'][1] if _mailfolder['domain'] is not None: mailfolder = "%s%s%s@%s" % ( prefix, @@ -184,8 +184,14 @@ ) # TODO: Workaround for undelete - if len(self.lm(mailfolder)) < 1: - return self.server + if len(self.lm(mailfolder)) < 1 and _mailfolder['hex_timestamp']: + mailfolder = self.folder_utf7("DELETED/%s%s%s@%s" % ( + self.separator.join(_mailfolder['path_parts']), + self.separator, + _mailfolder['hex_timestamp'], + _mailfolder['domain']) + ) + # TODO: Murder capabilities may have been suppressed using Cyrus IMAP # configuration. @@ -219,17 +225,19 @@ max_tries = 20 num_try = 0 - annotation_path = "/shared/vendor/cmu/cyrus-imapd/server" + ann_path = "/vendor/cmu/cyrus-imapd/server" + s_ann_path = "/shared%s" % (ann_path) while 1: num_try += 1 annotations = self._getannotation( - mailfolder, - annotation_path + '"%s"' % (mailfolder), + ann_path ) if annotations.has_key(mailfolder): - break + if annotations[mailfolder].has_key(s_ann_path): + break if max_tries <= num_try: log.error( @@ -240,7 +248,7 @@ annotations = { mailfolder: { - annotation_path: self.server + s_ann_path: self.server } } @@ -255,7 +263,7 @@ time.sleep(1) - server = annotations[mailfolder][annotation_path] + server = annotations[mailfolder][s_ann_path] self.mbox[mailfolder] = server log.debug(
View file
pykolab-0.8.7.tar.gz/pykolab/xml/event.py -> pykolab-0.8.8.tar.gz/pykolab/xml/event.py
Changed
@@ -880,7 +880,8 @@ if attr == "categories": self.add_category(value) elif attr == "class": - self.set_classification(value) + if (value and value[:2] not in ['X-', 'x-']): + self.set_classification(value) elif attr == "recurrenceid": self.set_ical_recurrenceid(value, params) elif hasattr(self, ical_setter): @@ -1035,7 +1036,7 @@ self.event.setSequence(int(sequence)) def set_url(self, url): - self.event.setUrl(str(url)) + self.event.setUrl(ustr(url)) def set_recurrence(self, recurrence): self.event.setRecurrenceRule(recurrence)
View file
pykolab-0.8.7.tar.gz/share/templates/header_checks.submission -> pykolab-0.8.8.tar.gz/share/templates/header_checks.submission
Changed
@@ -2,3 +2,5 @@ /^Received:.*127\.0\.0\.1/ IGNORE /^User-Agent:/ IGNORE /^X-Mailer:/ IGNORE +/^Sender:/ IGNORE +/^X-Sender:/ IGNORE
View file
pykolab-0.8.7.tar.gz/share/templates/master.cf.tpl -> pykolab-0.8.8.tar.gz/share/templates/master.cf.tpl
Changed
@@ -85,6 +85,7 @@ # Filter email through Wallace smtp-wallace unix - - n - 3 smtp + -o default_destination_recipient_limit=1 -o smtp_data_done_timeout=1800 -o disable_dns_lookups=yes -o smtp_send_xforward_command=yes
View file
pykolab-0.8.7.tar.gz/wallace/module_invitationpolicy.py -> pykolab-0.8.8.tar.gz/wallace/module_invitationpolicy.py
Changed
@@ -419,8 +419,8 @@ # compare sequence number to determine a (re-)scheduling request if existing is not None: - log.debug(_("Existing %s: %r") % (existing.type, existing), level=9) scheduling_required = itip_event['sequence'] > 0 and itip_event['sequence'] > existing.get_sequence() + log.debug(_("Scheduling required: %r, for existing %s: %s") % (scheduling_required, existing.type, existing.get_uid()), level=8) save_object = True # if scheduling: check availability (skip that for tasks) @@ -774,14 +774,14 @@ return True -def list_user_folders(user_rec, type): +def list_user_folders(user_rec, _type): """ Get a list of the given user's private calendar/tasks folders """ global imap # return cached list - if user_rec.has_key('_imap_folders'): + if '_imap_folders' in user_rec: return user_rec['_imap_folders'] result = [] @@ -789,39 +789,84 @@ if not imap_proxy_auth(user_rec): return result - folders = imap.list_folders('*') - log.debug(_("List %r folders for user %r: %r") % (type, user_rec['mail'], folders), level=8) + folders = imap.get_metadata('*') + + log.debug( + _("List %r folders for user %r: %r") % ( + _type, + user_rec['mail'], + folders + ), + level=8 + ) (ns_personal, ns_other, ns_shared) = imap.namespaces() - for folder in folders: - # exclude shared and other user's namespace - if ns_other is not None and folder.startswith(ns_other) and '_delegated_mailboxes' in user_rec: - # allow shared folders from delegators - if len([_mailbox for _mailbox in user_rec['_delegated_mailboxes'] if folder.startswith(ns_other + _mailbox + '/')]) == 0: + _folders = {} + + # Filter the folders by type relevance + for folder, metadata in folders.items(): + key = '/shared' + FOLDER_TYPE_ANNOTATION + if key in metadata: + if metadata[key].startswith(_type): + _folders[folder] = metadata + + key = '/private' + FOLDER_TYPE_ANNOTATION + if key in metadata: + if metadata[key].startswith(_type): + _folders[folder] = metadata + + for folder, metadata in _folders.items(): + folder_delegated = False + + # Exclude shared and other user's namespace + # + # First, test if this is another users folder + if ns_other is not None and folder.startswith(ns_other): + # If we have no delegated mailboxes, we can skip this entirely + if '_delegated_mailboxes' not in user_rec: + continue + + for _m in user_rec['_delegated_mailboxes']: + if folder.startswith(ns_other + _m + '/'): + folder_delegated = True + + if not folder_delegated: continue + # TODO: list shared folders the user has write privileges ? - if ns_shared is not None and len([_ns for _ns in ns_shared if folder.startswith(_ns)]) > 0: - continue - - metadata = imap.get_metadata(folder) - log.debug(_("IMAP metadata for %r: %r") % (folder, metadata), level=9) - if metadata.has_key(folder) and ( \ - metadata[folder].has_key('/shared' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/shared' + FOLDER_TYPE_ANNOTATION].startswith(type) \ - or metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].startswith(type)): - result.append(folder) - - if metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION): - # store default folder in user record - if metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.default'): - user_rec['_default_folder'] = folder - - # store private and confidential folders in user record - if metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.confidential') and not user_rec.has_key('_confidential_folder'): + if ns_shared is not None: + if len([_ns for _ns in ns_shared if folder.startswith(_ns)]) > 0: + continue + + key = '/shared' + FOLDER_TYPE_ANNOTATION + if key in metadata: + if metadata[key].startswith(_type): + result.append(folder) + + key = '/private' + FOLDER_TYPE_ANNOTATION + if key in metadata: + if metadata[key].startswith(_type): + result.append(folder) + + # store default folder in user record + if metadata[key].endswith('.default'): + user_rec['_default_folder'] = folder + continue + + # store private and confidential folders in user record + if metadata[key].endswith('.confidential'): + if '_confidential_folder' not in user_rec: user_rec['_confidential_folder'] = folder - if metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.private') and not user_rec.has_key('_private_folder'): + + continue + + if metadata[key].endswith('.private'): + if '_private_folder' not in user_rec: user_rec['_private_folder'] = folder + continue + # cache with user record user_rec['_imap_folders'] = result
View file
pykolab-0.8.7.tar.gz/wallace/module_resources.py -> pykolab-0.8.8.tar.gz/wallace/module_resources.py
Changed
@@ -432,6 +432,9 @@ resource_dns = auth.find_resource('*') + # Remove referrals + resource_dns = [dn for dn in resource_dns if dn is not None] + # filter by resource_base_dn resource_base_dn = conf.get('ldap', 'resource_base_dn', None) if resource_base_dn is not None:
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.7-0~kolab2 +Version: 0.8.8-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.7.tar.gz + 00000000000000000000000000000000 0 pykolab-0.8.8.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
.