Projects
Kolab:16
pykolab
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 21
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,8 +1,14 @@ +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 - * Ubuntu Xenial: pykolab requires now python-pymysql because /usr/lib/postfix/kolab_smtp_access_policy needs module pymysql + * pykolab requires now python-pymysql because /usr/lib/postfix/kolab_smtp_access_policy needs module pymysql on Ubuntu Xenial - -- Timotheus Pokorra <tp@tbits.net> Tue, 30 May 2017 01:49:00 +0100 + -- Timotheus Pokorra <tp@tbits.net> Thu, 25 May 2017 01:49:00 +0100 pykolab (0.8.7-0~kolab1) unstable; urgency=low
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() + + return created + def user_mailbox_delete(self, mailbox_base_name): """ Delete a user mailbox.
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
.