Projects
Kolab:3.4
pykolab
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 93
View file
pykolab-0.7.tar.gz/bin/kolab_parse_telemetry.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/bin/kolab_smtp_access_policy.py
Changed
@@ -4,18 +4,18 @@ # # 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. +# 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 datetime
View file
pykolab-0.7.tar.gz/conf.py
Changed
@@ -5,18 +5,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # """ Kolab configuration utility.
View file
pykolab-0.7.tar.gz/conf/kolab.conf
Changed
@@ -234,6 +234,10 @@ ; The attribute that holds the quota. quota_attribute = mailquota + +; The format of the modifytimestamp attribute values +modifytimestamp_format = %Y%m%d%H%M%SZ + ; A unique attribute that can be used to identify the entry beyond renames and ; moves. Note that 'nsuniqueid' is specific to all Netscape-based directory ; services. @@ -361,10 +365,13 @@ result_attribute = mail [wallace] -modules = resources, footer +modules = resources, invitationpolicy, footer footer_text = /etc/kolab/footer.text footer_html = /etc/kolab/footer.html +; default settings for kolabInvitationPolicy +kolab_invitation_policy = ACT_ACCEPT_IF_NO_CONFLICT:example.org, ACT_MANUAL + ; This is a domain name space specific section, that enables us to override ; all settings, for example, the LDAP URI, base and bind DNs, scopes, filters, ; etc. Note that overriding the LDAP settings for the primary domain name space
View file
pykolab-0.7.tar.gz/cyruslib.py
Changed
@@ -5,19 +5,18 @@ # Copyright (C) 2003-2006 Gianluigi Tiesi <sherpya@netfarm.it> # Copyright (C) 2003-2006 NetFarm S.r.l. [http://www.netfarm.it] # -# This program is free software; you can redistribute it and/or modify +# 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 2 of the License, or +# the Free Software Foundation, either version 2 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, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # # Requires python >= 2.3 #
View file
pykolab-0.7.tar.gz/kolab-cli.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/kolabd.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/kolabd/__init__.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # """
View file
pykolab-0.7.tar.gz/kolabd/process.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import multiprocessing
View file
pykolab-0.7.tar.gz/po/POTFILES.in
Changed
@@ -12,11 +12,10 @@ ext/python/Tools/freeze/makemakefile.py ext/python/Tools/freeze/parsesetup.py ext/python/Tools/freeze/winmakemakefile.py +kolab-cli.py kolabd/__init__.py kolabd/process.py kolabd.py -kolab/__init__.py -kolab.py pykolab/auth/__init__.py pykolab/auth/ldap/auth_cache.py pykolab/auth/ldap/cache.py @@ -84,11 +83,13 @@ pykolab/imap/__init__.py pykolab/imap_utf7.py pykolab/__init__.py +pykolab/itip/__init__.py pykolab/logger.py pykolab/plugins/defaultfolders/__init__.py pykolab/plugins/dynamicquota/__init__.py pykolab/plugins/__init__.py pykolab/plugins/recipientpolicy/__init__.py +pykolab/plugins/roundcubedb/__init__.py pykolab/plugins/sievemgmt/__init__.py pykolab/setup/components.py pykolab/setup/__init__.py @@ -137,6 +138,8 @@ tests/functional/test_wallace/test_004_nonascii_addresses.py tests/functional/test_wallace/test_005_resource_add.py tests/functional/test_wallace/test_005_resource_invitation.py +tests/functional/test_wallace/test_006_resource_performance.py +tests/functional/test_wallace/test_007_invitationpolicy.py tests/functional/test_wap_client/__init__.py tests/functional/test_wap_client/test_001_connect.py tests/functional/test_wap_client/test_002_user_add.py @@ -160,12 +163,18 @@ tests/unit/test-008-sievelib.py tests/unit/test-009-parse_ldap_uri.py tests/unit/test-010-transliterate.py +tests/unit/test-011-itip.py tests/unit/test-011-wallace_resources.py +tests/unit/test-012-wallace_invitationpolicy.py +tests/unit/test-014-conf-and-raw.py +tests/unit/test-015-translate.py test-wallace.py ucs/kolab_sieve.py ucs/listener.py wallace/__init__.py wallace/module_footer.py +wallace/module_gpgencrypt.py +wallace/module_invitationpolicy.py wallace/module_optout.py wallace/module_resources.py wallace/modules.py
View file
pykolab-0.7.tar.gz/po/POTFILES.skip
Changed
@@ -1,214 +1,70 @@ -activate_domain.py -bin/test_parse_policy.py -bin/test-read-input.py -bonnie/__init__.py -bonnie.py -demo.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/about.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/authentication.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/data.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/environ.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/error.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/index.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/login.mak.py -kwap/data/templates/home/kanarip/devel/src/kolab/pykolab.git/kwap/kwap/templates/master.mak.py -kwap/ez_setup/__init__.py -kwap/kwap/config/app_cfg.py -kwap/kwap/config/environment.py -kwap/kwap/config/__init__.py -kwap/kwap/config/middleware.py -kwap/kwap/controllers/domain.py -kwap/kwap/controllers/error.py -kwap/kwap/controllers/__init__.py -kwap/kwap/controllers/root.py -kwap/kwap/controllers/secure.py -kwap/kwap/controllers/template.py -kwap/kwap/grids/domains.py -kwap/kwap/grids/__init__.py -kwap/kwap/__init__.py -kwap/kwap/lib/app_globals.py -kwap/kwap/lib/base.py -kwap/kwap/lib/helpers.py -kwap/kwap/lib/__init__.py -kwap/kwap/model/auth.py -kwap/kwap/model/__init__.py -kwap/kwap/templates/domain/__init__.py -kwap/kwap/templates/__init__.py -kwap/kwap/tests/functional/__init__.py -kwap/kwap/tests/functional/test_authentication.py -kwap/kwap/tests/functional/test_root.py -kwap/kwap/tests/__init__.py -kwap/kwap/tests/models/__init__.py -kwap/kwap/tests/models/test_auth.py -kwap/kwap/websetup/bootstrap.py -kwap/kwap/websetup/__init__.py -kwap/kwap/websetup/schema.py -kwap/setup.py -munich_demo.py -play/anon-imap/anon-imap.py -play/augeas-insert.py -play/base_64_decode.py -play/brepr_vs_unicode.py -play/cleanup_acls.py -play/cliconfmgmt.py -play/conf-add-file-to-service.py -play/conf-add-setting.py -play/conf-list-config-files.py -play/confmgmt/augeas.py -play/confmgmt/db.py -play/confmgmt/__init__.py -play/confmgmt/model.py -play/conf.py -play/conf-settings-from-file.py -play/conf-update-file.py -play/detect-object-type.py -play/dttz.py -play/effectiverights.py -play/flawed_zpush_testing_create_folders.py -play/fork.py -play/get_uid.py -play/imap_annotations_test.py -play/kolab-sap/kolab_smtp_access_policy.py -play/libkolabxml/contact.py -play/libkolabxml/event_imap.py -play/libkolabxml/event.py -play/libkolabxml/event_rfc822.py -play/libkolabxml/todo.py -play/load_test.py -play/migrate_lowercase_uid.py -play/migrate_mail_to_uid_prod.py -play/migrate_mail_to_uid.py -play/migrate_uid_to_mail_prod.py -play/migrate_uid_to_mail.py -play/noheaderini.py -play/not-an-itip-message.py -play/openssl/license.py -play/parallel_persistent_searches.py -play/parse_policy.py -play/persistent_search_kolab_23.py -play/persistent_search.py -play/pooling.py -play/purge_users_roundcube.py -play/push_contacts.py -play/pygpgme/sign.py -play/pygpgme/verify.py -play/regexps.py -play/rolequota/__init__.py -play/roundcube_database/identities.py -play/roundcube_database/__init__.py -play/roundcube_database.py -play/roundcube_database/users.py -play/split_message_file.py -play/sqlalchemy_schemadisplay.py -play/strip_many_headers.py -play/sync_client.py -play/sync_repl_kolab_23.py -play/test_augeas_load.py -play/test_cal_spread.py -play/test-entitlements.py -play/test_filter.py -play/test_folders.py -play/test-icalendar-attendee.py -play/test_imapd.py -play/test_imap.py -play/test-kolab-smtp-access-policy-load.py -play/test_kolabxml.py -play/test-login-as.py -play/test-namespace.py -play/test-output.py -play/test_page_control.py -play/test-parse_ldap_uri.py -play/test.py -play/test_sk.ks.c.py -play/test_socket_client.py -play/test_socket.py -play/test_submission.py -play/test_undelete.py -play/translit.py -play/unicode_test.py -play/unicode-to-ascii.py -play/wap/domain.info.py -play/wap/domains.capabilities.py -play/wap/domains.list.py -play/wap/form_value.generate_cn.py -play/wap/form_value.generate_displayname.py -play/wap/form_value.generate_mail.py -play/wap/form_value.generate_password.py -play/wap/form_value.generate_uid.py -play/wap/form_value.list_options-c.py -play/wap/form_value.select_options-ou.py -play/wap/form_value.select_options-preferredlanguage.py -play/wap/group.add.py -play/wap/group.info.py -play/wap/group.members_list.py -play/wap/groups.list.py -play/wap/group_types.list.py -play/wap/role.add.py -play/wap/role.capabilities.py -play/wap/role.delete.py -play/wap/role.find_by_attribute.py -play/wap/role.info.py -play/wap/roles.list.py -play/wap/scu.py -play/wap/system.capabilities.py -play/wap/system.select_domain.py -play/wap/user.add.py -play/wap/user.delete.py -play/wap/user.edit.py -play/wap/user.info.py -play/wap/users.list.py -play/wap/user_types.list.py -play/xmlevent.py -play/xmlformat.py -play/xmlfromical.py -play/zorbadb/test.py -pykolab/auth/ldap/fds/__init__.py -pykolab/auth/ldap/msds/__init__.py -pykolab/auth/ldap/openldap/__init__.py -pykolab/auth/ldap/rhds/__init__.py -pykolab/auth/ldap/sunds/__init__.py -pykolab/auth/sql/__init__.py -pykolab/cli/cmd_examine_message.py -pykolab/cli/cmd_list_contacts.py -pykolab/cli/cmd_list_events.py -pykolab/cli/cmd_rebalance_mailboxes.py -pykolab/cli/cmd_role_info.py -pykolab/cli/cmd_set_quota.py -pykolab/cli/cmd_summarize_quota_allocation.py -pykolab/confmgmt/augeas.py -pykolab/conf/parser.py +kolabd/.___init__.py +pykolab/auth/.___init__.py +pykolab/auth/ldap/._cache.py +pykolab/auth/ldap/.___init__.py +pykolab/._base.py +pykolab/cli/._cmd_create_mailbox.py +pykolab/cli/._cmd_list_mailbox_metadata.py +pykolab/cli/._cmd_list_quota.py +pykolab/cli/._cmd_set_language.py +pykolab/cli/._cmd_set_mailbox_acl.py +pykolab/cli/._cmd_set_mail.py +pykolab/conf/._defaults.py +pykolab/conf/.___init__.py +pykolab/._constants.py pykolab/constants.py -pykolab/ical/itip.py -pykolab/imap/dovecot.py -pykolab/plugins/roundcube/__init__.py -pykolab/wap_client.old/__init__.py -pykolab/xml/task.py -sievelib-0.5/setup.py -sievelib-0.5/sievelib/commands.py -sievelib-0.5/sievelib/digest_md5.py -sievelib-0.5/sievelib/factory.py -sievelib-0.5/sievelib/__init__.py -sievelib-0.5/sievelib/managesieve.py -sievelib-0.5/sievelib/parser.py -testaci.py -test-ask_menu.py -test-search.py -test-send-mail-kolab_smtp_access_policy.py -test-send-mail-kolab_smtp_access_policy-relay.py -tests/functional/test_kolabd/test_004_many_aliases.py -test-subscribe-address-to-ml.py -tests/unit/test-011-base64_encoded_contact.py -tests/unit/test-012-utf7.py -test-urllib.py -test-wallace-loadmsg.py -test-wallace-resource.py -test-wallace-send.py -wallace/future_module_bcc.py -wallace/future_module_conversations.py -wallace/future_module_correctsentdate.py -wallace/future_module_dlp.py -wallace/future_module_footer.py -wallace/future_module_freebusy.py -wallace/future_module_googletranslate.py -wallace/future_module_statistics.py -wap_raw.py +pykolab/._constants.py.in +pykolab/imap/._cyrus.py +pykolab/imap/.___init__.py +pykolab/.___init__.py +pykolab/itip/.___init__.py +pykolab/._logger.py +pykolab/plugins/dynamicquota/.___init__.py +pykolab/plugins/.___init__.py +pykolab/plugins/roundcubedb/.___init__.py +pykolab/setup/.___init__.py +pykolab/setup/._setup_freebusy.py +pykolab/setup/._setup_ldap.py +pykolab/setup/._setup_mta.py +pykolab/setup/._setup_roundcube.py +pykolab/._translate.py +pykolab/._translit.py +pykolab/._utils.py +pykolab/wap_client/.___init__.py +pykolab/xml/._attendee.py +pykolab/xml/._event.py +pykolab/xml/.___init__.py +pykolab/xml/._utils.py +tests/functional/._purge_users.py +tests/functional/._resource_func.py +tests/functional/._synchronize.py +tests/functional/test_auth/.___init__.py +tests/functional/test_auth/._test_001_ldap.py +tests/functional/test_auth/._test_002_sql.py +tests/functional/test_auth/._test_003_pam.py +tests/functional/test_auth/._test_004_saslauthd.py +tests/functional/test_kolabd/._test_001_user_sync.py +tests/functional/test_wallace/._test_001_user_add.py +tests/functional/test_wallace/._test_002_footer.py +tests/functional/test_wallace/._test_005_resource_add.py +tests/functional/test_wallace/._test_005_resource_invitation.py +tests/functional/test_wallace/._test_006_resource_performance.py +tests/functional/test_wallace/._test_007_invitationpolicy.py +tests/functional/test_wap_client/._test_002_user_add.py +tests/functional/._user_add.py +tests/unit/._test-000-imports.py +tests/unit/._test-002-attendee.py +tests/unit/._test-003-event.py +tests/unit/._test-006-ldap_psearch.py +tests/unit/._test-007-ldap_syncrepl.py +tests/unit/._test-010-transliterate.py +tests/unit/._test-011-itip.py +tests/unit/._test-011-wallace_resources.py +tests/unit/._test-012-wallace_invitationpolicy.py +tests/unit/._test-014-conf-and-raw.py +tests/unit/._test-015-translate.py +wallace/.___init__.py +wallace/._module_gpgencrypt.py +wallace/._module_invitationpolicy.py +wallace/._module_resources.py +wallace/._modules.py
View file
pykolab-0.7.tar.gz/po/de.po
Changed
@@ -3,331 +3,362 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Christoph Wickert <cwickert@fedoraproject.org>, 2011. -# <grote@kolabsys.com>, 2012. +# Christoph Wickert <christoph.wickert@gmail.com>, 2011 +# Grote <grote@kolabsys.com>, 2012 +# balin <johannes_graumann@web.de>, 2012 +# Jo <jo@caj-augsburg.de>, 2012 +# bitnukl <robert@proemper.net>, 2014 +# Thomas Brüderli <roundcube@gmail.com>, 2014 +# Till Savekoul <till@koul.de>, 2012 msgid "" msgstr "" "Project-Id-Version: Kolab Groupware Solution\n" -"Report-Msgid-Bugs-To: https://isues.kolab.org/\n" -"POT-Creation-Date: 2012-08-14 12:22+0100\n" -"PO-Revision-Date: 2012-08-14 11:13+0000\n" -"Last-Translator: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-10 07:21-0400\n" +"PO-Revision-Date: 2014-07-22 13:01+0000\n" +"Last-Translator: Thomas Brüderli <roundcube@gmail.com>\n" "Language-Team: German (http://www.transifex.com/projects/p/kolab/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../bin/kolab_smtp_access_policy.py:206 +#: ../bin/kolab_smtp_access_policy.py:209 #, python-format msgid "Adding policy request to instance %s" msgstr "Füge Richtlinien-Anfrage zu Instanz %s hinzu" -#: ../bin/kolab_smtp_access_policy.py:446 +#: ../bin/kolab_smtp_access_policy.py:479 msgid "Unauthorized access not allowed" msgstr "Unberechtigter Zugriff nicht erlaubt" -#: ../bin/kolab_smtp_access_policy.py:467 -#: ../bin/kolab_smtp_access_policy.py:657 +#: ../bin/kolab_smtp_access_policy.py:508 +#: ../bin/kolab_smtp_access_policy.py:689 msgid "Could not find recipient" msgstr "Konnte den Empfänger nicht finden" -#: ../bin/kolab_smtp_access_policy.py:486 -#: ../bin/kolab_smtp_access_policy.py:586 +#: ../bin/kolab_smtp_access_policy.py:527 #, python-format -msgid "Could not find envelope sender user %s" -msgstr "Konnte den Absender-Umschlag für den Benutzer %s nicht finden" +msgid "Could not find envelope sender user %s (511)" +msgstr "" -#: ../bin/kolab_smtp_access_policy.py:529 +#: ../bin/kolab_smtp_access_policy.py:570 #, python-format msgid "Obtained authenticated user details for %r: %r" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:608 +#: ../bin/kolab_smtp_access_policy.py:627 +#, python-format +msgid "Could not find envelope sender user %s" +msgstr "Konnte den Absender-Umschlag für den Benutzer %s nicht finden" + +#: ../bin/kolab_smtp_access_policy.py:649 #, python-format msgid "%s is unauthorized to send on behalf of %s" msgstr "Benutzer %s ist nicht berechtigt als Benutzer %s zu senden" -#: ../bin/kolab_smtp_access_policy.py:618 +#: ../bin/kolab_smtp_access_policy.py:659 #, python-format msgid "" "User %s attempted to use envelope sender address %s without authorization" -msgstr "" +msgstr "Benutzer %s versuchte die Absendeadresse %s ohne Berechtigung zu verwenden" -#: ../bin/kolab_smtp_access_policy.py:681 -#: ../bin/kolab_smtp_access_policy.py:692 +#: ../bin/kolab_smtp_access_policy.py:713 +#: ../bin/kolab_smtp_access_policy.py:724 #, python-format msgid "Found user %s to be a delegate user of %s" msgstr "Benutzer %s ist ein delegierter Benutzer von %s" -#: ../bin/kolab_smtp_access_policy.py:716 +#: ../bin/kolab_smtp_access_policy.py:748 #, python-format msgid "" "Verifying authenticated sender '%(sender)s' with sasl_username " "'%(sasl_username)s' for recipient '%(recipient)s'" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:719 +#: ../bin/kolab_smtp_access_policy.py:751 #, python-format msgid "" "Verifying unauthenticated sender '%(sender)s' for recipient '%(recipient)s'" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:735 +#: ../bin/kolab_smtp_access_policy.py:767 #, python-format msgid "Reproducing verify_recipient(%s, %s) from cache" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:753 +#: ../bin/kolab_smtp_access_policy.py:804 #, python-format msgid "Using authentication domain %s instead of %s" msgstr "Benutze Authentisierungsdomain %s anstelle von %s" -#: ../bin/kolab_smtp_access_policy.py:763 +#: ../bin/kolab_smtp_access_policy.py:814 #, python-format msgid "Domain %s is a primary domain" msgstr "Die Domain %s ist die primäre Domain" -#: ../bin/kolab_smtp_access_policy.py:771 +#: ../bin/kolab_smtp_access_policy.py:822 #, python-format msgid "" "Checking the recipient for domain %s that is not ours. This is probably a " "configuration error." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:786 +#: ../bin/kolab_smtp_access_policy.py:837 msgid "" "This recipient address is related to multiple object entries and the SMTP " "Access Policy can therefore not restrict message flow" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:793 +#: ../bin/kolab_smtp_access_policy.py:854 #, python-format msgid "" "Recipient address %r not found. Allowing since the MTA was configured to " "accept the recipient." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:820 +#: ../bin/kolab_smtp_access_policy.py:890 msgid "Invalid recipient" msgstr "Ungültiger Empfänger" -#: ../bin/kolab_smtp_access_policy.py:831 +#: ../bin/kolab_smtp_access_policy.py:901 msgid "Could not find this user, accepting" msgstr "Konnte keine Einschränkung für diesen Benutzer finden, akzeptiere Nachricht" -#: ../bin/kolab_smtp_access_policy.py:894 -#: ../bin/kolab_smtp_access_policy.py:945 +#: ../bin/kolab_smtp_access_policy.py:974 +#: ../bin/kolab_smtp_access_policy.py:1050 #, python-format msgid "Sender %s is not allowed to send to recipient %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:933 +#: ../bin/kolab_smtp_access_policy.py:1038 #, python-format msgid "Reproducing verify_sender(%r) from cache" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:960 +#: ../bin/kolab_smtp_access_policy.py:1055 +msgid "Unverifiable sender." +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1060 +msgid "Sender is not using an alias" +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1068 msgid "Sender uses unauthorized envelope sender address" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:977 +#: ../bin/kolab_smtp_access_policy.py:1085 msgid "Could not verify sender" msgstr "Konnte den Absender nicht verifizieren" -#: ../bin/kolab_smtp_access_policy.py:984 +#: ../bin/kolab_smtp_access_policy.py:1092 msgid "" "Verifying whether sender is allowed to send to recipient using sender policy" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:997 +#: ../bin/kolab_smtp_access_policy.py:1105 #, python-format msgid "Result is %r" msgstr "Das Ergebnis ist %r" -#: ../bin/kolab_smtp_access_policy.py:1002 +#: ../bin/kolab_smtp_access_policy.py:1110 msgid "No recipient policy restrictions exist for this sender" msgstr "Es existiert keine Empfängerrichtlinie für diesen Absender" -#: ../bin/kolab_smtp_access_policy.py:1011 +#: ../bin/kolab_smtp_access_policy.py:1119 msgid "Found a recipient policy to apply for this sender." msgstr "Empfänger-Richtlinie für diesen Benutzer gefunden" -#: ../bin/kolab_smtp_access_policy.py:1026 +#: ../bin/kolab_smtp_access_policy.py:1134 #, python-format msgid "Sender %s not allowed to send to recipient %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1056 +#: ../bin/kolab_smtp_access_policy.py:1155 msgid "Cleaning up the cache" msgstr "Aufräumen des Cache" -#: ../bin/kolab_smtp_access_policy.py:1093 +#: ../bin/kolab_smtp_access_policy.py:1177 +msgid "" +"The 'uri' setting in the kolab_smtp_access_policy section is soon going to " +"be deprecated in favor of 'cache_uri'" +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1193 #, python-format msgid "Operational Error in caching: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1144 +#: ../bin/kolab_smtp_access_policy.py:1245 #, python-format msgid "Caching the policy result with timestamp %d" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1221 +#: ../bin/kolab_smtp_access_policy.py:1319 #, python-format msgid "Returning action DEFER_IF_PERMIT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1226 +#: ../bin/kolab_smtp_access_policy.py:1324 #, python-format msgid "Returning action DUNNO: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1231 +#: ../bin/kolab_smtp_access_policy.py:1329 #, python-format msgid "Returning action HOLD: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1236 +#: ../bin/kolab_smtp_access_policy.py:1334 #, python-format msgid "Returning action PERMIT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1241 +#: ../bin/kolab_smtp_access_policy.py:1459 #, python-format msgid "Returning action REJECT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1287 +#: ../bin/kolab_smtp_access_policy.py:1505 msgid "Starting to loop for new request" msgstr "Starte Schleife für neue Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1294 +#: ../bin/kolab_smtp_access_policy.py:1512 msgid "Timeout for policy request reading exceeded" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1300 +#: ../bin/kolab_smtp_access_policy.py:1518 msgid "End of current request" msgstr "Ende der aktuellen Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1304 +#: ../bin/kolab_smtp_access_policy.py:1522 #, python-format msgid "Getting line: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1308 +#: ../bin/kolab_smtp_access_policy.py:1526 msgid "Returning request" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1334 +#: ../bin/kolab_smtp_access_policy.py:1555 msgid "Access Policy Options" msgstr "Zugriffsrichtlinien-Einstellungen" -#: ../bin/kolab_smtp_access_policy.py:1341 +#: ../bin/kolab_smtp_access_policy.py:1562 msgid "SMTP Policy request timeout." msgstr "Zeitüberschreitung der SMTP Richtlinien-Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1347 +#: ../bin/kolab_smtp_access_policy.py:1568 msgid "Verify the recipient access policy." msgstr "Verifiziere die Empfänger-Zugriffs-Richtlinie." -#: ../bin/kolab_smtp_access_policy.py:1353 +#: ../bin/kolab_smtp_access_policy.py:1574 msgid "Verify the sender access policy." msgstr "Verifiziere die Sender-Zugriffs-Richtlinie." -#: ../bin/kolab_smtp_access_policy.py:1359 +#: ../bin/kolab_smtp_access_policy.py:1580 msgid "Allow unauthenticated senders." msgstr "Erlaube nicht authentisierte Sender." -#: ../bin/kolab_smtp_access_policy.py:1373 +#: ../bin/kolab_smtp_access_policy.py:1594 #, python-format msgid "Got request instance %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1382 +#: ../bin/kolab_smtp_access_policy.py:1603 #, python-format msgid "Request instance %s is in state %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1390 +#: ../bin/kolab_smtp_access_policy.py:1611 #, python-format msgid "Request instance %s is not yet in DATA state" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1402 +#: ../bin/kolab_smtp_access_policy.py:1623 #, python-format msgid "Request instance %s reached DATA state" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1420 +#: ../bin/kolab_smtp_access_policy.py:1643 +#, python-format +msgid "Unhandled exception caught: %r" +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1647 msgid "Sender access denied" msgstr "Sender Zugriff verweigert" -#: ../bin/kolab_smtp_access_policy.py:1422 +#: ../bin/kolab_smtp_access_policy.py:1649 msgid "Recipient access denied" msgstr "Empfänger Zugriff verweigert" -#: ../bin/kolab_smtp_access_policy.py:1424 +#: ../bin/kolab_smtp_access_policy.py:1651 msgid "No objections" msgstr "Keine Einwände" -#: ../conf.py:37 ../kolab.py:34 ../saslauthd.py:33 +#: ../conf.py:37 ../kolab-cli.py:34 ../saslauthd.py:33 msgid "Cannot load pykolab/logger.py:" -msgstr "" +msgstr "Laden von pykolab/logger.py nicht möglich:" -#: ../kolabd/__init__.py:49 ../saslauthd/__init__.py:48 -#: ../wallace/__init__.py:65 +#: ../kolabd/__init__.py:49 ../saslauthd/__init__.py:51 +#: ../wallace/__init__.py:85 msgid "Daemon Options" msgstr "Daemon Optionen" -#: ../kolabd/__init__.py:56 ../saslauthd/__init__.py:55 -#: ../wallace/__init__.py:72 +#: ../kolabd/__init__.py:56 ../saslauthd/__init__.py:58 +#: ../wallace/__init__.py:92 msgid "Fork to the background." msgstr "In den Hintergrund abtauchen" -#: ../kolabd/__init__.py:65 ../saslauthd/__init__.py:64 -#: ../wallace/__init__.py:98 +#: ../kolabd/__init__.py:65 ../saslauthd/__init__.py:67 +#: ../wallace/__init__.py:118 msgid "Path to the PID file to use." msgstr "Pfad zur PID-Datei" -#: ../kolabd/__init__.py:74 ../saslauthd/__init__.py:73 -#: ../wallace/__init__.py:115 +#: ../kolabd/__init__.py:74 ../saslauthd/__init__.py:76 +#: ../wallace/__init__.py:135 msgid "Run as user USERNAME" -msgstr "" +msgstr "Als Benutzer USERNAME ausführen" -#: ../kolabd/__init__.py:84 ../saslauthd/__init__.py:83 -#: ../wallace/__init__.py:89 +#: ../kolabd/__init__.py:84 ../saslauthd/__init__.py:86 +#: ../wallace/__init__.py:109 msgid "Run as group GROUPNAME" -msgstr "" +msgstr "Als Gruppe GROUPNAME ausführen" -#: ../kolabd/__init__.py:122 ../pykolab/utils.py:151 -#: ../wallace/__init__.py:288 +#: ../kolabd/__init__.py:122 ../pykolab/logger.py:139 ../pykolab/utils.py:234 +#: ../saslauthd/__init__.py:292 ../wallace/__init__.py:329 #, python-format msgid "Group %s does not exist" -msgstr "" +msgstr "Gruppe %s exisitert nicht" -#: ../kolabd/__init__.py:131 ../wallace/__init__.py:297 +#: ../kolabd/__init__.py:131 ../saslauthd/__init__.py:301 +#: ../wallace/__init__.py:338 #, python-format msgid "Switching real and effective group id to %d" msgstr "" -#: ../kolabd/__init__.py:153 ../pykolab/utils.py:175 -#: ../wallace/__init__.py:319 +#: ../kolabd/__init__.py:153 ../pykolab/logger.py:159 ../pykolab/utils.py:258 +#: ../saslauthd/__init__.py:323 ../wallace/__init__.py:360 #, python-format msgid "User %s does not exist" msgstr "Benutzer %s existiert nicht" -#: ../kolabd/__init__.py:163 ../wallace/__init__.py:329 +#: ../kolabd/__init__.py:163 ../saslauthd/__init__.py:333 +#: ../wallace/__init__.py:370 #, python-format msgid "Switching real and effective user id to %d" msgstr "" -#: ../kolabd/__init__.py:172 ../wallace/__init__.py:338 +#: ../kolabd/__init__.py:172 ../saslauthd/__init__.py:342 +#: ../wallace/__init__.py:379 msgid "Could not change real and effective uid and/or gid" msgstr "" -#: ../kolabd/__init__.py:192 ../saslauthd/__init__.py:122 -#: ../wallace/__init__.py:358 +#: ../kolabd/__init__.py:192 ../saslauthd/__init__.py:133 +#: ../wallace/__init__.py:399 msgid "Interrupted by user" msgstr "Vom Benutzer unterbrochen" @@ -335,328 +366,492 @@ msgid "Traceback occurred, please report a " msgstr "" -#: ../kolabd/__init__.py:203 ../saslauthd/__init__.py:130 -#: ../wallace/__init__.py:367 +#: ../kolabd/__init__.py:203 ../saslauthd/__init__.py:141 +#: ../wallace/__init__.py:408 #, python-format msgid "Type Error: %s" msgstr "Typ-Fehler: %s" -#: ../kolabd/__init__.py:223 ../pykolab/auth/ldap/__init__.py:1591 +#: ../kolabd/__init__.py:230 +msgid "Could not connect to LDAP, is it running?" +msgstr "" + +#: ../kolabd/__init__.py:233 ../pykolab/auth/ldap/__init__.py:2137 #: ../pykolab/cli/cmd_sync.py:36 msgid "Listing domains..." msgstr "Liste Domains auf..." -#: ../kolabd/__init__.py:256 +#: ../kolabd/__init__.py:244 +msgid "No domains. Not syncing" +msgstr "" + +#: ../kolabd/__init__.py:275 #, python-format msgid "added domains: %r, removed domains: %r" msgstr "" +#: ../kolabd/process.py:33 +#, python-format +msgid "Process created for domain %s" +msgstr "" + +#: ../kolabd/process.py:42 +#, python-format +msgid "Synchronizing for domain %s" +msgstr "" + +#: ../kolabd/process.py:59 +#, python-format +msgid "" +"Error in process %r, terminating:\n" +"\t%r" +msgstr "" + #: ../kolabd.py:31 ../setup-kolab.py:36 ../wallace.py:31 msgid "Cannot load pykolab/constants.py:" msgstr "Konnte nicht pykolab/constants.py laden:" -#: ../pykolab/auth/__init__.py:94 +#: ../pykolab/auth/__init__.py:89 #, python-format msgid "Called for domain %r" msgstr "" -#: ../pykolab/auth/__init__.py:107 ../pykolab/auth/__init__.py:116 +#: ../pykolab/auth/__init__.py:106 ../pykolab/auth/__init__.py:115 #, python-format msgid "Using section %s and domain %s" msgstr "" -#: ../pykolab/auth/__init__.py:121 +#: ../pykolab/auth/__init__.py:120 #, python-format msgid "Connecting to Authentication backend for domain %s" msgstr "" -#: ../pykolab/auth/__init__.py:132 +#: ../pykolab/auth/__init__.py:131 #, python-format msgid "Section %s has no option 'auth_mechanism'" msgstr "" -#: ../pykolab/auth/__init__.py:139 +#: ../pykolab/auth/__init__.py:138 #, python-format msgid "Section %s has auth_mechanism: %r" msgstr "" -#: ../pykolab/auth/__init__.py:148 ../pykolab/auth/__init__.py:157 +#: ../pykolab/auth/__init__.py:147 ../pykolab/auth/__init__.py:156 msgid "Starting LDAP..." msgstr "Starte LDAP..." -#: ../pykolab/auth/ldap/cache.py:109 +#: ../pykolab/auth/ldap/cache.py:126 #, python-format msgid "Inserting cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/cache.py:122 +#: ../pykolab/auth/ldap/cache.py:147 #, python-format msgid "Updating timestamp for cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/cache.py:129 +#: ../pykolab/auth/ldap/cache.py:155 #, python-format msgid "Updating result_attribute for cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:51 +#: ../pykolab/auth/ldap/__init__.py:52 msgid "Python LDAP library does not support persistent search" msgstr "Die Python LDAP Bibliothek unterstützt keine persistente Suche" -#: ../pykolab/auth/ldap/__init__.py:142 +#: ../pykolab/auth/ldap/__init__.py:143 #, python-format msgid "Attempting to authenticate user %s in realm %s" msgstr "Versuche Benutzer %s in Bereich %s zu authentisieren" -#: ../pykolab/auth/ldap/__init__.py:184 +#: ../pykolab/auth/ldap/__init__.py:175 ../pykolab/auth/ldap/__init__.py:226 +#, python-format +msgid "Authentication cache failed: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:216 ../pykolab/auth/ldap/__init__.py:240 #, python-format msgid "Binding with user_dn %s and password %s" msgstr "Binde mit user_dn %s und Passwort %s" -#: ../pykolab/auth/ldap/__init__.py:194 +#: ../pykolab/auth/ldap/__init__.py:231 ../pykolab/auth/ldap/__init__.py:263 #, python-format msgid "Failed to authenticate as user %s" +msgstr "Autorisation als Benutzer %s gescheitert" + +#: ../pykolab/auth/ldap/__init__.py:249 +#, python-format +msgid "Error occured, there is no such object: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:254 +msgid "Authentication cache failed to clear entry" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:260 +#, python-format +msgid "Exception occured: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:211 +#: ../pykolab/auth/ldap/__init__.py:280 msgid "Connecting to LDAP..." msgstr "Verbinde zum LDAP..." -#: ../pykolab/auth/ldap/__init__.py:215 +#: ../pykolab/auth/ldap/__init__.py:284 #, python-format msgid "Attempting to use LDAP URI %s" msgstr "Versuche LDAP URI %s zu benutzen" -#: ../pykolab/auth/ldap/__init__.py:357 +#: ../pykolab/auth/ldap/__init__.py:371 +#, python-format +msgid "Entry ID: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:373 +#, python-format +msgid "Entry DN: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:376 +#, python-format +msgid "" +"ldap search: (%r, %r, filterstr='(objectclass=*)', attrlist=[ 'dn' ] + %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:453 #, python-format msgid "Finding recipient with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:425 +#: ../pykolab/auth/ldap/__init__.py:529 #, python-format msgid "Finding resource with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:448 +#: ../pykolab/auth/ldap/__init__.py:560 #, python-format msgid "Using timestamp %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:480 +#: ../pykolab/auth/ldap/__init__.py:595 +msgid "Applying recipient policy disabled through configuration" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:600 #, python-format msgid "Applying recipient policy to %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:497 +#: ../pykolab/auth/ldap/__init__.py:617 #, python-format msgid "Using mail attributes: %r, with primary %r and " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:508 +#: ../pykolab/auth/ldap/__init__.py:628 #, python-format msgid "key %r not in entry" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:510 +#: ../pykolab/auth/ldap/__init__.py:630 #, python-format msgid "key %r is the prim. mail attr." msgstr "" -#: ../pykolab/auth/ldap/__init__.py:512 +#: ../pykolab/auth/ldap/__init__.py:632 msgid "prim. mail pol. is not empty" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:515 +#: ../pykolab/auth/ldap/__init__.py:635 #, python-format msgid "key %r is the sec. mail attr." msgstr "" -#: ../pykolab/auth/ldap/__init__.py:517 +#: ../pykolab/auth/ldap/__init__.py:637 msgid "sec. mail pol. is not empty" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:520 ../pykolab/auth/ldap/__init__.py:533 +#: ../pykolab/auth/ldap/__init__.py:641 ../pykolab/auth/ldap/__init__.py:655 #, python-format msgid "Attributes %r are not yet available for entry %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:574 +#: ../pykolab/auth/ldap/__init__.py:694 #, python-format msgid "No results for mail address %s found" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:585 +#: ../pykolab/auth/ldap/__init__.py:705 #, python-format msgid "1 result for address %s found, verifying" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:595 +#: ../pykolab/auth/ldap/__init__.py:715 #, python-format msgid "Too bad, primary email address %s " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:606 ../pykolab/auth/ldap/__init__.py:695 +#: ../pykolab/auth/ldap/__init__.py:726 ../pykolab/auth/ldap/__init__.py:815 msgid "Address assigned to us" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:661 +#: ../pykolab/auth/ldap/__init__.py:781 #, python-format msgid "No results for address %s found" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:672 +#: ../pykolab/auth/ldap/__init__.py:792 #, python-format msgid "1 result for address %s found, " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:683 +#: ../pykolab/auth/ldap/__init__.py:803 msgid "Too bad, secondary email " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:710 +#: ../pykolab/auth/ldap/__init__.py:830 msgid "Recipient policy composed the following set of secondary " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:716 +#: ../pykolab/auth/ldap/__init__.py:841 #, python-format msgid "Secondary mail addresses that we want is not None: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:727 +#: ../pykolab/auth/ldap/__init__.py:852 msgid "Avoiding the duplication of the primary mail " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:738 +#: ../pykolab/auth/ldap/__init__.py:863 #, python-format msgid "Entry is getting secondary mail addresses: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:746 +#: ../pykolab/auth/ldap/__init__.py:871 msgid "Entry did not have any secondary mail " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:772 +#: ../pykolab/auth/ldap/__init__.py:888 ../pykolab/auth/ldap/__init__.py:894 +#, python-format +msgid "secondary_mail_addresses: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:889 ../pykolab/auth/ldap/__init__.py:895 +#, python-format +msgid "entry[%s]: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:906 #, python-format msgid "Entry modifications list: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:792 +#: ../pykolab/auth/ldap/__init__.py:934 #, python-format msgid "Setting entry attribute %r to %r for %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:828 +#: ../pykolab/auth/ldap/__init__.py:970 #, python-format -msgid "Could not update dn %r" +msgid "" +"Could not update dn %r:\n" +"%r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:841 +#: ../pykolab/auth/ldap/__init__.py:983 #, python-format msgid "Using filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:879 +#: ../pykolab/auth/ldap/__init__.py:998 +#, python-format +msgid "Synchronization is searching against base DN: %s" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1044 #, python-format msgid "About to consider the user quota for %r (used: %r, " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:945 +#: ../pykolab/auth/ldap/__init__.py:1115 msgid "Invalid DN, username and/or password." msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1229 +#: ../pykolab/auth/ldap/__init__.py:1236 ../pykolab/auth/ldap/__init__.py:1249 +#: ../pykolab/auth/ldap/__init__.py:1614 ../pykolab/auth/ldap/__init__.py:1627 +#, python-format +msgid "Found a subject %r with access %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1356 +#, python-format +msgid "Entry %s attribute value: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1364 #, python-format -msgid "Current changelog entry %s with %s" +msgid "imap.user_mailbox_server(%r) result: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1242 +#: ../pykolab/auth/ldap/__init__.py:1684 ../pykolab/auth/ldap/__init__.py:1853 #, python-format msgid "Result from recipient policy: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1385 +#: ../pykolab/auth/ldap/__init__.py:1908 #, python-format msgid "Kolab user %s does not have a result attribute %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1527 +#: ../pykolab/auth/ldap/__init__.py:2067 #, python-format msgid "Finding domain root dn for domain %s" -msgstr "" +msgstr "Suche root dn für die Domain %s" -#: ../pykolab/auth/ldap/__init__.py:1615 +#: ../pykolab/auth/ldap/__init__.py:2164 msgid "Authentication database DOWN" msgstr "Authentisierungsdatenbank UNTEN" -#: ../pykolab/auth/ldap/__init__.py:1699 ../pykolab/auth/ldap/__init__.py:1734 +#: ../pykolab/auth/ldap/__init__.py:2248 ../pykolab/auth/ldap/__init__.py:2296 #, python-format msgid "Entry type: %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1822 +#: ../pykolab/auth/ldap/__init__.py:2321 +#, python-format +msgid "Done with _synchronize_callback() for entry %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:2393 msgid "LDAP Search Result Data Entry:" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1838 +#: ../pykolab/auth/ldap/__init__.py:2409 msgid "Entry Change Notification attributes:" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1843 +#: ../pykolab/auth/ldap/__init__.py:2414 #, python-format msgid "Change Type: %r (%r)" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1851 +#: ../pykolab/auth/ldap/__init__.py:2422 #, python-format msgid "Previous DN: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1906 +#: ../pykolab/auth/ldap/__init__.py:2477 #, python-format msgid "Object %s searched no longer exists" msgstr "Das gesuchte Objekt %s existiert nicht mehr" -#: ../pykolab/auth/ldap/__init__.py:1916 +#: ../pykolab/auth/ldap/__init__.py:2487 #, python-format msgid "%d results..." msgstr "%d Ergebnisse..." -#: ../pykolab/auth/ldap/__init__.py:2014 +#: ../pykolab/auth/ldap/__init__.py:2590 #, python-format msgid "Searching with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:2058 +#: ../pykolab/auth/ldap/__init__.py:2642 #, python-format msgid "Checking for support for %s on %s" msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:36 ../pykolab/cli/cmd_create_mailbox.py:36 +#: ../pykolab/auth/ldap/__init__.py:2661 +#, python-format +msgid "Found support for %s" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:2706 +#, python-format +msgid "An error occured using %s: %r" +msgstr "" + +#: ../pykolab/auth/ldap/syncrepl.py:46 +msgid "The name of the persistent, unique attribute " +msgstr "" + +#: ../pykolab/cli/cmd_acl_cleanup.py:34 +msgid "Clean up ACLs that use identifiers that no longer exist" +msgstr "" + +#: ../pykolab/cli/cmd_acl_cleanup.py:56 +#, python-format +msgid "Deleting ACL %s for subject %s on folder %s" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:42 +msgid "Specify the (new) alias address" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:45 +msgid "Specify the existing recipient address" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:66 ../pykolab/cli/cmd_add_alias.py:70 +#, python-format +msgid "Domain %r is not a local domain" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:75 +msgid "Primary and secondary domain do not have the same parent domain" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:81 +#, python-format +msgid "No such recipient %r" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:87 +#, python-format +msgid "Recipient for alias %r already exists" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:97 +msgid "Environment is not configured for " +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:105 +#, python-format +msgid "Recipient %r is not the primary recipient for address %r" +msgstr "" + +#: ../pykolab/cli/cmd_add_domain.py:36 +#: ../pykolab/cli/cmd_count_domain_mailboxes.py:38 +#: ../pykolab/cli/cmd_create_mailbox.py:36 #: ../pykolab/cli/cmd_export_mailbox.py:33 -#: ../pykolab/cli/cmd_list_mailboxes.py:39 -#: ../pykolab/cli/cmd_list_user_subscriptions.py:35 +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:38 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:36 +#: ../pykolab/cli/cmd_list_mailboxes.py:40 +#: ../pykolab/cli/cmd_list_mailbox_metadata.py:37 +#: ../pykolab/cli/cmd_list_messages.py:37 ../pykolab/cli/cmd_list_quota.py:36 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:36 +#: ../pykolab/cli/cmd_server_info.py:34 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:38 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:39 +#: ../pykolab/cli/cmd_undelete_mailbox.py:34 msgid "CLI Options" msgstr "Kommandozeilen-Parameter" #: ../pykolab/cli/cmd_add_domain.py:42 -msgid "Add domain as alias for DOMAIN" +msgid "Add alias domain." msgstr "" #: ../pykolab/cli/cmd_add_domain.py:47 -msgid "Add a new domain or domain alias." -msgstr "Füge eine neue Domain oder einen neuen Domain Alias hinzu." - -#: ../pykolab/cli/cmd_add_domain.py:55 -msgid "Could not find credentials with sufficient permissions" +msgid "Add a new domain." msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:80 ../pykolab/wap_client/__init__.py:113 -msgid "Invalid parent domain" +#: ../pykolab/cli/cmd_add_domain.py:55 ../pykolab/cli/cmd_delete_domain.py:44 +#: ../pykolab/cli/cmd_find_domain.py:44 +msgid "Could not find credentials with sufficient permissions" msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:86 +#: ../pykolab/cli/cmd_add_domain.py:67 ../pykolab/cli/cmd_delete_domain.py:56 +#: ../pykolab/cli/cmd_find_domain.py:56 msgid "Domain name" -msgstr "" +msgstr "Name der Domain" #: ../pykolab/cli/cmd_add_user_subscription.py:37 msgid "Subscribe a user to a folder." @@ -670,7 +865,7 @@ msgstr "" #: ../pykolab/cli/cmd_add_user_subscription.py:50 -#: ../pykolab/cli/cmd_list_user_subscriptions.py:56 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:63 #: ../pykolab/cli/cmd_remove_user_subscription.py:50 msgid "User ID" msgstr "Benutzer ID" @@ -682,30 +877,39 @@ msgstr "" #: ../pykolab/cli/cmd_add_user_subscription.py:73 +#: ../pykolab/cli/cmd_delete_message.py:61 +#: ../pykolab/cli/cmd_list_messages.py:67 #: ../pykolab/cli/cmd_remove_user_subscription.py:73 msgid "No such folder" -msgstr "" +msgstr "Dieser Ordner ist nicht vorhanden" -#: ../pykolab/cli/cmd_add_user_subscription.py:86 -#, python-format -msgid "Successfully subscribed user %s to the following folders:" -msgstr "" - -#: ../pykolab/cli/cmd_add_user_subscription.py:92 -#, python-format -msgid "User %s not subscribed to any folders." +#: ../pykolab/cli/cmd_count_domain_mailboxes.py:44 +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:50 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:48 +#: ../pykolab/cli/cmd_list_mailboxes.py:52 ../pykolab/cli/cmd_list_quota.py:42 +#: ../pykolab/cli/cmd_server_info.py:40 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:57 +msgid "List mailboxes on server SERVER only." msgstr "" -#: ../pykolab/cli/cmd_create_mailbox.py:41 +#: ../pykolab/cli/cmd_create_mailbox.py:42 msgid "Set metadata for folder to ANNOTATION=VALUE" msgstr "" #: ../pykolab/cli/cmd_create_mailbox.py:50 -msgid "Invalid argument" +msgid "Create folder on PARTITION." msgstr "" -#: ../pykolab/cli/cmd_create_mailbox.py:58 +#: ../pykolab/cli/cmd_create_mailbox.py:60 +msgid "Invalid argument" +msgstr "Ungültiges Argument" + +#: ../pykolab/cli/cmd_create_mailbox.py:68 msgid "Invalid argument for metadata" +msgstr "Ungültiges Argument für die Metadaten" + +#: ../pykolab/cli/cmd_delete_domain.py:36 +msgid "Delete a domain." msgstr "" #: ../pykolab/cli/cmd_delete_mailbox_acl.py:45 @@ -716,26 +920,48 @@ msgstr "" #: ../pykolab/cli/cmd_delete_mailbox_acl.py:48 -#: ../pykolab/cli/cmd_list_mailbox_acls.py:41 -#: ../pykolab/cli/cmd_list_mailbox_metadata.py:41 +#: ../pykolab/cli/cmd_list_mailbox_acls.py:43 +#: ../pykolab/cli/cmd_list_mailbox_metadata.py:54 #: ../pykolab/cli/cmd_set_mailbox_acl.py:54 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:54 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:66 +#: ../pykolab/cli/cmd_set_quota.py:46 ../tests/unit/test-015-translate.py:12 +#: ../tests/unit/test-015-translate.py:16 +#: ../tests/unit/test-015-translate.py:18 +#: ../tests/unit/test-015-translate.py:20 msgid "Folder name" -msgstr "" +msgstr "Ordnername" #: ../pykolab/cli/cmd_delete_mailbox_acl.py:60 -#: ../pykolab/cli/cmd_list_mailbox_acls.py:52 -#: ../pykolab/cli/cmd_list_mailbox_metadata.py:52 +#: ../pykolab/cli/cmd_list_mailbox_acls.py:54 +#: ../pykolab/cli/cmd_list_mailbox_metadata.py:80 #: ../pykolab/cli/cmd_set_mailbox_acl.py:67 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:67 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:94 +#: ../pykolab/cli/cmd_set_quota.py:58 #, python-format msgid "No such folder %r" -msgstr "" +msgstr "Kein Ordner %r verfügbar" #: ../pykolab/cli/cmd_delete_mailbox.py:46 msgid "No mailbox specified" msgstr "Keine Mailbox angegeben" +#: ../pykolab/cli/cmd_delete_mailbox.py:56 +msgid "No such folder(s)" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:36 +msgid "Delete a message from a folder" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:49 +msgid "Specify a UID" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:52 +#: ../pykolab/cli/cmd_list_messages.py:58 +msgid "Specify a folder" +msgstr "" + #: ../pykolab/cli/cmd_export_mailbox.py:38 msgid "All folders this user has access to" msgstr "" @@ -743,40 +969,77 @@ #: ../pykolab/cli/cmd_export_mailbox.py:108 #, python-format msgid "%s is not a directory" -msgstr "" +msgstr "%s ist kein Verzeichnis" #: ../pykolab/cli/cmd_export_mailbox.py:118 #, python-format msgid "ZIP file at %s.zip" -msgstr "" +msgstr "ZIP-Datei unter %s.zip" #: ../pykolab/cli/cmd_export_mailbox.py:120 #, python-format msgid "No directories found for user %s" msgstr "" -#: ../pykolab/cli/cmd_list_mailboxes.py:44 +#: ../pykolab/cli/cmd_find_domain.py:36 +msgid "Find a domain." +msgstr "" + +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:43 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:41 +#: ../pykolab/cli/cmd_list_mailboxes.py:45 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:41 msgid "Display raw IMAP UTF-7 folder names" msgstr "" -#: ../pykolab/cli/cmd_list_mailboxes.py:75 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:58 +msgid "Domain" +msgstr "Domäne" + +#: ../pykolab/cli/cmd_list_mailboxes.py:87 #, python-format msgid "Appending folder search for %r" msgstr "" -#: ../pykolab/cli/cmd_list_user_subscriptions.py:40 +#: ../pykolab/cli/cmd_list_mailbox_metadata.py:44 +msgid "List annotations as user USER" +msgstr "" + +#: ../pykolab/cli/cmd_list_messages.py:43 +msgid "Include messages flagged as \\Deleted" +msgstr "" + +#: ../pykolab/cli/cmd_list_messages.py:47 +msgid "List messages in a folder" +msgstr "" + +#: ../pykolab/cli/cmd_list_quota.py:73 ../pykolab/cli/cmd_list_quota.py:89 +#, python-format +msgid "The quota for folder %s is set to literally allow 0KB of storage." +msgstr "" + +#: ../pykolab/cli/cmd_list_user_subscriptions.py:47 msgid "List unsubscribed folders" msgstr "Liste nicht abonnierte Ordner" -#: ../pykolab/cli/cmd_list_user_subscriptions.py:43 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:50 msgid "List the folders a user is subscribed to." msgstr "Liste die Ordner, die ein Benutzer abonniert hat." -#: ../pykolab/cli/cmd_list_user_subscriptions.py:88 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:98 #, python-format msgid "No unsubscribed folders for user %s" msgstr "" +#: ../pykolab/cli/cmd_mailbox_cleanup.py:37 +msgid "Clean up mailboxes that do no longer have an owner." +msgstr "" + +#: ../pykolab/cli/cmd_mailbox_cleanup.py:61 +#, python-format +msgid "Deleting folder 'user/%s'" +msgstr "" + #: ../pykolab/cli/cmd_remove_mailaddress.py:49 msgid "Invalid or unqualified email address." msgstr "" @@ -811,23 +1074,23 @@ #: ../pykolab/cli/cmd_remove_user_subscription.py:92 #, python-format -msgid "User %s not be unsubscribed from any folders." +msgid "User %s was not unsubscribed from any folders." msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:48 +#: ../pykolab/cli/cmd_rename_mailbox.py:52 msgid "No target mailbox name specified" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:50 +#: ../pykolab/cli/cmd_rename_mailbox.py:54 msgid "No source mailbox name specified" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:62 +#: ../pykolab/cli/cmd_rename_mailbox.py:66 #, python-format msgid "Source folder %r does not exist" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:66 +#: ../pykolab/cli/cmd_rename_mailbox.py:70 #, python-format msgid "Target folder %r already exists" msgstr "" @@ -838,17 +1101,75 @@ msgid "ACI Permissions" msgstr "" -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:47 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:51 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:56 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:45 +msgid "Set annotation as user USER" +msgstr "" + +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:59 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:63 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:68 msgid "Metadata value" msgstr "" -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:50 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:55 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:62 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:67 msgid "Metadata path" msgstr "" +#: ../pykolab/cli/cmd_set_quota.py:43 ../pykolab/cli/cmd_set_quota.py:47 +msgid "New quota" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:44 +msgid "Delete mailboxes for recipients that do not appear to exist in LDAP." +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:50 +msgid "Display changes, do not apply them." +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:88 +#, python-format +msgid "Domains in IMAP not in LDAP: %r" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:101 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:142 +#, python-format +msgid "" +"No recipients for '%s' (would have deleted the mailbox if not for --dry-" +"run)!" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:106 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:147 +#, python-format +msgid "Deleting mailbox '%s' because it has no recipients" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:110 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:151 +#, python-format +msgid "An error occurred removing mailbox %r: %r" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:112 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:153 +#, python-format +msgid "Not automatically deleting shared folder '%s'" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:114 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:155 +#, python-format +msgid "No recipients for '%s' (use --delete to delete)!" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:136 +#, python-format +msgid "Multiple recipients for '%s'!" +msgstr "" + #: ../pykolab/cli/cmd_sync.py:41 #, python-format msgid "Found %d domains in %d seconds" @@ -859,15 +1180,23 @@ msgid "Running for domain %s" msgstr "Starte für Domain %s" -#: ../pykolab/cli/cmd_sync.py:57 +#: ../pykolab/cli/cmd_sync.py:58 #, python-format msgid "Synchronizing users for %s took %d seconds" msgstr "Benutzer für %s zu synchronisieren dauerte %d Sekunden" -#: ../pykolab/cli/cmd_undelete_mailbox.py:33 +#: ../pykolab/cli/cmd_undelete_mailbox.py:39 +msgid "Do not actually execute, but state what would have been executed." +msgstr "" + +#: ../pykolab/cli/cmd_undelete_mailbox.py:42 msgid "Recover mailboxes previously deleted." msgstr "" +#: ../pykolab/cli/cmd_user_info.py:39 +msgid "Email address" +msgstr "E-Mail-Adresse" + #. This is a nested command #. This is a nested component #: ../pykolab/cli/commands.py:98 ../pykolab/setup/components.py:90 @@ -875,25 +1204,102 @@ msgid "Command Group: %s" msgstr "" -#: ../pykolab/cli/commands.py:109 ../pykolab/cli/commands.py:114 +#: ../pykolab/cli/commands.py:113 ../pykolab/cli/commands.py:118 msgid "No such command." msgstr "Dieses Kommando existiert nicht." -#: ../pykolab/cli/commands.py:165 ../pykolab/setup/components.py:231 +#: ../pykolab/cli/commands.py:168 ../pykolab/setup/components.py:231 #, python-format msgid "Command '%s' already registered" msgstr "" -#: ../pykolab/cli/commands.py:190 ../pykolab/setup/components.py:257 -#: ../wallace/modules.py:338 +#: ../pykolab/cli/commands.py:193 ../pykolab/setup/components.py:257 +#: ../wallace/modules.py:369 #, python-format msgid "Alias for %s" msgstr "Alias für %s" -#: ../pykolab/cli/commands.py:198 ../pykolab/setup/components.py:265 +#: ../pykolab/cli/commands.py:201 ../pykolab/setup/components.py:265 msgid "Not yet implemented" msgstr "Diese Funktion ist noch nicht implementiert" +#: ../pykolab/cli/sieve/cmd_list.py:43 ../pykolab/cli/sieve/cmd_put.py:42 +#: ../pykolab/cli/sieve/cmd_refresh.py:44 ../pykolab/cli/sieve/cmd_test.py:43 +msgid "Email Address" +msgstr "E-mail-Adresse" + +#: ../pykolab/cli/sieve/cmd_refresh.py:99 +#: ../pykolab/plugins/sievemgmt/__init__.py:111 +#, python-format +msgid "Found the following scripts for user %s: %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:100 +#: ../pykolab/plugins/sievemgmt/__init__.py:112 +#, python-format +msgid "And the following script is active for user %s: %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:178 +#: ../pykolab/plugins/sievemgmt/__init__.py:190 +#, python-format +msgid "" +"Delivery to folder active, but no folder name attribute available for user " +"%r" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:181 +#: ../pykolab/plugins/sievemgmt/__init__.py:193 +msgid "Delivery to folder active, but no folder name attribute configured" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:359 +#, python-format +msgid "MANAGEMENT script for user %s contents: %r" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:364 +#: ../pykolab/plugins/sievemgmt/__init__.py:374 +#, python-format +msgid "Uploading script MANAGEMENT failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:366 +#: ../pykolab/plugins/sievemgmt/__init__.py:376 +#, python-format +msgid "Uploading script MANAGEMENT for user %s succeeded" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:377 +#: ../pykolab/plugins/sievemgmt/__init__.py:387 +#, python-format +msgid "Including script %s in USER (for user %s)" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:386 +#: ../pykolab/plugins/sievemgmt/__init__.py:396 +#, python-format +msgid "Uploading script USER failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:388 +#: ../pykolab/plugins/sievemgmt/__init__.py:398 +#, python-format +msgid "Uploading script USER for user %s succeeded" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:416 +#: ../pykolab/plugins/sievemgmt/__init__.py:426 +#, python-format +msgid "Uploading script MASTER failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:418 +#: ../pykolab/plugins/sievemgmt/__init__.py:428 +#, python-format +msgid "Uploading script MASTER for user %s succeeded" +msgstr "" + #: ../pykolab/cli/telemetry/cmd_examine_command_issue.py:40 msgid "Unspecified command issue identifier" msgstr "" @@ -958,27 +1364,27 @@ #: ../pykolab/conf/__init__.py:87 #, python-format msgid "Setting %s to %r (from defaults)" -msgstr "" +msgstr "Setze %s auf %r (aus den Standardeinstellungen)" #: ../pykolab/conf/__init__.py:106 #, python-format msgid "Setting %s to %r (from CLI, verified)" -msgstr "" +msgstr "Setze %s auf %r (von der Kommandozeile, überprüft)" #: ../pykolab/conf/__init__.py:109 #, python-format msgid "Setting %s to %r (from CLI, not checked)" -msgstr "" +msgstr "Setze %s auf %r (von der Kommandozeile, nicht überprüft)" #: ../pykolab/conf/__init__.py:150 ../pykolab/conf/__init__.py:207 #, python-format msgid "Setting %s_%s to '****' (from configuration file)" -msgstr "" +msgstr "Setze %s_%s auf '****' (aus Konfigurationsdatei)" #: ../pykolab/conf/__init__.py:152 ../pykolab/conf/__init__.py:209 #, python-format msgid "Setting %s_%s to %r (from configuration file)" -msgstr "" +msgstr "Setze %s_%s auf %r (aus Konfigurationsdatei)" #: ../pykolab/conf/__init__.py:162 msgid "Setting options from configuration file" @@ -1039,76 +1445,76 @@ msgid "No command supplied" msgstr "Kein Befehl angegeben" -#: ../pykolab/conf/__init__.py:411 +#: ../pykolab/conf/__init__.py:416 msgid "Insufficient options. Need section, key and value -in that order." msgstr "Unzureichende Optionen. Brauche Sektion, Schlüssel und Wert in dieser Reihenfolge." -#: ../pykolab/conf/__init__.py:414 +#: ../pykolab/conf/__init__.py:419 #, python-format msgid "No section '%s' exists." msgstr "Es existiert keine Sektion '%s'." -#: ../pykolab/conf/__init__.py:445 +#: ../pykolab/conf/__init__.py:461 #, python-format msgid "Setting %s to %r (from the default values for CLI options)" -msgstr "" +msgstr "Setze %s auf %r (aus den Standardwerten für Kommandozeilenoptionen)" -#: ../pykolab/conf/__init__.py:514 +#: ../pykolab/conf/__init__.py:534 #, python-format msgid "Could not execute configuration function: %s" -msgstr "" +msgstr "Konnte die Konfigurationsfunktion nicht ausführen: %s" -#: ../pykolab/conf/__init__.py:522 +#: ../pykolab/conf/__init__.py:542 #, python-format msgid "Option %s/%s does not exist in config file %s, pulling from defaults" -msgstr "" +msgstr "Die Option %s/%s existiert in der Konfigurationsdatei %s nicht, sie wird aus den Standardeinstellungen geholt" -#: ../pykolab/conf/__init__.py:530 ../pykolab/conf/__init__.py:533 +#: ../pykolab/conf/__init__.py:550 ../pykolab/conf/__init__.py:553 msgid "Option does not exist in defaults." msgstr "Diese Option hat keinen Standardwert." -#: ../pykolab/conf/__init__.py:543 +#: ../pykolab/conf/__init__.py:563 #, python-format msgid "Configuration file %s not readable." msgstr "Konfigurationsdatei %s ist nicht lesbar." -#: ../pykolab/conf/__init__.py:546 +#: ../pykolab/conf/__init__.py:566 #, python-format msgid "Configuration file %s does not exist." msgstr "Konfigurationsdatei %s existiert nicht." -#: ../pykolab/conf/__init__.py:551 +#: ../pykolab/conf/__init__.py:571 msgid "" "WARNING: A negative debug level value does not make this program be any more" " silent." msgstr "Warnung: Eine negative Fehlerprotokollierungszahl macht dieses Programm nicht noch stiller." -#: ../pykolab/conf/__init__.py:557 +#: ../pykolab/conf/__init__.py:577 msgid "This program has 9 levels of verbosity. Using the maximum of 9." msgstr "Dieses Programm hat 9 Ebenen der Detailliertheit. Benutze das Maximum 9." -#: ../pykolab/conf/__init__.py:565 ../pykolab/conf/__init__.py:571 +#: ../pykolab/conf/__init__.py:585 ../pykolab/conf/__init__.py:591 msgid "Cannot start SASL authentication daemon" msgstr "Konnte SASL Authentisierungsdaemon nicht starten" -#: ../pykolab/conf/__init__.py:582 +#: ../pykolab/conf/__init__.py:602 msgid "No imaplib library found." -msgstr "" +msgstr "Keine imaplib-Bibliothek gefunden." -#: ../pykolab/conf/__init__.py:592 +#: ../pykolab/conf/__init__.py:612 msgid "No LMTP class found in the smtplib library." -msgstr "" +msgstr "Keine Klasse namens LMTP in der smtplib-Bibliothek gefunden." -#: ../pykolab/conf/__init__.py:602 +#: ../pykolab/conf/__init__.py:622 msgid "No SMTP class found in the smtplib library." -msgstr "" +msgstr "Keine Klasse namens SMTP in der smtplib-Bibliothek gefunden." -#: ../pykolab/conf/__init__.py:616 +#: ../pykolab/conf/__init__.py:636 #, python-format msgid "Found you specified a specific set of items to test: %s" msgstr "" -#: ../pykolab/conf/__init__.py:624 +#: ../pykolab/conf/__init__.py:644 #, python-format msgid "Selectively selecting: %s" msgstr "" @@ -1137,263 +1543,383 @@ msgid "OpenLDAP or compatible" msgstr "OpenLDAP oder kompatibel" -#: ../pykolab/imap/cyrus.py:79 +#: ../pykolab/imap/cyrus.py:80 #, python-format msgid "Could not connect to Cyrus IMAP server %r" -msgstr "" +msgstr "Verbindung zum Cyrus IMAP-Server %r nicht möglich" -#: ../pykolab/imap/cyrus.py:134 +#: ../pykolab/imap/cyrus.py:137 #, python-format msgid "Continuing with separator: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:139 +#: ../pykolab/imap/cyrus.py:142 msgid "Detected we are running in a Murder topology" msgstr "" -#: ../pykolab/imap/cyrus.py:143 +#: ../pykolab/imap/cyrus.py:146 msgid "This system is not part of a murder topology" msgstr "" -#: ../pykolab/imap/cyrus.py:164 +#: ../pykolab/imap/cyrus.py:167 #, python-format msgid "Checking actual backend server for folder %s through annotations" msgstr "" -#: ../pykolab/imap/cyrus.py:179 +#: ../pykolab/imap/cyrus.py:172 +msgid "Possibly reproducing the find " +msgstr "" + +#: ../pykolab/imap/cyrus.py:195 #, python-format msgid "Could not get the annotations after %s tries." msgstr "" -#: ../pykolab/imap/cyrus.py:183 +#: ../pykolab/imap/cyrus.py:199 #, python-format msgid "No annotations for %s: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:190 +#: ../pykolab/imap/cyrus.py:206 #, python-format msgid "Server for INBOX folder %s is %s" msgstr "" -#: ../pykolab/imap/cyrus.py:202 +#: ../pykolab/imap/cyrus.py:226 #, python-format msgid "Setting quota for folder %s to %s" msgstr "" -#: ../pykolab/imap/cyrus.py:206 +#: ../pykolab/imap/cyrus.py:230 #, python-format msgid "Could not set quota for mailfolder %s" msgstr "" -#: ../pykolab/imap/cyrus.py:215 +#: ../pykolab/imap/cyrus.py:239 #, python-format msgid "Moving INBOX folder %s to %s" -msgstr "" +msgstr "Verschiebe Eingangsordner %s nach %s" -#: ../pykolab/imap/cyrus.py:227 +#: ../pykolab/imap/cyrus.py:254 #, python-format msgid "Setting annotation %s on folder %s" msgstr "" -#: ../pykolab/imap/cyrus.py:234 +#: ../pykolab/imap/cyrus.py:259 #, python-format msgid "Could not set annotation %r on mail folder %r: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:238 +#: ../pykolab/imap/cyrus.py:263 #, python-format msgid "Transferring folder %s from %s to %s" msgstr "" -#: ../pykolab/imap/cyrus.py:298 +#: ../pykolab/imap/cyrus.py:323 #, python-format msgid "Undeleting %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:45 +#: ../pykolab/imap/cyrus.py:334 #, python-format -msgid "Cleaning up ACL entries for %s across all folders" +msgid "Would have transfered %s from %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:60 +#: ../pykolab/imap/cyrus.py:336 #, python-format -msgid "Cleaning up ACL entries referring to identifier %s" +msgid "Would have renamed %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:69 +#: ../pykolab/imap/__init__.py:46 +#, python-format +msgid "Cleaning up ACL entries for %s across all folders" +msgstr "" + +#: ../pykolab/imap/__init__.py:61 +#, python-format +msgid "Cleaning up ACL entries referring to identifier %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:70 #, python-format msgid "Iterating over %d folders" msgstr "" #. Set the ACL to '' (effectively deleting the ACL entry) -#: ../pykolab/imap/__init__.py:82 +#: ../pykolab/imap/__init__.py:83 #, python-format msgid "Removing acl %r for subject %r from folder %r" msgstr "" -#: ../pykolab/imap/__init__.py:143 +#: ../pykolab/imap/__init__.py:145 +msgid "No administrator password is available." +msgstr "" + +#: ../pykolab/imap/__init__.py:153 #, python-format msgid "Logging on to Cyrus IMAP server %s" -msgstr "" +msgstr "Anmeldung am Cyrus IMAP Server %s" -#: ../pykolab/imap/__init__.py:152 +#: ../pykolab/imap/__init__.py:162 #, python-format msgid "Logging on to Dovecot IMAP server %s" -msgstr "" +msgstr "Anmeldung am Dovecot IMAP Server %s" -#: ../pykolab/imap/__init__.py:161 +#: ../pykolab/imap/__init__.py:171 #, python-format msgid "Logging on to generic IMAP server %s" -msgstr "" +msgstr "Anmeldung am generischen IMAP Server %s" -#: ../pykolab/imap/__init__.py:179 +#: ../pykolab/imap/__init__.py:189 #, python-format msgid "Reusing existing IMAP server connection to %s" msgstr "Benutze Verbindung zum IMAP Server %s wieder" -#: ../pykolab/imap/__init__.py:181 +#: ../pykolab/imap/__init__.py:191 #, python-format msgid "Reconnecting to IMAP server %s" msgstr "Verbinde nochmal zum IMAP Server %s" -#: ../pykolab/imap/__init__.py:197 +#: ../pykolab/imap/__init__.py:208 msgid "Called imap.disconnect() on a server that we had no connection to." msgstr "" -#: ../pykolab/imap/__init__.py:212 +#: ../pykolab/imap/__init__.py:222 ../pykolab/imap/__init__.py:234 #, python-format -msgid "%r has no attribute %s" -msgstr "%r hat kein Attribut %s" +msgid "Could not create folder %r" +msgstr "" -#: ../pykolab/imap/__init__.py:285 -msgid "Private annotations need to be set using the appropriate user account." +#: ../pykolab/imap/__init__.py:223 +#, python-format +msgid " on server %r" msgstr "" -#: ../pykolab/imap/__init__.py:318 ../pykolab/imap/__init__.py:353 +#: ../pykolab/imap/__init__.py:244 ../pykolab/imap/__init__.py:246 +#, python-format +msgid "%r has no attribute %s" +msgstr "%r hat kein Attribut %s" + +#: ../pykolab/imap/__init__.py:393 ../pykolab/imap/__init__.py:428 #, python-format msgid "Creating new shared folder %s" msgstr "Erzeuge einen neuen geteilten Ordner %s" -#: ../pykolab/imap/__init__.py:375 +#: ../pykolab/imap/__init__.py:453 ../pykolab/imap/__init__.py:675 +#, python-format +msgid "Downcasing mailbox name %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:457 #, python-format msgid "Creating new mailbox for user %s" msgstr "Erzeuge eine neue Mailbox für Benutzer %s" -#: ../pykolab/imap/__init__.py:404 +#: ../pykolab/imap/__init__.py:470 +msgid "Waiting for the Cyrus IMAP Murder to settle..." +msgstr "" + +#: ../pykolab/imap/__init__.py:516 #, python-format msgid "Creating additional folders for user %s" msgstr "Erzeuge weitere Order für Benutzer %s" -#: ../pykolab/imap/__init__.py:428 +#: ../pykolab/imap/__init__.py:535 +#, python-format +msgid "Waiting for the Cyrus murder to settle... %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:547 +#, python-format +msgid "Correcting additional folder name from %r to %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:553 #, python-format msgid "Mailbox already exists: %s" msgstr "Mailbox existiert bereits: %s" -#: ../pykolab/imap/__init__.py:471 +#: ../pykolab/imap/__init__.py:593 msgid "Subscribing user to the additional folders" msgstr "Abonniere weitere Ordner für den Benutzer" -#: ../pykolab/imap/__init__.py:531 ../pykolab/imap/__init__.py:605 +#: ../pykolab/imap/__init__.py:607 +msgid "Using the following tests for folder subscriptions:" +msgstr "" + +#: ../pykolab/imap/__init__.py:609 +#, python-format +msgid " %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:612 +#, python-format +msgid "Folder %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:624 +#, python-format +msgid "Subscribing %s to folder %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:628 +#, python-format +msgid "Subscribing %s to folder %s failed: %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:658 +#, python-format +msgid "Could not rename %s to reside on partition %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:691 +#, python-format +msgid "INBOX folder to rename (%s) does not exist" +msgstr "" + +#: ../pykolab/imap/__init__.py:694 ../pykolab/imap/__init__.py:770 #, python-format msgid "Renaming INBOX from %s to %s" msgstr "Benenne INBOX Ordner von %s in %s um" -#: ../pykolab/imap/__init__.py:535 +#: ../pykolab/imap/__init__.py:698 #, python-format msgid "Could not rename INBOX folder %s to %s" msgstr "Konnte INBOX Ordner nicht von %s in %s umbenennen" -#: ../pykolab/imap/__init__.py:537 ../pykolab/imap/__init__.py:609 +#: ../pykolab/imap/__init__.py:700 ../pykolab/imap/__init__.py:774 #, python-format msgid "" "Moving INBOX folder %s won't succeed as target folder %s already exists" +msgstr "Der INBOX-Ordner %s kann nicht verschoben werden, weil der Zielordner %s bereits existiert" + +#: ../pykolab/imap/__init__.py:704 +#, python-format +msgid "Server for mailbox %r is %r" msgstr "" -#: ../pykolab/imap/__init__.py:547 +#: ../pykolab/imap/__init__.py:712 #, python-format msgid "Looking for folder '%s', we found folders: %r" -msgstr "" +msgstr "Auf der Suche nach dem Ordner '%s' haben wir diese Ordner gefunden: %r" -#: ../pykolab/imap/__init__.py:570 +#: ../pykolab/imap/__init__.py:735 #, python-format msgid "Setting ACL rights %s for subject %s on folder " msgstr "Richte ACL Rechte %s für Subjekt %s des Ordners ein" -#: ../pykolab/imap/__init__.py:581 +#: ../pykolab/imap/__init__.py:746 #, python-format msgid "Removing ACL rights %s for subject %s on folder " msgstr "" -#: ../pykolab/imap/__init__.py:602 +#: ../pykolab/imap/__init__.py:767 #, python-format msgid "Found old INBOX folder %s" -msgstr "" +msgstr "Alter INBOX-Ordner %s gefunden" -#: ../pykolab/imap/__init__.py:611 +#: ../pykolab/imap/__init__.py:776 #, python-format msgid "Did not find old folder user/%s to rename" msgstr "Konnte alten Ordner user/%s nicht zum umbenennen finden." -#: ../pykolab/imap/__init__.py:613 +#: ../pykolab/imap/__init__.py:778 msgid "Value for user is not a dictionary" msgstr "Der Wert für user ist kein dictionary" #. TODO: Go in fact correct the quota. -#: ../pykolab/imap/__init__.py:673 +#: ../pykolab/imap/__init__.py:846 #, python-format msgid "Cannot get current IMAP quota for folder %s" msgstr "Kann aktuelles IMAP Kontingent für den Ordner %s nicht bekommen" -#: ../pykolab/imap/__init__.py:686 +#: ../pykolab/imap/__init__.py:859 #, python-format msgid "Quota for %s currently is %s" msgstr "Kontingent für %s ist aktuell %s" -#: ../pykolab/imap/__init__.py:692 +#: ../pykolab/imap/__init__.py:865 #, python-format msgid "Adjusting authentication database quota for folder %s to %d" msgstr "" -#: ../pykolab/imap/__init__.py:697 +#: ../pykolab/imap/__init__.py:870 #, python-format msgid "Correcting quota for %s to %s (currently %s)" msgstr "" -#: ../pykolab/imap/__init__.py:774 +#: ../pykolab/imap/__init__.py:947 #, python-format msgid "Checking folder: %s" msgstr "Überprüfe Ordner: %s" -#: ../pykolab/imap/__init__.py:779 +#: ../pykolab/imap/__init__.py:952 #, python-format msgid "Folder has no corresponding user (1): %s" msgstr "" -#: ../pykolab/imap/__init__.py:782 +#: ../pykolab/imap/__init__.py:955 #, python-format msgid "Folder has no corresponding user (2): %s" msgstr "" #. We got user identifier only -#: ../pykolab/imap/__init__.py:797 +#: ../pykolab/imap/__init__.py:970 msgid "Please don't give us just a user identifier" msgstr "" -#: ../pykolab/imap/__init__.py:800 +#: ../pykolab/imap/__init__.py:973 #, python-format msgid "Deleting folder %s" -msgstr "" +msgstr "Lösche Verzeichnis %s" #: ../pykolab/__init__.py:50 msgid "Returning thread local configuration" msgstr "" -#: ../pykolab/logger.py:105 +#: ../pykolab/itip/__init__.py:43 +#, python-format +msgid "Method %r not really interesting for us." +msgstr "" + +#: ../pykolab/itip/__init__.py:49 +#, python-format +msgid "Raw iTip payload: %s" +msgstr "" + +#: ../pykolab/itip/__init__.py:59 +msgid "Could not read iTip from message." +msgstr "" + +#: ../pykolab/itip/__init__.py:67 +#, python-format +msgid "Duplicate iTip object: %s" +msgstr "" + +#: ../pykolab/itip/__init__.py:90 +msgid "iTip event without a start" +msgstr "" + +#: ../pykolab/itip/__init__.py:132 +msgid "Message is not an iTip message (non-multipart message)" +msgstr "" + +#: ../pykolab/itip/__init__.py:225 +#, python-format +msgid "Failed to compose iTip reply message: %r" +msgstr "" + +#: ../pykolab/itip/__init__.py:236 ../wallace/module_invitationpolicy.py:936 +#: ../wallace/module_resources.py:964 #, python-format -msgid "Could not change the ownership of log file %s" +msgid "SMTP sendmail error: %r" msgstr "" -#: ../pykolab/logger.py:121 +#: ../pykolab/logger.py:173 ../pykolab/logger.py:179 +#, python-format +msgid "Could not change permissions on %s: %r" +msgstr "" + +#: ../pykolab/logger.py:196 #, python-format msgid "Cannot log to file %s: %s" msgstr "" @@ -1425,12 +1951,12 @@ #: ../pykolab/plugins/__init__.py:74 #, python-format msgid "RuntimeError for plugin %s: %s" -msgstr "" +msgstr "Laufzeitfehler von Plugin %s: %s" #: ../pykolab/plugins/__init__.py:78 #, python-format msgid "Plugin %s failed to load (%s: %s)" -msgstr "" +msgstr "Plugin %s konnte nicht geladen werden (%s: %s)" #: ../pykolab/plugins/__init__.py:116 ../pykolab/plugins/__init__.py:118 #, python-format @@ -1470,7 +1996,7 @@ #: ../pykolab/plugins/__init__.py:187 #, python-format msgid "Cannot check options for plugin %s: %s" -msgstr "" +msgstr "Kein Zugriff auf Einstellungen des Plugins %s: %s" #: ../pykolab/plugins/__init__.py:189 #, python-format @@ -1491,16 +2017,51 @@ msgid "Attribute substitution for 'mail' failed in Recipient Policy" msgstr "" -#: ../pykolab/plugins/recipientpolicy/__init__.py:115 +#: ../pykolab/plugins/recipientpolicy/__init__.py:116 msgid "Could not parse the alternative mail routines" msgstr "" +#: ../pykolab/plugins/recipientpolicy/__init__.py:120 +#, python-format +msgid "Alternative mail routines: %r" +msgstr "" + #: ../pykolab/plugins/recipientpolicy/__init__.py:127 -#: ../pykolab/plugins/recipientpolicy/__init__.py:137 +#, python-format +msgid "" +"An error occurred in composing the secondary mail attribute for entry %r" +msgstr "" + +#: ../pykolab/plugins/recipientpolicy/__init__.py:138 +#: ../pykolab/plugins/recipientpolicy/__init__.py:153 +#, python-format +msgid "Appending additional mail address: %s" +msgstr "" + +#: ../pykolab/plugins/recipientpolicy/__init__.py:142 +#, python-format +msgid "Policy for secondary email address failed: %r" +msgstr "" + +#: ../pykolab/plugins/recipientpolicy/__init__.py:157 msgid "" "Attribute substitution for 'alternative_mail' failed in Recipient Policy" msgstr "" +#: ../pykolab/plugins/roundcubedb/__init__.py:48 +#, python-format +msgid "user_delete: %r" +msgstr "" + +#: ../pykolab/plugins/roundcubedb/__init__.py:55 +#: ../pykolab/setup/setup_roundcube.py:160 +msgid "Roundcube installation path not found." +msgstr "" + +#: ../pykolab/plugins/sievemgmt/__init__.py:51 +msgid "Wrong number of arguments for sieve management plugin" +msgstr "" + #: ../pykolab/setup/components.py:58 msgid "Display this help." msgstr "Zeige diese Hilfe." @@ -1521,47 +2082,27 @@ msgid "Free/Busy is not installed on this system" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:55 -msgid "" -"\n" -" Please supply the MySQL password for the 'roundcube'\n" -" user. You have supplied this password earlier, and it is\n" -" available from the database URI setting in\n" -" /etc/roundcubemail/db.inc.php.\n" -" " -msgstr "" - -#: ../pykolab/setup/setup_freebusy.py:64 -#: ../pykolab/setup/setup_roundcube.py:56 -msgid "MySQL roundcube password" -msgstr "MySQL roundcube Passwort" +#: ../pykolab/setup/setup_imap.py:45 +msgid "Setup IMAP." +msgstr "Richte IMAP ein." -#: ../pykolab/setup/setup_freebusy.py:92 -#: ../pykolab/setup/setup_roundcube.py:116 ../pykolab/setup/setup_zpush.py:71 -#, python-format -msgid "Using template file %r" +#: ../pykolab/setup/setup_imap.py:89 +msgid "Could not write out Cyrus IMAP configuration file /etc/imapd.conf" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:99 -#: ../pykolab/setup/setup_roundcube.py:123 ../pykolab/setup/setup_zpush.py:78 -#, python-format -msgid "Successfully compiled template %r, writing out to %r" +#: ../pykolab/setup/setup_imap.py:114 +msgid "Could not write out Cyrus IMAP configuration file /etc/cyrus.conf" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:119 ../pykolab/setup/setup_imap.py:143 -#: ../pykolab/setup/setup_ldap.py:288 ../pykolab/setup/setup_ldap.py:521 -#: ../pykolab/setup/setup_mta.py:309 ../pykolab/setup/setup_mysql.py:49 -#: ../pykolab/setup/setup_roundcube.py:191 -#: ../pykolab/setup/setup_syncroton.py:66 ../pykolab/setup/setup_zpush.py:98 -msgid "Could not start and configure to start on boot, the " +#: ../pykolab/setup/setup_imap.py:158 +msgid "Could not start the cyrus-imapd and kolab-saslauthd services." msgstr "" -#: ../pykolab/setup/setup_imap.py:44 -msgid "Setup IMAP." -msgstr "Richte IMAP ein." - -#: ../pykolab/setup/setup_imap.py:88 ../pykolab/setup/setup_imap.py:113 -msgid "Could not write out Cyrus IMAP configuration file /etc/imapd.conf" +#: ../pykolab/setup/setup_imap.py:173 ../pykolab/setup/setup_kolabd.py:81 +#: ../pykolab/setup/setup_ldap.py:426 ../pykolab/setup/setup_mta.py:455 +#: ../pykolab/setup/setup_mysql.py:58 ../pykolab/setup/setup_roundcube.py:237 +#: ../pykolab/setup/setup_syncroton.py:102 +msgid "Could not configure to start on boot, the " msgstr "" #: ../pykolab/setup/setup_kolabd.py:43 @@ -1577,23 +2118,62 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:43 +#: ../pykolab/setup/setup_kolabd.py:72 +msgid "Could not start the kolab server service." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:45 msgid "LDAP Options" msgstr "LDAP Optionen" -#: ../pykolab/setup/setup_ldap.py:50 +#: ../pykolab/setup/setup_ldap.py:52 msgid "Specify FQDN (overriding defaults)." msgstr "" -#: ../pykolab/setup/setup_ldap.py:58 +#: ../pykolab/setup/setup_ldap.py:60 msgid "Allow anonymous binds (default: no)." msgstr "" -#: ../pykolab/setup/setup_ldap.py:62 +#: ../pykolab/setup/setup_ldap.py:68 +msgid "Skip setting up the LDAP server." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:76 +msgid "Setup configuration for OpenLDAP compatibility." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:84 +msgid "Setup configuration for Active Directory compatibility." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:88 msgid "Setup LDAP." msgstr "LDAP Einrichten" -#: ../pykolab/setup/setup_ldap.py:74 +#: ../pykolab/setup/setup_ldap.py:97 +msgid "Skipping setup of LDAP, as specified" +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:126 +msgid "" +"\n" +" You can not configure Kolab to run against OpenLDAP\n" +" and Active Directory simultaneously.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:139 +msgid "" +"\n" +" It seems 389 Directory Server has an existing\n" +" instance configured. This setup script does not\n" +" intend to destroy or overwrite your data. Please\n" +" make sure /etc/dirsrv/ and /var/lib/dirsrv/ are\n" +" clean so that this setup does not have to worry.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:154 msgid "" "\n" " Please supply a password for the LDAP administrator user\n" @@ -1602,11 +2182,11 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:82 +#: ../pykolab/setup/setup_ldap.py:162 msgid "Administrator password" msgstr "Administrator Passwort" -#: ../pykolab/setup/setup_ldap.py:89 +#: ../pykolab/setup/setup_ldap.py:169 msgid "" "\n" " Please supply a password for the LDAP Directory Manager\n" @@ -1616,11 +2196,11 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:98 +#: ../pykolab/setup/setup_ldap.py:178 msgid "Directory Manager password" msgstr "Verzeichnismanager Passwort" -#: ../pykolab/setup/setup_ldap.py:105 +#: ../pykolab/setup/setup_ldap.py:185 msgid "" "\n" " Please choose the system user and group the service\n" @@ -1629,15 +2209,15 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:112 +#: ../pykolab/setup/setup_ldap.py:195 ../pykolab/setup/setup_ldap.py:198 msgid "User" msgstr "Benutzer" -#: ../pykolab/setup/setup_ldap.py:113 +#: ../pykolab/setup/setup_ldap.py:196 ../pykolab/setup/setup_ldap.py:199 msgid "Group" msgstr "Gruppe" -#: ../pykolab/setup/setup_ldap.py:143 +#: ../pykolab/setup/setup_ldap.py:234 msgid "" "\n" " This setup procedure plans to set up Kolab Groupware for\n" @@ -1648,18 +2228,18 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:157 +#: ../pykolab/setup/setup_ldap.py:248 msgid "Domain name to use" msgstr "" -#: ../pykolab/setup/setup_ldap.py:162 ../pykolab/setup/setup_ldap.py:187 +#: ../pykolab/setup/setup_ldap.py:253 ../pykolab/setup/setup_ldap.py:278 msgid "" "\n" " Invalid input. Please try again.\n" " " -msgstr "" +msgstr "\n Ungültige Eingabe. Bitte nochmals versuchen.\n " -#: ../pykolab/setup/setup_ldap.py:171 +#: ../pykolab/setup/setup_ldap.py:262 msgid "" "\n" " The standard root dn we composed for you follows. Please\n" @@ -1667,11 +2247,15 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:182 +#: ../pykolab/setup/setup_ldap.py:273 msgid "Root DN to use" msgstr "" -#: ../pykolab/setup/setup_ldap.py:234 +#: ../pykolab/setup/setup_ldap.py:325 +msgid "No directory server setup tool available." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:337 msgid "" "\n" " Setup is now going to set up the 389 Directory Server. This\n" @@ -1680,24 +2264,42 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:241 +#: ../pykolab/setup/setup_ldap.py:344 msgid "Setting up 389 Directory Server" msgstr "Richte 389 Verzeichnisserver ein" -#. TODO: Get the return code and display output if not successful. -#: ../pykolab/setup/setup_ldap.py:253 +#: ../pykolab/setup/setup_ldap.py:356 +msgid "" +"\n" +" An error was detected in the setup procedure for 389\n" +" Directory Server. This setup will write out stderr and\n" +" stdout to /var/log/kolab/setup.error.log and\n" +" /var/log/kolab/setup.out.log respectively, before it\n" +" exits.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:373 msgid "Setup DS stdout:" msgstr "" -#: ../pykolab/setup/setup_ldap.py:256 +#: ../pykolab/setup/setup_ldap.py:376 msgid "Setup DS stderr:" msgstr "" -#: ../pykolab/setup/setup_ldap.py:279 ../pykolab/setup/setup_mysql.py:129 -msgid "Could not find the Kolab schema file" -msgstr "Konnte Kolab Schema Datei nicht finden" +#: ../pykolab/setup/setup_ldap.py:402 +msgid "Could not copy the LDAP extensions for Kolab" +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:405 +msgid "Could not find the ldap Kolab schema file" +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:417 +msgid "Could not start the directory server service." +msgstr "" -#: ../pykolab/setup/setup_ldap.py:293 +#: ../pykolab/setup/setup_ldap.py:431 msgid "" "\n" " Please supply a Cyrus Administrator password. This\n" @@ -1708,11 +2310,11 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:303 +#: ../pykolab/setup/setup_ldap.py:441 msgid "Cyrus Administrator password" msgstr "Cyrus Administrator Passwort" -#: ../pykolab/setup/setup_ldap.py:310 +#: ../pykolab/setup/setup_ldap.py:448 msgid "" "\n" " Please supply a Kolab Service account password. This\n" @@ -1722,98 +2324,127 @@ " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:319 +#: ../pykolab/setup/setup_ldap.py:457 msgid "Kolab Service password" msgstr "Kolab-Dienst-Passwort" -#: ../pykolab/setup/setup_ldap.py:329 +#: ../pykolab/setup/setup_ldap.py:467 msgid "Writing out configuration to kolab.conf" msgstr "Schreibe Einstellungen in kolab.conf" -#: ../pykolab/setup/setup_ldap.py:343 +#: ../pykolab/setup/setup_ldap.py:481 msgid "Inserting service users into LDAP." msgstr "Füge Service-Benutzer ins LDAP ein." -#: ../pykolab/setup/setup_ldap.py:417 +#: ../pykolab/setup/setup_ldap.py:555 msgid "Writing out cn=kolab,cn=config" msgstr "Schreibe cn=kolab,cn=config" #. TODO: Add kolab-admin role #. TODO: Assign kolab-admin admin ACLs -#: ../pykolab/setup/setup_ldap.py:441 +#: ../pykolab/setup/setup_ldap.py:579 #, python-format msgid "Adding domain %s to list of domains for this deployment" msgstr "Füge Domain %s zu dieser Installation hinzu" -#: ../pykolab/setup/setup_ldap.py:457 +#: ../pykolab/setup/setup_ldap.py:607 msgid "Disabling anonymous binds" msgstr "Stelle anonymes Binden ab" #. TODO: Ensure the uid attribute is unique #. TODO^2: Consider renaming the general "attribute uniqueness to "uid #. attribute uniqueness" -#: ../pykolab/setup/setup_ldap.py:465 +#: ../pykolab/setup/setup_ldap.py:615 msgid "Enabling attribute uniqueness plugin" msgstr "" -#: ../pykolab/setup/setup_ldap.py:471 +#: ../pykolab/setup/setup_ldap.py:621 msgid "Enabling referential integrity plugin" msgstr "" -#: ../pykolab/setup/setup_ldap.py:477 +#: ../pykolab/setup/setup_ldap.py:627 msgid "Enabling and configuring account policy plugin" msgstr "" #. TODO: Add kolab-admin role -#: ../pykolab/setup/setup_ldap.py:492 +#: ../pykolab/setup/setup_ldap.py:642 msgid "Adding the kolab-admin role" msgstr "Füge Kolab-Admin Rolle hinzu" #. TODO: User writeable attributes on root_dn -#: ../pykolab/setup/setup_ldap.py:503 +#: ../pykolab/setup/setup_ldap.py:653 #, python-format msgid "Setting access control to %s" msgstr "" -#: ../pykolab/setup/setup_mta.py:40 +#: ../pykolab/setup/setup_ldap.py:679 +msgid "Could not start and configure to start on boot, the " +msgstr "" + +#: ../pykolab/setup/setup_mta.py:41 msgid "Setup MTA." msgstr "Richte MTA ein." -#: ../pykolab/setup/setup_mta.py:224 ../pykolab/setup/setup_php.py:80 +#: ../pykolab/setup/setup_mta.py:317 ../pykolab/setup/setup_php.py:106 #, python-format msgid "Setting key %r to %r" msgstr "" -#: ../pykolab/setup/setup_mta.py:252 +#: ../pykolab/setup/setup_mta.py:350 msgid "Could not write out Postfix configuration file /etc/postfix/master.cf" msgstr "" -#: ../pykolab/setup/setup_mta.py:287 -msgid "" -"Could not write out Amavis configuration file /etc/amavisd/amavisd.conf" +#: ../pykolab/setup/setup_mta.py:397 +msgid "Could not write out Amavis configuration file amavisd.conf" +msgstr "" + +#: ../pykolab/setup/setup_mta.py:405 +msgid "Not writing out any configuration for Amavis." +msgstr "" + +#: ../pykolab/setup/setup_mta.py:437 +msgid "Could not start the postfix, clamav and amavisd services services." msgstr "" #: ../pykolab/setup/setup_mysql.py:39 msgid "Setup MySQL." msgstr "Richte MySQL ein." -#: ../pykolab/setup/setup_mysql.py:53 +#: ../pykolab/setup/setup_mysql.py:49 +msgid "Could not start the MySQL database service." +msgstr "" + +#: ../pykolab/setup/setup_mysql.py:71 +msgid "What MySQL server are we setting up?" +msgstr "" + +#: ../pykolab/setup/setup_mysql.py:75 msgid "" "\n" -" Please supply a root password for MySQL. This password will\n" -" be the administrative user for this MySQL server, and it\n" -" should be kept a secret. After this setup process has\n" -" completed, Kolab is going to discard and forget about this\n" -" password, but you will need it for administrative tasks in\n" -" MySQL.\n" -" " +" Please supply the root password for MySQL, so we can set\n" +" up user accounts for other components that use MySQL.\n" +" " msgstr "" -#: ../pykolab/setup/setup_mysql.py:64 +#: ../pykolab/setup/setup_mysql.py:82 ../pykolab/setup/setup_mysql.py:99 +#: ../pykolab/setup/setup_roundcube.py:183 +#: ../pykolab/setup/setup_syncroton.py:63 msgid "MySQL root password" +msgstr "MySQL root Password" + +#: ../pykolab/setup/setup_mysql.py:88 +msgid "" +"\n" +" Please supply a root password for MySQL. This password\n" +" will be the administrative user for this MySQL server,\n" +" and it should be kept a secret. After this setup process\n" +" has completed, Kolab is going to discard and forget\n" +" about this password, but you will need it for\n" +" administrative tasks in MySQL.\n" +" " msgstr "" -#: ../pykolab/setup/setup_mysql.py:103 +#: ../pykolab/setup/setup_mysql.py:139 msgid "" "\n" " Please supply a password for the MySQL user 'kolab'.\n" @@ -1822,8 +2453,12 @@ " " msgstr "" -#: ../pykolab/setup/setup_mysql.py:111 +#: ../pykolab/setup/setup_mysql.py:147 msgid "MySQL kolab password" +msgstr "MySQL-kolab Password" + +#: ../pykolab/setup/setup_mysql.py:165 +msgid "Could not find the MySQL Kolab schema file" msgstr "" #: ../pykolab/setup/setup_php.py:42 @@ -1832,23 +2467,38 @@ #: ../pykolab/setup/setup_php.py:49 msgid "Specify the timezone for PHP." +msgstr "Zeitzone für PHP definieren." + +#: ../pykolab/setup/setup_php.py:57 +msgid "Specify the path to the php.ini file used with the webserver." msgstr "" -#: ../pykolab/setup/setup_php.py:53 +#: ../pykolab/setup/setup_php.py:61 msgid "Setup PHP." msgstr "Richte PHP ein." -#: ../pykolab/setup/setup_php.py:58 +#: ../pykolab/setup/setup_php.py:66 msgid "" "\n" " Please supply the timezone PHP should be using.\n" +" You have to use a Continent or Country / City locality name\n" +" like 'Europe/Berlin', but not just 'CEST'.\n" " " msgstr "" -#: ../pykolab/setup/setup_php.py:64 +#: ../pykolab/setup/setup_php.py:74 msgid "Timezone ID" msgstr "Zeitzonen ID" +#: ../pykolab/setup/setup_php.py:80 +#, python-format +msgid "Cannot configure PHP through %r (No such file or directory)" +msgstr "" + +#: ../pykolab/setup/setup_php.py:91 +msgid "Could not find PHP configuration file php.ini" +msgstr "" + #: ../pykolab/setup/setup_roundcube.py:44 msgid "Setup Roundcube." msgstr "Stelle Roundcube ein." @@ -1862,18 +2512,29 @@ " " msgstr "" -#: ../pykolab/setup/setup_syncroton.py:40 -msgid "Setup Syncroton." -msgstr "Richte Syncroton ein." +#: ../pykolab/setup/setup_roundcube.py:56 +msgid "MySQL roundcube password" +msgstr "MySQL roundcube Passwort" + +#: ../pykolab/setup/setup_roundcube.py:120 +#, python-format +msgid "Using template file %r" +msgstr "" -#: ../pykolab/setup/setup_zpush.py:41 -msgid "Setup zpush." -msgstr "zpush einrichten." +#: ../pykolab/setup/setup_roundcube.py:127 +#, python-format +msgid "Successfully compiled template %r, writing out to %r" +msgstr "" -#: ../pykolab/setup/setup_zpush.py:45 -msgid "Z-Push is not installed on this system" +#: ../pykolab/setup/setup_roundcube.py:228 +#: ../pykolab/setup/setup_syncroton.py:93 +msgid "Could not start the webserver server service." msgstr "" +#: ../pykolab/setup/setup_syncroton.py:40 +msgid "Setup Syncroton." +msgstr "Richte Syncroton ein." + #. start_max = (int)(time.time()) #: ../pykolab/telemetry.py:588 #, python-format @@ -1899,111 +2560,181 @@ msgid "No database available" msgstr "Keine Datenbank verfügbar" -#: ../pykolab/utils.py:57 ../pykolab/utils.py:59 +#: ../pykolab/utils.py:62 ../pykolab/utils.py:64 #, python-format msgid "Confirm %s: " -msgstr "" +msgstr "Bestätige %s:" -#: ../pykolab/utils.py:62 +#: ../pykolab/utils.py:67 msgid "Incorrect confirmation. " -msgstr "" +msgstr "Ungültige Bestätigung." -#: ../pykolab/utils.py:67 ../pykolab/utils.py:72 +#: ../pykolab/utils.py:72 ../pykolab/utils.py:77 #, python-format msgid "%s: " msgstr "%s:" -#: ../pykolab/utils.py:69 ../pykolab/utils.py:74 +#: ../pykolab/utils.py:74 ../pykolab/utils.py:79 #, python-format msgid "%s [%s]: " msgstr "%s [%s]: " -#: ../pykolab/utils.py:119 +#: ../pykolab/utils.py:124 msgid "Please answer 'yes' or 'no'." msgstr "Bitte antworten Sie mit 'yes' (ja) oder 'no' (nein)." -#: ../pykolab/utils.py:185 +#: ../pykolab/utils.py:164 +msgid "Choice" +msgstr "" + +#: ../pykolab/utils.py:167 +msgid "Choice (type '?' for options)" +msgstr "" + +#: ../pykolab/utils.py:268 #, python-format msgid "Could not change the permissions on %s" msgstr "" -#: ../pykolab/wap_client/__init__.py:257 +#: ../pykolab/utils.py:479 +#, python-format +msgid "Transliterating string %r with locale %r" +msgstr "" + +#: ../pykolab/utils.py:487 +msgid "Attempting to set locale" +msgstr "" + +#: ../pykolab/utils.py:489 +msgid "Success setting locale" +msgstr "" + +#: ../pykolab/utils.py:491 +msgid "Failure to set locale" +msgstr "" + +#: ../pykolab/utils.py:499 +#, python-format +msgid "Executing '%s | %s'" +msgstr "" + +#: ../pykolab/utils.py:510 +#, python-format +msgid "Could not translate %s using locale %s" +msgstr "" + +#: ../pykolab/wap_client/__init__.py:320 #, python-format msgid "Requesting %r with params %r" msgstr "" -#: ../pykolab/wap_client/__init__.py:263 +#: ../pykolab/wap_client/__init__.py:328 #, python-format msgid "Got response: %r" msgstr "" #. Some data is not JSON -#: ../pykolab/wap_client/__init__.py:268 +#: ../pykolab/wap_client/__init__.py:334 msgid "Response data is not JSON" msgstr "" -#: ../pykolab/xml/attendee.py:79 ../pykolab/xml/attendee.py:99 +#. support integer values, too +#: ../pykolab/xml/attendee.py:9 ../pykolab/xml/attendee.py:17 +msgid "Needs Action" +msgstr "" + +#: ../pykolab/xml/attendee.py:10 ../pykolab/xml/attendee.py:18 +msgid "Accepted" +msgstr "Akzeptiert" + +#: ../pykolab/xml/attendee.py:11 ../pykolab/xml/attendee.py:19 +msgid "Declined" +msgstr "Abgelehnt" + +#: ../pykolab/xml/attendee.py:12 ../pykolab/xml/attendee.py:20 +msgid "Tentatively Accepted" +msgstr "Provisorisch Akzeptiert" + +#: ../pykolab/xml/attendee.py:13 ../pykolab/xml/attendee.py:21 +msgid "Delegated" +msgstr "Delegiert" + +#: ../pykolab/xml/attendee.py:14 +msgid "Completed" +msgstr "" + +#: ../pykolab/xml/attendee.py:15 +msgid "In Process" +msgstr "" + +#: ../pykolab/xml/attendee.py:108 ../pykolab/xml/attendee.py:130 msgid "Not a valid attendee" msgstr "" -#: ../pykolab/xml/attendee.py:84 +#: ../pykolab/xml/attendee.py:115 msgid "No valid delegator references found" msgstr "" -#: ../pykolab/xml/attendee.py:104 +#: ../pykolab/xml/attendee.py:135 msgid "No valid delegatee references found" msgstr "" -#: ../pykolab/xml/attendee.py:140 +#: ../pykolab/xml/attendee.py:180 #, python-format msgid "Invalid cutype %r" msgstr "" -#: ../pykolab/xml/attendee.py:151 +#: ../pykolab/xml/attendee.py:192 #, python-format msgid "Invalid participant status %r" msgstr "" -#: ../pykolab/xml/attendee.py:159 +#: ../pykolab/xml/attendee.py:200 #, python-format msgid "Invalid role %r" msgstr "" -#: ../pykolab/xml/event.py:172 +#: ../pykolab/xml/event.py:100 ../pykolab/xml/event.py:708 +#: ../pykolab/xml/event.py:751 +msgid "Event start needs datetime.date or datetime.datetime instance" +msgstr "" + +#: ../pykolab/xml/event.py:241 #, python-format msgid "No attendee with email or name %r" msgstr "" -#: ../pykolab/xml/event.py:180 +#: ../pykolab/xml/event.py:249 #, python-format msgid "Invalid argument value attendee %r, must be basestring or Attendee" msgstr "" -#: ../pykolab/xml/event.py:186 +#: ../pykolab/xml/event.py:255 #, python-format msgid "No attendee with email %r" msgstr "" -#: ../pykolab/xml/event.py:192 +#: ../pykolab/xml/event.py:261 #, python-format msgid "No attendee with name %r" msgstr "" -#: ../pykolab/xml/event.py:338 +#: ../pykolab/xml/event.py:426 msgid "Invalid participant status" msgstr "" -#: ../pykolab/xml/event.py:538 -msgid "Event end needs datetime.date or datetime.datetime instance" +#: ../pykolab/xml/event.py:542 +#, python-format +msgid "Invalid status %r" msgstr "" -#: ../pykolab/xml/event.py:654 +#: ../pykolab/xml/event.py:550 #, python-format -msgid "Invalid status %r" +msgid "Invalid classification %r" msgstr "" -#: ../pykolab/xml/event.py:675 ../pykolab/xml/event.py:725 -msgid "Event start needs datetime.date or datetime.datetime instance" +#: ../pykolab/xml/event.py:577 +msgid "Event end needs datetime.date or datetime.datetime instance" msgstr "" #: ../pykolab/xml/event.py:761 @@ -2011,62 +2742,434 @@ msgid "Invalid status set: %r" msgstr "" -#: ../pykolab/xml/event.py:879 +#: ../pykolab/xml/event.py:923 msgid "No sender specified" msgstr "" -#: ../saslauthd/__init__.py:126 ../saslauthd/__init__.py:134 -#: ../wallace/__init__.py:362 ../wallace/__init__.py:371 -msgid "" -"Traceback occurred, please report a bug at http://bugzilla.kolabsys.com" -msgstr "Ein Fehler mit Traceback trat auf, bitte legen Sie einen Bericht auf http://bugzilla.kolabsys.com an" - -#: ../wallace/__init__.py:61 +#: ../pykolab/xml/event.py:932 +#, python-format +msgid "Invitation for %s was %s" +msgstr "" + +#: ../pykolab/xml/event.py:937 +msgid "This is an automated response to one of your event requests." +msgstr "" + +#: ../saslauthd/__init__.py:99 +#, python-format +msgid "Could not create %r: %r" +msgstr "" + +#: ../saslauthd/__init__.py:137 ../saslauthd/__init__.py:145 +#: ../wallace/__init__.py:403 ../wallace/__init__.py:412 +msgid "" +"Traceback occurred, please report a bug at http://bugzilla.kolabsys.com" +msgstr "Ein Fehler mit Traceback trat auf, bitte legen Sie einen Bericht auf http://bugzilla.kolabsys.com an" + +#: ../saslauthd/__init__.py:185 +msgid "kolab-saslauthd could not accept " +msgstr "" + +#: ../saslauthd/__init__.py:190 +msgid "Maximum tries exceeded, exiting" +msgstr "" + +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:190 +#: ../wallace/module_resources.py:879 +#, python-format +msgid "Reservation Request for %(summary)s was %(status)s" +msgstr "" + +#. check notification message sent to resource owner (jane) +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:605 +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:621 +#: ../wallace/module_resources.py:954 +#, python-format +msgid "Booking for %s has been %s" +msgstr "Buchung für %s wurde %s" + +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:146 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:720 +#: ../wallace/module_invitationpolicy.py:374 +#, python-format +msgid "\"%(summary)s\" has been %(status)s" +msgstr "\"%(summary)s\" wurde %(status)s" + +#. check for notification message +#. this notification should be suppressed until mark has replied, too +#. this triggers an additional notification +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:616 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:622 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:635 +#: ../wallace/module_invitationpolicy.py:925 +#, python-format +msgid "\"%s\" has been updated" +msgstr "\"%s\" wurde aktualisiert" + +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:627 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:639 +msgid "PENDING" +msgstr "" + +#: ../wallace/__init__.py:57 +#, python-format +msgid "Wallace modules: %r" +msgstr "" + +#: ../wallace/__init__.py:69 +#, python-format +msgid "Module %s.execute() failed on message %r with error: %s" +msgstr "" + +#: ../wallace/__init__.py:78 #, python-format msgid "Worker process %s initializing" msgstr "" -#: ../wallace/__init__.py:80 +#: ../wallace/__init__.py:100 msgid "Bind address for Wallace." -msgstr "" +msgstr "Bind-Adresse für Wallace." -#: ../wallace/__init__.py:106 +#: ../wallace/__init__.py:126 msgid "Port that Wallace is supposed to use." msgstr "Port, den Wallace benutzen soll." -#: ../wallace/__init__.py:157 +#: ../wallace/__init__.py:177 #, python-format msgid "Could not bind to socket on port %d on bind " msgstr "" -#: ../wallace/__init__.py:169 +#: ../wallace/__init__.py:189 msgid "Could not shut down socket" -msgstr "" +msgstr "Konnte Socket nicht schließen" -#: ../wallace/__init__.py:226 +#: ../wallace/__init__.py:253 msgid "Accepted connection" msgstr "Verbindung akzeptiert" -#: ../wallace/__init__.py:387 +#: ../wallace/__init__.py:428 #, python-format msgid "Could not write pid file %s" msgstr "" -#: ../wallace/module_optout.py:61 ../wallace/module_resources.py:94 +#: ../wallace/module_footer.py:60 ../wallace/module_gpgencrypt.py:60 +#: ../wallace/module_invitationpolicy.py:168 ../wallace/module_optout.py:61 +#: ../wallace/module_resources.py:120 #, python-format msgid "Issuing callback after processing to stage %s" msgstr "" -#: ../wallace/module_optout.py:62 ../wallace/module_resources.py:100 +#: ../wallace/module_footer.py:61 ../wallace/module_gpgencrypt.py:61 +#: ../wallace/module_invitationpolicy.py:170 ../wallace/module_optout.py:62 +#: ../wallace/module_resources.py:126 #, python-format msgid "Testing cb_action_%s()" msgstr "" -#: ../wallace/module_optout.py:64 ../wallace/module_resources.py:103 +#: ../wallace/module_footer.py:63 ../wallace/module_gpgencrypt.py:63 +#: ../wallace/module_invitationpolicy.py:172 ../wallace/module_optout.py:64 +#: ../wallace/module_resources.py:129 #, python-format msgid "Attempting to execute cb_action_%s()" msgstr "" +#: ../wallace/module_footer.py:67 +#, python-format +msgid "Executing module footer for %r, %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:66 +#, python-format +msgid "Executing module gpgencrypt for %r, %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:98 +msgid "Message is already encrypted (app/pgp-enc content-type)" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:102 +msgid "Message already encrypted by main content-type header" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:131 +msgid "" +"Configured to encrypt to a key not configured, and strict policy enabled. " +"Bailing out." +msgstr "" + +#: ../wallace/module_gpgencrypt.py:134 +msgid "" +"Configured to encrypt to a key not configured, but continuing anyway (see " +"'gpgencrypt_strict')." +msgstr "" + +#: ../wallace/module_gpgencrypt.py:171 +#, python-format +msgid "Recipients: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:183 +#, python-format +msgid "Current keys: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:188 +#, python-format +msgid "Retrieving key for recipient: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:192 ../wallace/module_gpgencrypt.py:208 +#, python-format +msgid "Found matching address %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:200 +#, python-format +msgid "Found matching address %r in remote keys" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:232 +#, python-format +msgid "An error occurred: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:154 +#, python-format +msgid "Invitation policy called for %r, %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:211 +#: ../wallace/module_resources.py:169 +#, python-format +msgid "Failed to parse iTip events from message: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:215 +msgid "" +"Message is not an iTip message or does not contain any (valid) iTip events." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:219 +#, python-format +msgid "" +"iTip events attached to this message contain the following information: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:232 +#, python-format +msgid "No itips, no users, pass along %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:235 +#, python-format +msgid "iTips, but no users, pass along %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:255 +#, python-format +msgid "No user attendee matching envelope recipient %s, skip message" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:259 +#, python-format +msgid "Receiving user: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:284 +#, python-format +msgid "Apply invitation policy %r for domain %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:295 +#, python-format +msgid "Ignoring '%s' iTip method" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:299 +#, python-format +msgid "iTip message %r consumed by the invitationpolicy module" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:315 +msgid "Pass invitation for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:320 +#, python-format +msgid "Receiving Attendee: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:339 +#, python-format +msgid "Existing event: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:350 +#, python-format +msgid "Precondition for event %r fulfilled: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:386 +#, python-format +msgid "No RSVP for recipient %r requested" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:412 +msgid "Pass reply for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:419 +#, python-format +msgid "Sender Attendee: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:431 +#, python-format +msgid "" +"The iTip reply sequence (%r) doesn't match the referred event version (%r). " +"Forwarding to Inbox." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:437 +#, python-format +msgid "Auto-updating event %r on iTip REPLY" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:459 +#: ../wallace/module_invitationpolicy.py:488 +msgid "" +"The event referred by this reply was not found in the user's calendars. " +"Forwarding to Inbox." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:472 +msgid "Pass cancellation for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:517 +#, python-format +msgid "Checking if email address %r belongs to a local user" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:522 +#, python-format +msgid "User DN: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:524 +#, python-format +msgid "No user record(s) found for %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:577 +#, python-format +msgid "User record doesn't have the mailbox attribute %r set" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:590 +#, python-format +msgid "IMAP proxy authentication failed: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:612 +#, python-format +msgid "List calendar folders for user %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:628 +#, python-format +msgid "IMAP metadata for %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:658 +#, python-format +msgid "Searching folder %r for event %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:670 +#: ../wallace/module_invitationpolicy.py:709 +#: ../wallace/module_resources.py:486 +#, python-format +msgid "Failed to parse event from message %s/%s: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:696 +#, python-format +msgid "Listing events from folder %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:715 +#, python-format +msgid "Existing event %r conflicts with invitation %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:722 +#: ../wallace/module_resources.py:344 +#, python-format +msgid "start: %r, end: %r, total: %r, messages: %d" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:748 +#, python-format +msgid "%r is locked, waiting..." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:811 +#, python-format +msgid "Failed to save event: no calendar folder found for user %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:814 +#, python-format +msgid "Save event %r to user calendar %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:827 +#, python-format +msgid "Failed to save event to user calendar at %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:843 +#, python-format +msgid "Delete event %r in %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:863 +#, python-format +msgid "Compose participation status summary for event %r to user %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:901 +#, python-format +msgid "" +"Waiting for more automated replies (got %d of %d); skipping notification" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:998 +#, python-format +msgid "Updated %s's copy of %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1001 +#, python-format +msgid "Attendee %s's copy of %r not found" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1004 +#, python-format +msgid "Attendee %r not found in LDAP" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1008 +#, python-format +msgid "" +"\n" +" %(name)s has %(status)s your invitation for %(summary)s.\n" +"\n" +" *** This is an automated response sent by the Kolab Invitation system ***\n" +" " +msgstr "" + #. modules.next_module('optout') #: ../wallace/module_optout.py:70 #, python-format @@ -2088,210 +3191,295 @@ msgid "Could not send request to optout_url %s" msgstr "" -#: ../wallace/module_resources.py:81 +#: ../wallace/module_resources.py:110 #, python-format msgid "Resource Management called for %r, %r" msgstr "" -#: ../wallace/module_resources.py:139 +#: ../wallace/module_resources.py:174 msgid "Message is not an iTip message or does not contain any " msgstr "" -#: ../wallace/module_resources.py:147 +#: ../wallace/module_resources.py:182 msgid "iTip events attached to this message contain the " msgstr "" -#: ../wallace/module_resources.py:174 +#: ../wallace/module_resources.py:205 msgid "Not an iTip message, but sent to resource nonetheless. Reject message" msgstr "" -#: ../wallace/module_resources.py:182 -msgid "No itips, no resources, pass along" +#: ../wallace/module_resources.py:213 +#, python-format +msgid "No itips, no resources, pass along %r" msgstr "" -#: ../wallace/module_resources.py:186 -msgid "iTips, but no resources, pass along" +#: ../wallace/module_resources.py:216 +#, python-format +msgid "iTips, but no resources, pass along %r" msgstr "" -#: ../wallace/module_resources.py:218 +#: ../wallace/module_resources.py:225 #, python-format -msgid "Resources: %r" +msgid "No resource attendees matching envelope recipient %s, Reject message" msgstr "" -#: ../wallace/module_resources.py:236 +#: ../wallace/module_resources.py:234 #, python-format -msgid "Checking events in resource folder %r" +msgid "Resources: %r; %r" msgstr "" -#: ../wallace/module_resources.py:243 +#: ../wallace/module_resources.py:244 #, python-format -msgid "Mailbox for resource %r doesn't exist" +msgid "Receiving Resource: %r; %r" msgstr "" -#: ../wallace/module_resources.py:256 +#: ../wallace/module_resources.py:252 #, python-format -msgid "Fetching message UID %r from folder %r" +msgid "Recipient %r is non-participant, ignoring message" msgstr "" -#: ../wallace/module_resources.py:295 +#: ../wallace/module_resources.py:279 #, python-format -msgid "Event %r conflicts with event " +msgid "Accept invitation for individual resource %r / %r" msgstr "" #: ../wallace/module_resources.py:308 #, python-format -msgid "start: %r, end: %r, total: %r, messages: %r" +msgid "Delegate invitation for resource collection %r to %r" +msgstr "" + +#: ../wallace/module_resources.py:340 +#, python-format +msgid "Failed to read resource calendar for %r: %r" msgstr "" -#: ../wallace/module_resources.py:315 +#: ../wallace/module_resources.py:350 #, python-format msgid "Polling for resource %r" msgstr "" -#: ../wallace/module_resources.py:319 +#: ../wallace/module_resources.py:353 #, python-format msgid "Resource %r has been popped from the list" msgstr "" -#: ../wallace/module_resources.py:326 +#: ../wallace/module_resources.py:357 msgid "Resource is a collection" msgstr "" -#: ../wallace/module_resources.py:374 ../wallace/module_resources.py:424 +#: ../wallace/module_resources.py:368 #, python-format -msgid "Adding event to %r" +msgid "Removed conflicting resources from %r: (%r) => %r" msgstr "" -#: ../wallace/module_resources.py:473 +#: ../wallace/module_resources.py:380 #, python-format -msgid "Method %r not really interesting for us." +msgid "Conflicting events: %r for resource %r" msgstr "" -#: ../wallace/module_resources.py:481 +#: ../wallace/module_resources.py:397 #, python-format -msgid "Raw iTip payload: %s" +msgid "Delegate to another resource collection member: %r to %r" msgstr "" -#: ../wallace/module_resources.py:491 -msgid "Could not read iTip from message." +#: ../wallace/module_resources.py:459 +#, python-format +msgid "Checking events in resource folder %r" msgstr "" -#: ../wallace/module_resources.py:513 -msgid "iTip event without a start" +#: ../wallace/module_resources.py:475 +#, python-format +msgid "Fetching message UID %r from folder %r" msgstr "" -#. end if c.name == "VEVENT" -#. end for c in cal.walk() -#. end if part.get_content_type() == "text/calendar" -#. end for part in message.walk() -#. if message.is_multipart() -#: ../wallace/module_resources.py:543 -msgid "Message is not an iTip message (non-multipart message)" +#: ../wallace/module_resources.py:498 +#, python-format +msgid "Event %r conflicts with event %r" msgstr "" -#: ../wallace/module_resources.py:564 +#: ../wallace/module_resources.py:525 #, python-format -msgid "Checking if email address %r belongs to a resource (collection)" +msgid "Adding event to %r: %r" msgstr "" -#: ../wallace/module_resources.py:575 ../wallace/module_resources.py:649 -#: ../wallace/module_resources.py:699 +#: ../wallace/module_resources.py:573 #, python-format -msgid "No resource (collection) records found for %r" +msgid "Failed to save event to resource calendar at %r: %r" +msgstr "" + +#: ../wallace/module_resources.py:590 +#, python-format +msgid "Delete resource calendar object %r in %r: %r" +msgstr "" + +#: ../wallace/module_resources.py:633 +#, python-format +msgid "Checking if email address %r belongs to a resource (collection)" msgstr "" -#: ../wallace/module_resources.py:583 ../wallace/module_resources.py:657 -#: ../wallace/module_resources.py:707 +#: ../wallace/module_resources.py:641 ../wallace/module_resources.py:709 +#: ../wallace/module_resources.py:743 #, python-format msgid "Resource record(s): %r" msgstr "" -#: ../wallace/module_resources.py:589 ../wallace/module_resources.py:664 -#: ../wallace/module_resources.py:714 +#: ../wallace/module_resources.py:643 ../wallace/module_resources.py:711 +#: ../wallace/module_resources.py:746 +#, python-format +msgid "No resource (collection) records found for %r" +msgstr "" + +#: ../wallace/module_resources.py:647 ../wallace/module_resources.py:715 +#: ../wallace/module_resources.py:750 #, python-format msgid "Resource record: %r" msgstr "" -#: ../wallace/module_resources.py:608 +#: ../wallace/module_resources.py:667 #, python-format msgid "Raw itip_events: %r" msgstr "" -#: ../wallace/module_resources.py:616 +#: ../wallace/module_resources.py:675 #, python-format msgid "Raw set of attendees: %r" msgstr "" -#: ../wallace/module_resources.py:624 +#: ../wallace/module_resources.py:683 #, python-format msgid "Raw set of resources: %r" msgstr "" -#: ../wallace/module_resources.py:638 +#: ../wallace/module_resources.py:702 #, python-format msgid "Checking if attendee %r is a resource (collection)" msgstr "" -#: ../wallace/module_resources.py:671 ../wallace/module_resources.py:717 +#: ../wallace/module_resources.py:718 ../wallace/module_resources.py:752 msgid "Resource reservation made but no resource records found" msgstr "" -#: ../wallace/module_resources.py:689 +#: ../wallace/module_resources.py:737 #, python-format msgid "Checking if resource %r is a resource (collection)" msgstr "" -#: ../wallace/module_resources.py:721 +#: ../wallace/module_resources.py:755 msgid "The following resources are being referred to in the " msgstr "" +#: ../wallace/module_resources.py:894 +#, python-format +msgid "" +"\n" +" *** This is an automated response, please do not reply! ***\n" +"\n" +" Your reservation was delegated to \"%s\" which is available for the requested time.\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:905 +#, python-format +msgid "" +"\n" +" *** This is an automated response, please do not reply! ***\n" +" \n" +" We hereby inform you that your reservation was %s.\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:912 +#, python-format +msgid "" +"\n" +" If you have questions about this reservation, please contact\n" +" %s <%s> %s\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:941 +#, python-format +msgid "Sending booking notification for event %r to %r from %r" +msgstr "" + +#: ../wallace/module_resources.py:954 +msgid "failed" +msgstr "" + +#: ../wallace/module_resources.py:973 +#, python-format +msgid "" +"\n" +" The resource booking for %(resource)s by %(orgname)s <%(orgemail)s> has been %(status)s for %(date)s.\n" +"\n" +" *** This is an automated message, sent to you as the resource owner. ***\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:979 +#, python-format +msgid "" +"\n" +" A reservation request for %(resource)s could not be processed automatically.\n" +" Please contact %(orgname)s <%(orgemail)s> who requested this resource for %(date)s. Subject: %(summary)s.\n" +"\n" +" *** This is an automated message, sent to you as the resource owner. ***\n" +" " +msgstr "" + #. This is a nested module -#: ../wallace/modules.py:96 +#: ../wallace/modules.py:97 #, python-format msgid "Module Group: %s" +msgstr "Modulgruppe: %s" + +#: ../wallace/modules.py:108 +#, python-format +msgid "No such module %r in modules %r (1)." msgstr "" -#: ../wallace/modules.py:107 ../wallace/modules.py:112 -msgid "No such module." +#: ../wallace/modules.py:113 +#, python-format +msgid "No such module %r in modules %r (2)." msgstr "" -#: ../wallace/modules.py:118 +#: ../wallace/modules.py:119 #, python-format msgid "Holding message in queue for manual review (%s by %s)" -msgstr "" +msgstr "Behalte Nachricht zur manuellen Prüfung in der Warteliste (%s von %s)" -#: ../wallace/modules.py:121 +#: ../wallace/modules.py:122 #, python-format msgid "Deferring message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:131 +#: ../wallace/modules.py:134 #, python-format msgid "The time when the message was sent: %r" -msgstr "" +msgstr "Zeitpunkt des Versandts: %r" -#: ../wallace/modules.py:132 +#: ../wallace/modules.py:135 #, python-format msgid "The time now: %r" msgstr "Die Zeit ist jetzt: %r" -#: ../wallace/modules.py:133 +#: ../wallace/modules.py:136 #, python-format msgid "The time delta: %r" -msgstr "" +msgstr "Die Zeitdifferenz: %r" #. TODO: Send NDR back to user -#: ../wallace/modules.py:137 +#: ../wallace/modules.py:140 #, python-format msgid "Message in file %s older then 5 days, deleting" msgstr "" -#: ../wallace/modules.py:162 +#: ../wallace/modules.py:165 #, python-format msgid "Rejecting message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:180 +#: ../wallace/modules.py:186 #, python-format msgid "" "This is the email system Wallace at %s.\n" @@ -2304,21 +3492,31 @@ "Your message is being delivered to any other recipients you may have\n" "sent your message to. There is no need to resend the message to those\n" "recipients.\n" -msgstr "" +msgstr "Ich bin das E-Mail-System Wallace auf %s.\n\nMit Bedauern muß ich Sie informieren, daß die angehängte Nachricht\nnicht an die folgenden Empfänger zugestellt werden konnte:\n\n- %s\n\nFalls Sie noch andere Empfänger angegeben haben wurde die Nachricht\nan diese zugestellt. An diese Empfänger müssen sie die Nachricht\nnicht erneut senden.\n" -#: ../wallace/modules.py:195 +#: ../wallace/modules.py:201 #, python-format msgid "" "X-Wallace-Module: %s\n" "X-Wallace-Result: REJECT\n" msgstr "" -#: ../wallace/modules.py:248 +#: ../wallace/modules.py:260 #, python-format msgid "Accepting message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:316 +#: ../wallace/modules.py:262 #, python-format -msgid "Module '%s' already registered" +msgid "Accepting message in: %r" msgstr "" + +#: ../wallace/modules.py:269 +#, python-format +msgid "recipients: %r" +msgstr "" + +#: ../wallace/modules.py:347 +#, python-format +msgid "Module '%s' already registered" +msgstr "Modul '%s' ist bereits registriert"
View file
pykolab-0.7.tar.gz/po/de_DE.po
Changed
@@ -1,678 +1,913 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: -# <grote@kolabsys.com>, 2012. +# Christoph Wickert <christoph.wickert@gmail.com>, 2012 +# Grote <grote@kolabsys.com>, 2012 +# Thomas Brüderli <roundcube@gmail.com>, 2014 msgid "" msgstr "" "Project-Id-Version: Kolab Groupware Solution\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-12 11:17+0000\n" -"PO-Revision-Date: 2012-08-14 11:13+0000\n" -"Last-Translator: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>\n" -"Language-Team: German (Germany) (http://www.transifex.com/projects/p/kolab/" -"language/de_DE/)\n" -"Language: de_DE\n" +"POT-Creation-Date: 2014-07-10 07:21-0400\n" +"PO-Revision-Date: 2014-07-22 13:04+0000\n" +"Last-Translator: Thomas Brüderli <roundcube@gmail.com>\n" +"Language-Team: German (Germany) (http://www.transifex.com/projects/p/kolab/language/de_DE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Language: de_DE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../bin/kolab_smtp_access_policy.py:206 +#: ../bin/kolab_smtp_access_policy.py:209 #, python-format msgid "Adding policy request to instance %s" msgstr "Füge Richtlinien-Anfrage zu Instanz %s hinzu" -#: ../bin/kolab_smtp_access_policy.py:446 +#: ../bin/kolab_smtp_access_policy.py:479 msgid "Unauthorized access not allowed" msgstr "Unberechtigter Zugriff nicht erlaubt" -#: ../bin/kolab_smtp_access_policy.py:475 -#: ../bin/kolab_smtp_access_policy.py:657 +#: ../bin/kolab_smtp_access_policy.py:508 +#: ../bin/kolab_smtp_access_policy.py:689 msgid "Could not find recipient" msgstr "Konnte den Empfänger nicht finden" -#: ../bin/kolab_smtp_access_policy.py:494 -#: ../bin/kolab_smtp_access_policy.py:594 +#: ../bin/kolab_smtp_access_policy.py:527 #, python-format -msgid "Could not find envelope sender user %s" -msgstr "Konnte den Absender-Umschlag für den Benutzer %s nicht finden" +msgid "Could not find envelope sender user %s (511)" +msgstr "" -#: ../bin/kolab_smtp_access_policy.py:537 +#: ../bin/kolab_smtp_access_policy.py:570 #, python-format msgid "Obtained authenticated user details for %r: %r" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:616 +#: ../bin/kolab_smtp_access_policy.py:627 +#, python-format +msgid "Could not find envelope sender user %s" +msgstr "Konnte den Absender-Umschlag für den Benutzer %s nicht finden" + +#: ../bin/kolab_smtp_access_policy.py:649 #, python-format msgid "%s is unauthorized to send on behalf of %s" msgstr "Benutzer %s ist nicht berechtigt als Benutzer %s zu senden" -#: ../bin/kolab_smtp_access_policy.py:626 +#: ../bin/kolab_smtp_access_policy.py:659 #, python-format -msgid "User %s attempted to use envelope sender address %s " +msgid "" +"User %s attempted to use envelope sender address %s without authorization" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:681 -#: ../bin/kolab_smtp_access_policy.py:692 +#: ../bin/kolab_smtp_access_policy.py:713 +#: ../bin/kolab_smtp_access_policy.py:724 #, python-format msgid "Found user %s to be a delegate user of %s" msgstr "Benutzer %s ist ein delegierter Benutzer von %s" -#: ../bin/kolab_smtp_access_policy.py:716 +#: ../bin/kolab_smtp_access_policy.py:748 #, python-format -msgid "Verifying authenticated sender '%(sender)s' with " +msgid "" +"Verifying authenticated sender '%(sender)s' with sasl_username " +"'%(sasl_username)s' for recipient '%(recipient)s'" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:721 +#: ../bin/kolab_smtp_access_policy.py:751 #, python-format -msgid "Verifying unauthenticated sender '%(sender)s' " +msgid "" +"Verifying unauthenticated sender '%(sender)s' for recipient '%(recipient)s'" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:738 +#: ../bin/kolab_smtp_access_policy.py:767 #, python-format -msgid "Reproducing verify_recipient(%s, %s) from " +msgid "Reproducing verify_recipient(%s, %s) from cache" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:760 +#: ../bin/kolab_smtp_access_policy.py:804 #, python-format msgid "Using authentication domain %s instead of %s" msgstr "Benutze Authentisierungsdomain %s anstelle von %s" -#: ../bin/kolab_smtp_access_policy.py:770 +#: ../bin/kolab_smtp_access_policy.py:814 #, python-format msgid "Domain %s is a primary domain" msgstr "Die Domain %s ist die primäre Domain" -#: ../bin/kolab_smtp_access_policy.py:778 +#: ../bin/kolab_smtp_access_policy.py:822 #, python-format -msgid "Checking the recipient for domain %s that is not " +msgid "" +"Checking the recipient for domain %s that is not ours. This is probably a " +"configuration error." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:794 -msgid "This recipient address is related to multiple " +#: ../bin/kolab_smtp_access_policy.py:837 +msgid "" +"This recipient address is related to multiple object entries and the SMTP " +"Access Policy can therefore not restrict message flow" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:803 +#: ../bin/kolab_smtp_access_policy.py:854 #, python-format -msgid "Recipient address %r not found. Allowing since " +msgid "" +"Recipient address %r not found. Allowing since the MTA was configured to " +"accept the recipient." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:831 +#: ../bin/kolab_smtp_access_policy.py:890 msgid "Invalid recipient" msgstr "Ungültiger Empfänger" -#: ../bin/kolab_smtp_access_policy.py:842 +#: ../bin/kolab_smtp_access_policy.py:901 msgid "Could not find this user, accepting" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:905 -#: ../bin/kolab_smtp_access_policy.py:958 +#: ../bin/kolab_smtp_access_policy.py:974 +#: ../bin/kolab_smtp_access_policy.py:1050 #, python-format -msgid "Sender %s is not allowed to send to " +msgid "Sender %s is not allowed to send to recipient %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:945 +#: ../bin/kolab_smtp_access_policy.py:1038 #, python-format -msgid "Reproducing verify_sender(%r) from cache, " +msgid "Reproducing verify_sender(%r) from cache" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:974 +#: ../bin/kolab_smtp_access_policy.py:1055 +msgid "Unverifiable sender." +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1060 +msgid "Sender is not using an alias" +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1068 msgid "Sender uses unauthorized envelope sender address" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:991 +#: ../bin/kolab_smtp_access_policy.py:1085 msgid "Could not verify sender" msgstr "Konnte den Absender nicht verifizieren" -#: ../bin/kolab_smtp_access_policy.py:998 -msgid "Verifying whether sender is allowed to send to " +#: ../bin/kolab_smtp_access_policy.py:1092 +msgid "" +"Verifying whether sender is allowed to send to recipient using sender policy" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1012 +#: ../bin/kolab_smtp_access_policy.py:1105 #, python-format msgid "Result is %r" msgstr "Das Ergebnis ist %r" -#: ../bin/kolab_smtp_access_policy.py:1017 +#: ../bin/kolab_smtp_access_policy.py:1110 msgid "No recipient policy restrictions exist for this sender" msgstr "Es existiert keine Empfängerrichtlinie für diesen Absender" -#: ../bin/kolab_smtp_access_policy.py:1026 +#: ../bin/kolab_smtp_access_policy.py:1119 msgid "Found a recipient policy to apply for this sender." msgstr "Empfänger-Richtlinie für diesen Benutzer gefunden" -#: ../bin/kolab_smtp_access_policy.py:1041 +#: ../bin/kolab_smtp_access_policy.py:1134 #, python-format -msgid "Sender %s not allowed to send to recipient " +msgid "Sender %s not allowed to send to recipient %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1063 +#: ../bin/kolab_smtp_access_policy.py:1155 msgid "Cleaning up the cache" msgstr "Aufräumen des Cache" -#: ../bin/kolab_smtp_access_policy.py:1085 +#: ../bin/kolab_smtp_access_policy.py:1177 msgid "" "The 'uri' setting in the kolab_smtp_access_policy section is soon going to " "be deprecated in favor of 'cache_uri'" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1101 +#: ../bin/kolab_smtp_access_policy.py:1193 #, python-format msgid "Operational Error in caching: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1152 +#: ../bin/kolab_smtp_access_policy.py:1245 #, python-format msgid "Caching the policy result with timestamp %d" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1229 +#: ../bin/kolab_smtp_access_policy.py:1319 #, python-format msgid "Returning action DEFER_IF_PERMIT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1234 +#: ../bin/kolab_smtp_access_policy.py:1324 #, python-format msgid "Returning action DUNNO: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1239 +#: ../bin/kolab_smtp_access_policy.py:1329 #, python-format msgid "Returning action HOLD: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1244 +#: ../bin/kolab_smtp_access_policy.py:1334 #, python-format msgid "Returning action PERMIT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1249 +#: ../bin/kolab_smtp_access_policy.py:1459 #, python-format msgid "Returning action REJECT: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1298 +#: ../bin/kolab_smtp_access_policy.py:1505 msgid "Starting to loop for new request" msgstr "Starte Schleife für neue Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1305 +#: ../bin/kolab_smtp_access_policy.py:1512 msgid "Timeout for policy request reading exceeded" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1311 +#: ../bin/kolab_smtp_access_policy.py:1518 msgid "End of current request" msgstr "Ende der aktuellen Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1315 +#: ../bin/kolab_smtp_access_policy.py:1522 #, python-format msgid "Getting line: %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1319 +#: ../bin/kolab_smtp_access_policy.py:1526 msgid "Returning request" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1348 +#: ../bin/kolab_smtp_access_policy.py:1555 msgid "Access Policy Options" msgstr "Zugriffsrichtlinien-Einstellungen" -#: ../bin/kolab_smtp_access_policy.py:1355 +#: ../bin/kolab_smtp_access_policy.py:1562 msgid "SMTP Policy request timeout." msgstr "Zeitüberschreitung der SMTP Richtlinien-Anfrage" -#: ../bin/kolab_smtp_access_policy.py:1361 +#: ../bin/kolab_smtp_access_policy.py:1568 msgid "Verify the recipient access policy." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1367 +#: ../bin/kolab_smtp_access_policy.py:1574 msgid "Verify the sender access policy." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1373 +#: ../bin/kolab_smtp_access_policy.py:1580 msgid "Allow unauthenticated senders." msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1385 +#: ../bin/kolab_smtp_access_policy.py:1594 #, python-format msgid "Got request instance %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1394 +#: ../bin/kolab_smtp_access_policy.py:1603 #, python-format msgid "Request instance %s is in state %s" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1402 +#: ../bin/kolab_smtp_access_policy.py:1611 #, python-format msgid "Request instance %s is not yet in DATA state" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1414 +#: ../bin/kolab_smtp_access_policy.py:1623 #, python-format msgid "Request instance %s reached DATA state" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1432 +#: ../bin/kolab_smtp_access_policy.py:1643 +#, python-format +msgid "Unhandled exception caught: %r" +msgstr "" + +#: ../bin/kolab_smtp_access_policy.py:1647 msgid "Sender access denied" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1434 +#: ../bin/kolab_smtp_access_policy.py:1649 msgid "Recipient access denied" msgstr "" -#: ../bin/kolab_smtp_access_policy.py:1436 +#: ../bin/kolab_smtp_access_policy.py:1651 msgid "No objections" msgstr "" -#: ../conf.py:37 ../kolab.py:34 ../saslauthd.py:33 +#: ../conf.py:37 ../kolab-cli.py:34 ../saslauthd.py:33 msgid "Cannot load pykolab/logger.py:" msgstr "" -#: ../kolabd/__init__.py:49 ../saslauthd/__init__.py:48 -#: ../wallace/__init__.py:66 +#: ../kolabd/__init__.py:49 ../saslauthd/__init__.py:51 +#: ../wallace/__init__.py:85 msgid "Daemon Options" msgstr "" -#: ../kolabd/__init__.py:56 ../saslauthd/__init__.py:55 -#: ../wallace/__init__.py:73 +#: ../kolabd/__init__.py:56 ../saslauthd/__init__.py:58 +#: ../wallace/__init__.py:92 msgid "Fork to the background." msgstr "" -#: ../kolabd/__init__.py:65 ../saslauthd/__init__.py:64 -#: ../wallace/__init__.py:99 +#: ../kolabd/__init__.py:65 ../saslauthd/__init__.py:67 +#: ../wallace/__init__.py:118 msgid "Path to the PID file to use." msgstr "" -#: ../kolabd/__init__.py:74 ../saslauthd/__init__.py:73 -#: ../wallace/__init__.py:116 +#: ../kolabd/__init__.py:74 ../saslauthd/__init__.py:76 +#: ../wallace/__init__.py:135 msgid "Run as user USERNAME" msgstr "" -#: ../kolabd/__init__.py:84 ../saslauthd/__init__.py:83 -#: ../wallace/__init__.py:90 +#: ../kolabd/__init__.py:84 ../saslauthd/__init__.py:86 +#: ../wallace/__init__.py:109 msgid "Run as group GROUPNAME" msgstr "" -#: ../kolabd/__init__.py:122 ../pykolab/utils.py:180 -#: ../wallace/__init__.py:297 +#: ../kolabd/__init__.py:122 ../pykolab/logger.py:139 ../pykolab/utils.py:234 +#: ../saslauthd/__init__.py:292 ../wallace/__init__.py:329 #, python-format msgid "Group %s does not exist" msgstr "" -#: ../kolabd/__init__.py:131 ../wallace/__init__.py:306 +#: ../kolabd/__init__.py:131 ../saslauthd/__init__.py:301 +#: ../wallace/__init__.py:338 #, python-format msgid "Switching real and effective group id to %d" msgstr "" -#: ../kolabd/__init__.py:153 ../pykolab/utils.py:204 -#: ../wallace/__init__.py:328 +#: ../kolabd/__init__.py:153 ../pykolab/logger.py:159 ../pykolab/utils.py:258 +#: ../saslauthd/__init__.py:323 ../wallace/__init__.py:360 #, python-format msgid "User %s does not exist" msgstr "" -#: ../kolabd/__init__.py:163 ../wallace/__init__.py:338 +#: ../kolabd/__init__.py:163 ../saslauthd/__init__.py:333 +#: ../wallace/__init__.py:370 #, python-format msgid "Switching real and effective user id to %d" msgstr "" -#: ../kolabd/__init__.py:172 ../wallace/__init__.py:347 +#: ../kolabd/__init__.py:172 ../saslauthd/__init__.py:342 +#: ../wallace/__init__.py:379 msgid "Could not change real and effective uid and/or gid" msgstr "" -#: ../kolabd/__init__.py:192 ../saslauthd/__init__.py:122 -#: ../wallace/__init__.py:367 +#: ../kolabd/__init__.py:192 ../saslauthd/__init__.py:133 +#: ../wallace/__init__.py:399 msgid "Interrupted by user" msgstr "" #: ../kolabd/__init__.py:197 ../kolabd/__init__.py:208 -#: ../wallace/__init__.py:371 ../wallace/__init__.py:381 msgid "Traceback occurred, please report a " msgstr "" -#: ../kolabd/__init__.py:203 ../saslauthd/__init__.py:130 -#: ../wallace/__init__.py:377 +#: ../kolabd/__init__.py:203 ../saslauthd/__init__.py:141 +#: ../wallace/__init__.py:408 #, python-format msgid "Type Error: %s" msgstr "" -#: ../kolabd/__init__.py:223 ../pykolab/auth/ldap/__init__.py:1623 +#: ../kolabd/__init__.py:230 +msgid "Could not connect to LDAP, is it running?" +msgstr "" + +#: ../kolabd/__init__.py:233 ../pykolab/auth/ldap/__init__.py:2137 #: ../pykolab/cli/cmd_sync.py:36 msgid "Listing domains..." +msgstr "Domänen werden geladen…" + +#: ../kolabd/__init__.py:244 +msgid "No domains. Not syncing" msgstr "" -#: ../kolabd/__init__.py:260 +#: ../kolabd/__init__.py:275 #, python-format msgid "added domains: %r, removed domains: %r" msgstr "" -#: ../kolabd/process.py:48 +#: ../kolabd/process.py:33 #, python-format -msgid "Error in process %r, terminating: %r" +msgid "Process created for domain %s" +msgstr "" + +#: ../kolabd/process.py:42 +#, python-format +msgid "Synchronizing for domain %s" +msgstr "" + +#: ../kolabd/process.py:59 +#, python-format +msgid "" +"Error in process %r, terminating:\n" +"\t%r" msgstr "" #: ../kolabd.py:31 ../setup-kolab.py:36 ../wallace.py:31 msgid "Cannot load pykolab/constants.py:" msgstr "" -#: ../pykolab/auth/__init__.py:94 +#: ../pykolab/auth/__init__.py:89 #, python-format msgid "Called for domain %r" msgstr "" -#: ../pykolab/auth/__init__.py:107 ../pykolab/auth/__init__.py:116 +#: ../pykolab/auth/__init__.py:106 ../pykolab/auth/__init__.py:115 #, python-format msgid "Using section %s and domain %s" msgstr "" -#: ../pykolab/auth/__init__.py:121 +#: ../pykolab/auth/__init__.py:120 #, python-format msgid "Connecting to Authentication backend for domain %s" msgstr "" -#: ../pykolab/auth/__init__.py:132 +#: ../pykolab/auth/__init__.py:131 #, python-format msgid "Section %s has no option 'auth_mechanism'" msgstr "" -#: ../pykolab/auth/__init__.py:139 +#: ../pykolab/auth/__init__.py:138 #, python-format msgid "Section %s has auth_mechanism: %r" msgstr "" -#: ../pykolab/auth/__init__.py:148 ../pykolab/auth/__init__.py:157 +#: ../pykolab/auth/__init__.py:147 ../pykolab/auth/__init__.py:156 msgid "Starting LDAP..." msgstr "" -#: ../pykolab/auth/ldap/cache.py:112 +#: ../pykolab/auth/ldap/cache.py:126 #, python-format msgid "Inserting cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/cache.py:129 +#: ../pykolab/auth/ldap/cache.py:147 #, python-format msgid "Updating timestamp for cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/cache.py:136 +#: ../pykolab/auth/ldap/cache.py:155 #, python-format msgid "Updating result_attribute for cache entry %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:51 +#: ../pykolab/auth/ldap/__init__.py:52 msgid "Python LDAP library does not support persistent search" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:142 +#: ../pykolab/auth/ldap/__init__.py:143 #, python-format msgid "Attempting to authenticate user %s in realm %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:184 +#: ../pykolab/auth/ldap/__init__.py:175 ../pykolab/auth/ldap/__init__.py:226 +#, python-format +msgid "Authentication cache failed: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:216 ../pykolab/auth/ldap/__init__.py:240 #, python-format msgid "Binding with user_dn %s and password %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:194 +#: ../pykolab/auth/ldap/__init__.py:231 ../pykolab/auth/ldap/__init__.py:263 #, python-format msgid "Failed to authenticate as user %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:211 -msgid "Connecting to LDAP..." +#: ../pykolab/auth/ldap/__init__.py:249 +#, python-format +msgid "Error occured, there is no such object: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:254 +msgid "Authentication cache failed to clear entry" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:260 +#, python-format +msgid "Exception occured: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:215 +#: ../pykolab/auth/ldap/__init__.py:280 +msgid "Connecting to LDAP..." +msgstr "Zum LDAP verbinden…" + +#: ../pykolab/auth/ldap/__init__.py:284 #, python-format msgid "Attempting to use LDAP URI %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:363 +#: ../pykolab/auth/ldap/__init__.py:371 +#, python-format +msgid "Entry ID: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:373 +#, python-format +msgid "Entry DN: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:376 +#, python-format +msgid "" +"ldap search: (%r, %r, filterstr='(objectclass=*)', attrlist=[ 'dn' ] + %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:453 #, python-format msgid "Finding recipient with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:431 +#: ../pykolab/auth/ldap/__init__.py:529 #, python-format msgid "Finding resource with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:454 +#: ../pykolab/auth/ldap/__init__.py:560 #, python-format msgid "Using timestamp %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:486 +#: ../pykolab/auth/ldap/__init__.py:595 +msgid "Applying recipient policy disabled through configuration" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:600 #, python-format msgid "Applying recipient policy to %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:503 +#: ../pykolab/auth/ldap/__init__.py:617 #, python-format msgid "Using mail attributes: %r, with primary %r and " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:514 +#: ../pykolab/auth/ldap/__init__.py:628 #, python-format msgid "key %r not in entry" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:516 +#: ../pykolab/auth/ldap/__init__.py:630 #, python-format msgid "key %r is the prim. mail attr." msgstr "" -#: ../pykolab/auth/ldap/__init__.py:518 +#: ../pykolab/auth/ldap/__init__.py:632 msgid "prim. mail pol. is not empty" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:521 +#: ../pykolab/auth/ldap/__init__.py:635 #, python-format msgid "key %r is the sec. mail attr." msgstr "" -#: ../pykolab/auth/ldap/__init__.py:523 +#: ../pykolab/auth/ldap/__init__.py:637 msgid "sec. mail pol. is not empty" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:527 ../pykolab/auth/ldap/__init__.py:541 +#: ../pykolab/auth/ldap/__init__.py:641 ../pykolab/auth/ldap/__init__.py:655 #, python-format msgid "Attributes %r are not yet available for entry %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:577 +#: ../pykolab/auth/ldap/__init__.py:694 #, python-format msgid "No results for mail address %s found" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:588 +#: ../pykolab/auth/ldap/__init__.py:705 #, python-format msgid "1 result for address %s found, verifying" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:598 +#: ../pykolab/auth/ldap/__init__.py:715 #, python-format msgid "Too bad, primary email address %s " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:609 ../pykolab/auth/ldap/__init__.py:698 +#: ../pykolab/auth/ldap/__init__.py:726 ../pykolab/auth/ldap/__init__.py:815 msgid "Address assigned to us" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:664 +#: ../pykolab/auth/ldap/__init__.py:781 #, python-format msgid "No results for address %s found" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:675 +#: ../pykolab/auth/ldap/__init__.py:792 #, python-format msgid "1 result for address %s found, " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:686 +#: ../pykolab/auth/ldap/__init__.py:803 msgid "Too bad, secondary email " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:713 +#: ../pykolab/auth/ldap/__init__.py:830 msgid "Recipient policy composed the following set of secondary " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:724 +#: ../pykolab/auth/ldap/__init__.py:841 #, python-format msgid "Secondary mail addresses that we want is not None: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:735 +#: ../pykolab/auth/ldap/__init__.py:852 msgid "Avoiding the duplication of the primary mail " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:746 +#: ../pykolab/auth/ldap/__init__.py:863 #, python-format msgid "Entry is getting secondary mail addresses: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:754 +#: ../pykolab/auth/ldap/__init__.py:871 msgid "Entry did not have any secondary mail " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:780 +#: ../pykolab/auth/ldap/__init__.py:888 ../pykolab/auth/ldap/__init__.py:894 +#, python-format +msgid "secondary_mail_addresses: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:889 ../pykolab/auth/ldap/__init__.py:895 +#, python-format +msgid "entry[%s]: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:906 #, python-format msgid "Entry modifications list: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:800 +#: ../pykolab/auth/ldap/__init__.py:934 #, python-format msgid "Setting entry attribute %r to %r for %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:836 +#: ../pykolab/auth/ldap/__init__.py:970 #, python-format -msgid "Could not update dn %r" +msgid "" +"Could not update dn %r:\n" +"%r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:849 +#: ../pykolab/auth/ldap/__init__.py:983 #, python-format msgid "Using filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:887 +#: ../pykolab/auth/ldap/__init__.py:998 +#, python-format +msgid "Synchronization is searching against base DN: %s" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1044 #, python-format msgid "About to consider the user quota for %r (used: %r, " msgstr "" -#: ../pykolab/auth/ldap/__init__.py:953 -#, fuzzy -msgid "Invalid bind credentials" -msgstr "Ungültiger Empfänger" +#: ../pykolab/auth/ldap/__init__.py:1115 +msgid "Invalid DN, username and/or password." +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1236 ../pykolab/auth/ldap/__init__.py:1249 +#: ../pykolab/auth/ldap/__init__.py:1614 ../pykolab/auth/ldap/__init__.py:1627 +#, python-format +msgid "Found a subject %r with access %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1356 +#, python-format +msgid "Entry %s attribute value: %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:1364 +#, python-format +msgid "imap.user_mailbox_server(%r) result: %r" +msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1248 ../pykolab/auth/ldap/__init__.py:1372 +#: ../pykolab/auth/ldap/__init__.py:1684 ../pykolab/auth/ldap/__init__.py:1853 #, python-format msgid "Result from recipient policy: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1417 +#: ../pykolab/auth/ldap/__init__.py:1908 #, python-format msgid "Kolab user %s does not have a result attribute %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1559 +#: ../pykolab/auth/ldap/__init__.py:2067 #, python-format msgid "Finding domain root dn for domain %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1647 +#: ../pykolab/auth/ldap/__init__.py:2164 msgid "Authentication database DOWN" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1731 ../pykolab/auth/ldap/__init__.py:1766 +#: ../pykolab/auth/ldap/__init__.py:2248 ../pykolab/auth/ldap/__init__.py:2296 #, python-format msgid "Entry type: %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1854 +#: ../pykolab/auth/ldap/__init__.py:2321 +#, python-format +msgid "Done with _synchronize_callback() for entry %r" +msgstr "" + +#: ../pykolab/auth/ldap/__init__.py:2393 msgid "LDAP Search Result Data Entry:" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1870 +#: ../pykolab/auth/ldap/__init__.py:2409 msgid "Entry Change Notification attributes:" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1875 +#: ../pykolab/auth/ldap/__init__.py:2414 #, python-format msgid "Change Type: %r (%r)" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1883 +#: ../pykolab/auth/ldap/__init__.py:2422 #, python-format msgid "Previous DN: %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:1938 +#: ../pykolab/auth/ldap/__init__.py:2477 #, python-format msgid "Object %s searched no longer exists" -msgstr "" +msgstr "Das gesuchte Objekt %s existiert nicht mehr" -#: ../pykolab/auth/ldap/__init__.py:1948 +#: ../pykolab/auth/ldap/__init__.py:2487 #, python-format msgid "%d results..." -msgstr "" +msgstr "%d Ergebnisse…" -#: ../pykolab/auth/ldap/__init__.py:2051 +#: ../pykolab/auth/ldap/__init__.py:2590 #, python-format msgid "Searching with filter %r" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:2095 +#: ../pykolab/auth/ldap/__init__.py:2642 #, python-format msgid "Checking for support for %s on %s" msgstr "" -#: ../pykolab/auth/ldap/__init__.py:2114 +#: ../pykolab/auth/ldap/__init__.py:2661 #, python-format msgid "Found support for %s" msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:36 ../pykolab/cli/cmd_create_mailbox.py:36 +#: ../pykolab/auth/ldap/__init__.py:2706 +#, python-format +msgid "An error occured using %s: %r" +msgstr "" + +#: ../pykolab/auth/ldap/syncrepl.py:46 +msgid "The name of the persistent, unique attribute " +msgstr "" + +#: ../pykolab/cli/cmd_acl_cleanup.py:34 +msgid "Clean up ACLs that use identifiers that no longer exist" +msgstr "" + +#: ../pykolab/cli/cmd_acl_cleanup.py:56 +#, python-format +msgid "Deleting ACL %s for subject %s on folder %s" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:42 +msgid "Specify the (new) alias address" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:45 +msgid "Specify the existing recipient address" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:66 ../pykolab/cli/cmd_add_alias.py:70 +#, python-format +msgid "Domain %r is not a local domain" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:75 +msgid "Primary and secondary domain do not have the same parent domain" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:81 +#, python-format +msgid "No such recipient %r" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:87 +#, python-format +msgid "Recipient for alias %r already exists" +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:97 +msgid "Environment is not configured for " +msgstr "" + +#: ../pykolab/cli/cmd_add_alias.py:105 +#, python-format +msgid "Recipient %r is not the primary recipient for address %r" +msgstr "" + +#: ../pykolab/cli/cmd_add_domain.py:36 +#: ../pykolab/cli/cmd_count_domain_mailboxes.py:38 +#: ../pykolab/cli/cmd_create_mailbox.py:36 #: ../pykolab/cli/cmd_export_mailbox.py:33 -#: ../pykolab/cli/cmd_list_mailboxes.py:39 +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:38 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:36 +#: ../pykolab/cli/cmd_list_mailboxes.py:40 #: ../pykolab/cli/cmd_list_mailbox_metadata.py:37 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:37 +#: ../pykolab/cli/cmd_list_messages.py:37 ../pykolab/cli/cmd_list_quota.py:36 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:36 +#: ../pykolab/cli/cmd_server_info.py:34 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:38 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:39 +#: ../pykolab/cli/cmd_undelete_mailbox.py:34 msgid "CLI Options" -msgstr "" +msgstr "Kommandozeilenoptionen" #: ../pykolab/cli/cmd_add_domain.py:42 -msgid "Add domain as alias for DOMAIN" +msgid "Add alias domain." msgstr "" #: ../pykolab/cli/cmd_add_domain.py:47 -msgid "Add a new domain or domain alias." +msgid "Add a new domain." msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:55 +#: ../pykolab/cli/cmd_add_domain.py:55 ../pykolab/cli/cmd_delete_domain.py:44 +#: ../pykolab/cli/cmd_find_domain.py:44 msgid "Could not find credentials with sufficient permissions" msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:80 ../pykolab/wap_client/__init__.py:113 -msgid "Invalid parent domain" +#: ../pykolab/cli/cmd_add_domain.py:67 ../pykolab/cli/cmd_delete_domain.py:56 +#: ../pykolab/cli/cmd_find_domain.py:56 +msgid "Domain name" msgstr "" -#: ../pykolab/cli/cmd_add_domain.py:86 -msgid "Domain name" +#: ../pykolab/cli/cmd_add_user_subscription.py:37 +msgid "Subscribe a user to a folder." +msgstr "" + +#: ../pykolab/cli/cmd_add_user_subscription.py:47 +#: ../pykolab/cli/cmd_add_user_subscription.py:51 +#: ../pykolab/cli/cmd_remove_user_subscription.py:47 +#: ../pykolab/cli/cmd_remove_user_subscription.py:51 +msgid "Folder pattern" +msgstr "" + +#: ../pykolab/cli/cmd_add_user_subscription.py:50 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:63 +#: ../pykolab/cli/cmd_remove_user_subscription.py:50 +msgid "User ID" +msgstr "" + +#: ../pykolab/cli/cmd_add_user_subscription.py:72 +#: ../pykolab/cli/cmd_remove_user_subscription.py:72 +#, python-format +msgid "Cannot subscribe user to folder %r:" +msgstr "" + +#: ../pykolab/cli/cmd_add_user_subscription.py:73 +#: ../pykolab/cli/cmd_delete_message.py:61 +#: ../pykolab/cli/cmd_list_messages.py:67 +#: ../pykolab/cli/cmd_remove_user_subscription.py:73 +msgid "No such folder" +msgstr "" + +#: ../pykolab/cli/cmd_count_domain_mailboxes.py:44 +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:50 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:48 +#: ../pykolab/cli/cmd_list_mailboxes.py:52 ../pykolab/cli/cmd_list_quota.py:42 +#: ../pykolab/cli/cmd_server_info.py:40 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:57 +msgid "List mailboxes on server SERVER only." msgstr "" #: ../pykolab/cli/cmd_create_mailbox.py:42 msgid "Set metadata for folder to ANNOTATION=VALUE" msgstr "" -#: ../pykolab/cli/cmd_create_mailbox.py:52 -msgid "Invalid argument" +#: ../pykolab/cli/cmd_create_mailbox.py:50 +msgid "Create folder on PARTITION." msgstr "" #: ../pykolab/cli/cmd_create_mailbox.py:60 +msgid "Invalid argument" +msgstr "" + +#: ../pykolab/cli/cmd_create_mailbox.py:68 msgid "Invalid argument for metadata" msgstr "" +#: ../pykolab/cli/cmd_delete_domain.py:36 +msgid "Delete a domain." +msgstr "" + #: ../pykolab/cli/cmd_delete_mailbox_acl.py:45 #: ../pykolab/cli/cmd_delete_mailbox_acl.py:49 #: ../pykolab/cli/cmd_set_mailbox_acl.py:50 @@ -684,7 +919,11 @@ #: ../pykolab/cli/cmd_list_mailbox_acls.py:43 #: ../pykolab/cli/cmd_list_mailbox_metadata.py:54 #: ../pykolab/cli/cmd_set_mailbox_acl.py:54 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:65 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:66 +#: ../pykolab/cli/cmd_set_quota.py:46 ../tests/unit/test-015-translate.py:12 +#: ../tests/unit/test-015-translate.py:16 +#: ../tests/unit/test-015-translate.py:18 +#: ../tests/unit/test-015-translate.py:20 msgid "Folder name" msgstr "" @@ -692,7 +931,8 @@ #: ../pykolab/cli/cmd_list_mailbox_acls.py:54 #: ../pykolab/cli/cmd_list_mailbox_metadata.py:80 #: ../pykolab/cli/cmd_set_mailbox_acl.py:67 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:93 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:94 +#: ../pykolab/cli/cmd_set_quota.py:58 #, python-format msgid "No such folder %r" msgstr "" @@ -701,6 +941,23 @@ msgid "No mailbox specified" msgstr "" +#: ../pykolab/cli/cmd_delete_mailbox.py:56 +msgid "No such folder(s)" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:36 +msgid "Delete a message from a folder" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:49 +msgid "Specify a UID" +msgstr "" + +#: ../pykolab/cli/cmd_delete_message.py:52 +#: ../pykolab/cli/cmd_list_messages.py:58 +msgid "Specify a folder" +msgstr "" + #: ../pykolab/cli/cmd_export_mailbox.py:38 msgid "All folders this user has access to" msgstr "" @@ -720,11 +977,22 @@ msgid "No directories found for user %s" msgstr "" -#: ../pykolab/cli/cmd_list_mailboxes.py:44 +#: ../pykolab/cli/cmd_find_domain.py:36 +msgid "Find a domain." +msgstr "" + +#: ../pykolab/cli/cmd_list_deleted_mailboxes.py:43 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:41 +#: ../pykolab/cli/cmd_list_mailboxes.py:45 +#: ../pykolab/cli/cmd_list_user_subscriptions.py:41 msgid "Display raw IMAP UTF-7 folder names" msgstr "" -#: ../pykolab/cli/cmd_list_mailboxes.py:75 +#: ../pykolab/cli/cmd_list_domain_mailboxes.py:58 +msgid "Domain" +msgstr "Domäne" + +#: ../pykolab/cli/cmd_list_mailboxes.py:87 #, python-format msgid "Appending folder search for %r" msgstr "" @@ -733,11 +1001,41 @@ msgid "List annotations as user USER" msgstr "" -#: ../pykolab/cli/cmd_list_quota.py:59 ../pykolab/cli/cmd_list_quota.py:71 +#: ../pykolab/cli/cmd_list_messages.py:43 +msgid "Include messages flagged as \\Deleted" +msgstr "" + +#: ../pykolab/cli/cmd_list_messages.py:47 +msgid "List messages in a folder" +msgstr "" + +#: ../pykolab/cli/cmd_list_quota.py:73 ../pykolab/cli/cmd_list_quota.py:89 #, python-format msgid "The quota for folder %s is set to literally allow 0KB of storage." msgstr "" +#: ../pykolab/cli/cmd_list_user_subscriptions.py:47 +msgid "List unsubscribed folders" +msgstr "" + +#: ../pykolab/cli/cmd_list_user_subscriptions.py:50 +msgid "List the folders a user is subscribed to." +msgstr "" + +#: ../pykolab/cli/cmd_list_user_subscriptions.py:98 +#, python-format +msgid "No unsubscribed folders for user %s" +msgstr "" + +#: ../pykolab/cli/cmd_mailbox_cleanup.py:37 +msgid "Clean up mailboxes that do no longer have an owner." +msgstr "" + +#: ../pykolab/cli/cmd_mailbox_cleanup.py:61 +#, python-format +msgid "Deleting folder 'user/%s'" +msgstr "" + #: ../pykolab/cli/cmd_remove_mailaddress.py:49 msgid "Invalid or unqualified email address." msgstr "" @@ -761,20 +1059,34 @@ msgid "Found the following recipients:" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:48 +#: ../pykolab/cli/cmd_remove_user_subscription.py:37 +msgid "Unsubscribe a user from a folder." +msgstr "" + +#: ../pykolab/cli/cmd_remove_user_subscription.py:86 +#, python-format +msgid "Successfully unsubscribed user %s from the following folders:" +msgstr "" + +#: ../pykolab/cli/cmd_remove_user_subscription.py:92 +#, python-format +msgid "User %s was not unsubscribed from any folders." +msgstr "" + +#: ../pykolab/cli/cmd_rename_mailbox.py:52 msgid "No target mailbox name specified" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:50 +#: ../pykolab/cli/cmd_rename_mailbox.py:54 msgid "No source mailbox name specified" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:62 +#: ../pykolab/cli/cmd_rename_mailbox.py:66 #, python-format msgid "Source folder %r does not exist" msgstr "" -#: ../pykolab/cli/cmd_rename_mailbox.py:66 +#: ../pykolab/cli/cmd_rename_mailbox.py:70 #, python-format msgid "Target folder %r already exists" msgstr "" @@ -785,21 +1097,75 @@ msgid "ACI Permissions" msgstr "" -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:44 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:45 msgid "Set annotation as user USER" msgstr "" -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:58 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:62 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:67 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:59 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:63 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:68 msgid "Metadata value" msgstr "" -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:61 -#: ../pykolab/cli/cmd_set_mailbox_metadata.py:66 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:62 +#: ../pykolab/cli/cmd_set_mailbox_metadata.py:67 msgid "Metadata path" msgstr "" +#: ../pykolab/cli/cmd_set_quota.py:43 ../pykolab/cli/cmd_set_quota.py:47 +msgid "New quota" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:44 +msgid "Delete mailboxes for recipients that do not appear to exist in LDAP." +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:50 +msgid "Display changes, do not apply them." +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:88 +#, python-format +msgid "Domains in IMAP not in LDAP: %r" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:101 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:142 +#, python-format +msgid "" +"No recipients for '%s' (would have deleted the mailbox if not for --dry-" +"run)!" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:106 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:147 +#, python-format +msgid "Deleting mailbox '%s' because it has no recipients" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:110 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:151 +#, python-format +msgid "An error occurred removing mailbox %r: %r" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:112 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:153 +#, python-format +msgid "Not automatically deleting shared folder '%s'" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:114 +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:155 +#, python-format +msgid "No recipients for '%s' (use --delete to delete)!" +msgstr "" + +#: ../pykolab/cli/cmd_sync_mailhost_attrs.py:136 +#, python-format +msgid "Multiple recipients for '%s'!" +msgstr "" + #: ../pykolab/cli/cmd_sync.py:41 #, python-format msgid "Found %d domains in %d seconds" @@ -810,37 +1176,126 @@ msgid "Running for domain %s" msgstr "" -#: ../pykolab/cli/cmd_sync.py:57 +#: ../pykolab/cli/cmd_sync.py:58 #, python-format msgid "Synchronizing users for %s took %d seconds" msgstr "" +#: ../pykolab/cli/cmd_undelete_mailbox.py:39 +msgid "Do not actually execute, but state what would have been executed." +msgstr "" + +#: ../pykolab/cli/cmd_undelete_mailbox.py:42 +msgid "Recover mailboxes previously deleted." +msgstr "" + +#: ../pykolab/cli/cmd_user_info.py:39 +msgid "Email address" +msgstr "" + #. This is a nested command #. This is a nested component -#: ../pykolab/cli/commands.py:101 ../pykolab/setup/components.py:90 +#: ../pykolab/cli/commands.py:98 ../pykolab/setup/components.py:90 #, python-format msgid "Command Group: %s" msgstr "" -#: ../pykolab/cli/commands.py:116 ../pykolab/cli/commands.py:121 +#: ../pykolab/cli/commands.py:113 ../pykolab/cli/commands.py:118 msgid "No such command." msgstr "" -#: ../pykolab/cli/commands.py:171 ../pykolab/setup/components.py:231 +#: ../pykolab/cli/commands.py:168 ../pykolab/setup/components.py:231 #, python-format msgid "Command '%s' already registered" msgstr "" -#: ../pykolab/cli/commands.py:196 ../pykolab/setup/components.py:257 -#: ../wallace/modules.py:348 +#: ../pykolab/cli/commands.py:193 ../pykolab/setup/components.py:257 +#: ../wallace/modules.py:369 #, python-format msgid "Alias for %s" msgstr "" -#: ../pykolab/cli/commands.py:204 ../pykolab/setup/components.py:265 +#: ../pykolab/cli/commands.py:201 ../pykolab/setup/components.py:265 msgid "Not yet implemented" msgstr "" +#: ../pykolab/cli/sieve/cmd_list.py:43 ../pykolab/cli/sieve/cmd_put.py:42 +#: ../pykolab/cli/sieve/cmd_refresh.py:44 ../pykolab/cli/sieve/cmd_test.py:43 +msgid "Email Address" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:99 +#: ../pykolab/plugins/sievemgmt/__init__.py:111 +#, python-format +msgid "Found the following scripts for user %s: %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:100 +#: ../pykolab/plugins/sievemgmt/__init__.py:112 +#, python-format +msgid "And the following script is active for user %s: %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:178 +#: ../pykolab/plugins/sievemgmt/__init__.py:190 +#, python-format +msgid "" +"Delivery to folder active, but no folder name attribute available for user " +"%r" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:181 +#: ../pykolab/plugins/sievemgmt/__init__.py:193 +msgid "Delivery to folder active, but no folder name attribute configured" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:359 +#, python-format +msgid "MANAGEMENT script for user %s contents: %r" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:364 +#: ../pykolab/plugins/sievemgmt/__init__.py:374 +#, python-format +msgid "Uploading script MANAGEMENT failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:366 +#: ../pykolab/plugins/sievemgmt/__init__.py:376 +#, python-format +msgid "Uploading script MANAGEMENT for user %s succeeded" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:377 +#: ../pykolab/plugins/sievemgmt/__init__.py:387 +#, python-format +msgid "Including script %s in USER (for user %s)" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:386 +#: ../pykolab/plugins/sievemgmt/__init__.py:396 +#, python-format +msgid "Uploading script USER failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:388 +#: ../pykolab/plugins/sievemgmt/__init__.py:398 +#, python-format +msgid "Uploading script USER for user %s succeeded" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:416 +#: ../pykolab/plugins/sievemgmt/__init__.py:426 +#, python-format +msgid "Uploading script MASTER failed for user %s" +msgstr "" + +#: ../pykolab/cli/sieve/cmd_refresh.py:418 +#: ../pykolab/plugins/sievemgmt/__init__.py:428 +#, python-format +msgid "Uploading script MASTER for user %s succeeded" +msgstr "" + #: ../pykolab/cli/telemetry/cmd_examine_command_issue.py:40 msgid "Unspecified command issue identifier" msgstr "" @@ -986,357 +1441,429 @@ msgid "No command supplied" msgstr "" -#: ../pykolab/conf/__init__.py:411 +#: ../pykolab/conf/__init__.py:416 msgid "Insufficient options. Need section, key and value -in that order." msgstr "" -#: ../pykolab/conf/__init__.py:414 +#: ../pykolab/conf/__init__.py:419 #, python-format msgid "No section '%s' exists." msgstr "" -#: ../pykolab/conf/__init__.py:445 +#: ../pykolab/conf/__init__.py:461 #, python-format msgid "Setting %s to %r (from the default values for CLI options)" msgstr "" -#: ../pykolab/conf/__init__.py:514 +#: ../pykolab/conf/__init__.py:534 #, python-format msgid "Could not execute configuration function: %s" msgstr "" -#: ../pykolab/conf/__init__.py:522 +#: ../pykolab/conf/__init__.py:542 #, python-format msgid "Option %s/%s does not exist in config file %s, pulling from defaults" msgstr "" -#: ../pykolab/conf/__init__.py:530 ../pykolab/conf/__init__.py:533 +#: ../pykolab/conf/__init__.py:550 ../pykolab/conf/__init__.py:553 msgid "Option does not exist in defaults." msgstr "" -#: ../pykolab/conf/__init__.py:543 +#: ../pykolab/conf/__init__.py:563 #, python-format msgid "Configuration file %s not readable." msgstr "" -#: ../pykolab/conf/__init__.py:546 +#: ../pykolab/conf/__init__.py:566 #, python-format msgid "Configuration file %s does not exist." msgstr "" -#: ../pykolab/conf/__init__.py:551 +#: ../pykolab/conf/__init__.py:571 msgid "" -"WARNING: A negative debug level value does not make this program be any more " -"silent." +"WARNING: A negative debug level value does not make this program be any more" +" silent." msgstr "" -#: ../pykolab/conf/__init__.py:557 +#: ../pykolab/conf/__init__.py:577 msgid "This program has 9 levels of verbosity. Using the maximum of 9." msgstr "" -#: ../pykolab/conf/__init__.py:565 ../pykolab/conf/__init__.py:571 +#: ../pykolab/conf/__init__.py:585 ../pykolab/conf/__init__.py:591 msgid "Cannot start SASL authentication daemon" msgstr "" -#: ../pykolab/conf/__init__.py:582 +#: ../pykolab/conf/__init__.py:602 msgid "No imaplib library found." msgstr "" -#: ../pykolab/conf/__init__.py:592 +#: ../pykolab/conf/__init__.py:612 msgid "No LMTP class found in the smtplib library." msgstr "" -#: ../pykolab/conf/__init__.py:602 +#: ../pykolab/conf/__init__.py:622 msgid "No SMTP class found in the smtplib library." msgstr "" -#: ../pykolab/conf/__init__.py:616 +#: ../pykolab/conf/__init__.py:636 #, python-format msgid "Found you specified a specific set of items to test: %s" msgstr "" -#: ../pykolab/conf/__init__.py:624 +#: ../pykolab/conf/__init__.py:644 #, python-format msgid "Selectively selecting: %s" msgstr "" #: ../pykolab/constants.py.in:40 -msgid "PyKolab is a Kolab Systems product. For more information " +msgid "" +"PyKolab is a Kolab Systems product. For more information about Kolab or " +"PyKolab, visit http://www.kolabsys.com" msgstr "" -#: ../pykolab/constants.py.in:54 +#: ../pykolab/constants.py.in:53 msgid "WARNING" msgstr "" -#: ../pykolab/constants.py.in:54 -msgid "The Fully Qualified " +#: ../pykolab/constants.py.in:53 +msgid "" +"The Fully Qualified Domain Name or FQDN for this system is incorrect. " +"Falling back to 'localdomain'." msgstr "" -#: ../pykolab/constants.py.in:75 +#: ../pykolab/constants.py.in:72 msgid "389 Directory Server or Red Hat Directory Server" msgstr "" -#: ../pykolab/constants.py.in:79 ../pykolab/constants.py.in:83 +#: ../pykolab/constants.py.in:76 ../pykolab/constants.py.in:80 msgid "OpenLDAP or compatible" msgstr "" -#: ../pykolab/imap/cyrus.py:79 +#: ../pykolab/imap/cyrus.py:80 #, python-format msgid "Could not connect to Cyrus IMAP server %r" msgstr "" -#: ../pykolab/imap/cyrus.py:136 +#: ../pykolab/imap/cyrus.py:137 #, python-format msgid "Continuing with separator: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:141 +#: ../pykolab/imap/cyrus.py:142 msgid "Detected we are running in a Murder topology" msgstr "" -#: ../pykolab/imap/cyrus.py:145 +#: ../pykolab/imap/cyrus.py:146 msgid "This system is not part of a murder topology" msgstr "" -#: ../pykolab/imap/cyrus.py:166 +#: ../pykolab/imap/cyrus.py:167 #, python-format msgid "Checking actual backend server for folder %s through annotations" msgstr "" -#: ../pykolab/imap/cyrus.py:181 +#: ../pykolab/imap/cyrus.py:172 +msgid "Possibly reproducing the find " +msgstr "" + +#: ../pykolab/imap/cyrus.py:195 #, python-format msgid "Could not get the annotations after %s tries." msgstr "" -#: ../pykolab/imap/cyrus.py:185 +#: ../pykolab/imap/cyrus.py:199 #, python-format msgid "No annotations for %s: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:192 +#: ../pykolab/imap/cyrus.py:206 #, python-format msgid "Server for INBOX folder %s is %s" msgstr "" -#: ../pykolab/imap/cyrus.py:204 +#: ../pykolab/imap/cyrus.py:226 #, python-format msgid "Setting quota for folder %s to %s" msgstr "" -#: ../pykolab/imap/cyrus.py:208 +#: ../pykolab/imap/cyrus.py:230 #, python-format msgid "Could not set quota for mailfolder %s" msgstr "" -#: ../pykolab/imap/cyrus.py:217 +#: ../pykolab/imap/cyrus.py:239 #, python-format msgid "Moving INBOX folder %s to %s" msgstr "" -#: ../pykolab/imap/cyrus.py:232 +#: ../pykolab/imap/cyrus.py:254 #, python-format msgid "Setting annotation %s on folder %s" msgstr "" -#: ../pykolab/imap/cyrus.py:237 +#: ../pykolab/imap/cyrus.py:259 #, python-format msgid "Could not set annotation %r on mail folder %r: %r" msgstr "" -#: ../pykolab/imap/cyrus.py:241 +#: ../pykolab/imap/cyrus.py:263 #, python-format msgid "Transferring folder %s from %s to %s" msgstr "" -#: ../pykolab/imap/cyrus.py:301 +#: ../pykolab/imap/cyrus.py:323 #, python-format msgid "Undeleting %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:45 +#: ../pykolab/imap/cyrus.py:334 +#, python-format +msgid "Would have transfered %s from %s to %s" +msgstr "" + +#: ../pykolab/imap/cyrus.py:336 +#, python-format +msgid "Would have renamed %s to %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:46 #, python-format msgid "Cleaning up ACL entries for %s across all folders" msgstr "" -#: ../pykolab/imap/__init__.py:60 +#: ../pykolab/imap/__init__.py:61 #, python-format msgid "Cleaning up ACL entries referring to identifier %s" msgstr "" -#: ../pykolab/imap/__init__.py:69 +#: ../pykolab/imap/__init__.py:70 #, python-format msgid "Iterating over %d folders" msgstr "" #. Set the ACL to '' (effectively deleting the ACL entry) -#: ../pykolab/imap/__init__.py:82 +#: ../pykolab/imap/__init__.py:83 #, python-format msgid "Removing acl %r for subject %r from folder %r" msgstr "" -#: ../pykolab/imap/__init__.py:143 +#: ../pykolab/imap/__init__.py:145 +msgid "No administrator password is available." +msgstr "" + +#: ../pykolab/imap/__init__.py:153 #, python-format msgid "Logging on to Cyrus IMAP server %s" msgstr "" -#: ../pykolab/imap/__init__.py:152 +#: ../pykolab/imap/__init__.py:162 #, python-format msgid "Logging on to Dovecot IMAP server %s" msgstr "" -#: ../pykolab/imap/__init__.py:161 +#: ../pykolab/imap/__init__.py:171 #, python-format msgid "Logging on to generic IMAP server %s" msgstr "" -#: ../pykolab/imap/__init__.py:179 +#: ../pykolab/imap/__init__.py:189 #, python-format msgid "Reusing existing IMAP server connection to %s" msgstr "" -#: ../pykolab/imap/__init__.py:181 +#: ../pykolab/imap/__init__.py:191 #, python-format msgid "Reconnecting to IMAP server %s" msgstr "" -#: ../pykolab/imap/__init__.py:197 +#: ../pykolab/imap/__init__.py:208 msgid "Called imap.disconnect() on a server that we had no connection to." msgstr "" -#: ../pykolab/imap/__init__.py:212 +#: ../pykolab/imap/__init__.py:222 ../pykolab/imap/__init__.py:234 #, python-format -msgid "%r has no attribute %s" +msgid "Could not create folder %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:223 +#, python-format +msgid " on server %r" msgstr "" -#: ../pykolab/imap/__init__.py:279 -msgid "Private annotations need to be set using the appropriate user account." +#: ../pykolab/imap/__init__.py:244 ../pykolab/imap/__init__.py:246 +#, python-format +msgid "%r has no attribute %s" msgstr "" -#: ../pykolab/imap/__init__.py:294 ../pykolab/imap/__init__.py:329 +#: ../pykolab/imap/__init__.py:393 ../pykolab/imap/__init__.py:428 #, python-format msgid "Creating new shared folder %s" msgstr "" -#: ../pykolab/imap/__init__.py:354 ../pykolab/imap/__init__.py:504 +#: ../pykolab/imap/__init__.py:453 ../pykolab/imap/__init__.py:675 #, python-format msgid "Downcasing mailbox name %r" msgstr "" -#: ../pykolab/imap/__init__.py:358 +#: ../pykolab/imap/__init__.py:457 #, python-format msgid "Creating new mailbox for user %s" msgstr "" -#: ../pykolab/imap/__init__.py:387 +#: ../pykolab/imap/__init__.py:470 +msgid "Waiting for the Cyrus IMAP Murder to settle..." +msgstr "" + +#: ../pykolab/imap/__init__.py:516 #, python-format msgid "Creating additional folders for user %s" msgstr "" -#: ../pykolab/imap/__init__.py:407 +#: ../pykolab/imap/__init__.py:535 +#, python-format +msgid "Waiting for the Cyrus murder to settle... %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:547 +#, python-format +msgid "Correcting additional folder name from %r to %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:553 #, python-format msgid "Mailbox already exists: %s" msgstr "" -#: ../pykolab/imap/__init__.py:443 +#: ../pykolab/imap/__init__.py:593 msgid "Subscribing user to the additional folders" msgstr "" -#: ../pykolab/imap/__init__.py:458 +#: ../pykolab/imap/__init__.py:607 +msgid "Using the following tests for folder subscriptions:" +msgstr "" + +#: ../pykolab/imap/__init__.py:609 +#, python-format +msgid " %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:612 #, python-format msgid "Folder %s" msgstr "" -#: ../pykolab/imap/__init__.py:470 +#: ../pykolab/imap/__init__.py:624 #, python-format msgid "Subscribing %s to folder %s" msgstr "" -#: ../pykolab/imap/__init__.py:520 ../pykolab/imap/__init__.py:594 +#: ../pykolab/imap/__init__.py:628 +#, python-format +msgid "Subscribing %s to folder %s failed: %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:658 +#, python-format +msgid "Could not rename %s to reside on partition %s" +msgstr "" + +#: ../pykolab/imap/__init__.py:691 +#, python-format +msgid "INBOX folder to rename (%s) does not exist" +msgstr "" + +#: ../pykolab/imap/__init__.py:694 ../pykolab/imap/__init__.py:770 #, python-format msgid "Renaming INBOX from %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:524 +#: ../pykolab/imap/__init__.py:698 #, python-format msgid "Could not rename INBOX folder %s to %s" msgstr "" -#: ../pykolab/imap/__init__.py:526 ../pykolab/imap/__init__.py:598 +#: ../pykolab/imap/__init__.py:700 ../pykolab/imap/__init__.py:774 #, python-format -msgid "Moving INBOX folder %s won't succeed as target folder %s already exists" +msgid "" +"Moving INBOX folder %s won't succeed as target folder %s already exists" msgstr "" -#: ../pykolab/imap/__init__.py:536 +#: ../pykolab/imap/__init__.py:704 +#, python-format +msgid "Server for mailbox %r is %r" +msgstr "" + +#: ../pykolab/imap/__init__.py:712 #, python-format msgid "Looking for folder '%s', we found folders: %r" msgstr "" -#: ../pykolab/imap/__init__.py:559 +#: ../pykolab/imap/__init__.py:735 #, python-format msgid "Setting ACL rights %s for subject %s on folder " msgstr "" -#: ../pykolab/imap/__init__.py:570 +#: ../pykolab/imap/__init__.py:746 #, python-format msgid "Removing ACL rights %s for subject %s on folder " msgstr "" -#: ../pykolab/imap/__init__.py:591 +#: ../pykolab/imap/__init__.py:767 #, python-format msgid "Found old INBOX folder %s" msgstr "" -#: ../pykolab/imap/__init__.py:600 +#: ../pykolab/imap/__init__.py:776 #, python-format msgid "Did not find old folder user/%s to rename" msgstr "" -#: ../pykolab/imap/__init__.py:602 +#: ../pykolab/imap/__init__.py:778 msgid "Value for user is not a dictionary" msgstr "" #. TODO: Go in fact correct the quota. -#: ../pykolab/imap/__init__.py:662 +#: ../pykolab/imap/__init__.py:846 #, python-format msgid "Cannot get current IMAP quota for folder %s" msgstr "" -#: ../pykolab/imap/__init__.py:675 +#: ../pykolab/imap/__init__.py:859 #, python-format msgid "Quota for %s currently is %s" msgstr "" -#: ../pykolab/imap/__init__.py:681 +#: ../pykolab/imap/__init__.py:865 #, python-format msgid "Adjusting authentication database quota for folder %s to %d" msgstr "" -#: ../pykolab/imap/__init__.py:686 +#: ../pykolab/imap/__init__.py:870 #, python-format msgid "Correcting quota for %s to %s (currently %s)" msgstr "" -#: ../pykolab/imap/__init__.py:763 +#: ../pykolab/imap/__init__.py:947 #, python-format msgid "Checking folder: %s" msgstr "" -#: ../pykolab/imap/__init__.py:768 +#: ../pykolab/imap/__init__.py:952 #, python-format msgid "Folder has no corresponding user (1): %s" msgstr "" -#: ../pykolab/imap/__init__.py:771 +#: ../pykolab/imap/__init__.py:955 #, python-format msgid "Folder has no corresponding user (2): %s" msgstr "" #. We got user identifier only -#: ../pykolab/imap/__init__.py:786 +#: ../pykolab/imap/__init__.py:970 msgid "Please don't give us just a user identifier" msgstr "" -#: ../pykolab/imap/__init__.py:789 +#: ../pykolab/imap/__init__.py:973 #, python-format msgid "Deleting folder %s" msgstr "" @@ -1345,12 +1872,50 @@ msgid "Returning thread local configuration" msgstr "" -#: ../pykolab/logger.py:106 +#: ../pykolab/itip/__init__.py:43 #, python-format -msgid "Could not change the ownership of log file %s" +msgid "Method %r not really interesting for us." +msgstr "" + +#: ../pykolab/itip/__init__.py:49 +#, python-format +msgid "Raw iTip payload: %s" +msgstr "" + +#: ../pykolab/itip/__init__.py:59 +msgid "Could not read iTip from message." msgstr "" -#: ../pykolab/logger.py:122 +#: ../pykolab/itip/__init__.py:67 +#, python-format +msgid "Duplicate iTip object: %s" +msgstr "" + +#: ../pykolab/itip/__init__.py:90 +msgid "iTip event without a start" +msgstr "" + +#: ../pykolab/itip/__init__.py:132 +msgid "Message is not an iTip message (non-multipart message)" +msgstr "" + +#: ../pykolab/itip/__init__.py:225 +#, python-format +msgid "Failed to compose iTip reply message: %r" +msgstr "" + +#: ../pykolab/itip/__init__.py:236 ../wallace/module_invitationpolicy.py:936 +#: ../wallace/module_resources.py:964 +#, python-format +msgid "SMTP sendmail error: %r" +msgstr "" + +#: ../pykolab/logger.py:173 ../pykolab/logger.py:179 +#, python-format +msgid "Could not change permissions on %s: %r" +msgstr "" + +#: ../pykolab/logger.py:196 #, python-format msgid "Cannot log to file %s: %s" msgstr "" @@ -1448,27 +2013,51 @@ msgid "Attribute substitution for 'mail' failed in Recipient Policy" msgstr "" -#: ../pykolab/plugins/recipientpolicy/__init__.py:115 +#: ../pykolab/plugins/recipientpolicy/__init__.py:116 msgid "Could not parse the alternative mail routines" msgstr "" -#: ../pykolab/plugins/recipientpolicy/__init__.py:119 +#: ../pykolab/plugins/recipientpolicy/__init__.py:120 #, python-format msgid "Alternative mail routines: %r" msgstr "" -#: ../pykolab/plugins/recipientpolicy/__init__.py:130 -#: ../pykolab/plugins/recipientpolicy/__init__.py:141 +#: ../pykolab/plugins/recipientpolicy/__init__.py:127 +#, python-format +msgid "" +"An error occurred in composing the secondary mail attribute for entry %r" +msgstr "" + +#: ../pykolab/plugins/recipientpolicy/__init__.py:138 +#: ../pykolab/plugins/recipientpolicy/__init__.py:153 #, python-format msgid "Appending additional mail address: %s" msgstr "" -#: ../pykolab/plugins/recipientpolicy/__init__.py:134 -#: ../pykolab/plugins/recipientpolicy/__init__.py:145 +#: ../pykolab/plugins/recipientpolicy/__init__.py:142 +#, python-format +msgid "Policy for secondary email address failed: %r" +msgstr "" + +#: ../pykolab/plugins/recipientpolicy/__init__.py:157 msgid "" "Attribute substitution for 'alternative_mail' failed in Recipient Policy" msgstr "" +#: ../pykolab/plugins/roundcubedb/__init__.py:48 +#, python-format +msgid "user_delete: %r" +msgstr "" + +#: ../pykolab/plugins/roundcubedb/__init__.py:55 +#: ../pykolab/setup/setup_roundcube.py:160 +msgid "Roundcube installation path not found." +msgstr "" + +#: ../pykolab/plugins/sievemgmt/__init__.py:51 +msgid "Wrong number of arguments for sieve management plugin" +msgstr "" + #: ../pykolab/setup/components.py:58 msgid "Display this help." msgstr "" @@ -1489,61 +2078,29 @@ msgid "Free/Busy is not installed on this system" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:55 -msgid "" -"\n" -" Please supply the MySQL password for the " -"'roundcube'\n" -" user. You have supplied this password earlier, and " -"it is\n" -" available from the database URI setting in\n" -" /etc/roundcubemail/db.inc.php.\n" -" " -msgstr "" - -#: ../pykolab/setup/setup_freebusy.py:64 -#: ../pykolab/setup/setup_roundcube.py:56 -msgid "MySQL roundcube password" +#: ../pykolab/setup/setup_imap.py:45 +msgid "Setup IMAP." msgstr "" -#: ../pykolab/setup/setup_freebusy.py:92 -#: ../pykolab/setup/setup_roundcube.py:115 ../pykolab/setup/setup_zpush.py:71 -#, python-format -msgid "Using template file %r" +#: ../pykolab/setup/setup_imap.py:89 +msgid "Could not write out Cyrus IMAP configuration file /etc/imapd.conf" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:99 -#: ../pykolab/setup/setup_roundcube.py:122 ../pykolab/setup/setup_zpush.py:78 -#, python-format -msgid "Successfully compiled template %r, writing out to %r" +#: ../pykolab/setup/setup_imap.py:114 +msgid "Could not write out Cyrus IMAP configuration file /etc/cyrus.conf" msgstr "" -#: ../pykolab/setup/setup_freebusy.py:119 -#: ../pykolab/setup/setup_roundcube.py:193 -#: ../pykolab/setup/setup_syncroton.py:66 ../pykolab/setup/setup_zpush.py:98 -msgid "Could not start the webserver server service." +#: ../pykolab/setup/setup_imap.py:158 +msgid "Could not start the cyrus-imapd and kolab-saslauthd services." msgstr "" -#: ../pykolab/setup/setup_freebusy.py:128 ../pykolab/setup/setup_imap.py:169 -#: ../pykolab/setup/setup_kolabd.py:81 ../pykolab/setup/setup_ldap.py:327 -#: ../pykolab/setup/setup_mta.py:378 ../pykolab/setup/setup_mysql.py:58 -#: ../pykolab/setup/setup_roundcube.py:202 -#: ../pykolab/setup/setup_syncroton.py:75 ../pykolab/setup/setup_zpush.py:107 +#: ../pykolab/setup/setup_imap.py:173 ../pykolab/setup/setup_kolabd.py:81 +#: ../pykolab/setup/setup_ldap.py:426 ../pykolab/setup/setup_mta.py:455 +#: ../pykolab/setup/setup_mysql.py:58 ../pykolab/setup/setup_roundcube.py:237 +#: ../pykolab/setup/setup_syncroton.py:102 msgid "Could not configure to start on boot, the " msgstr "" -#: ../pykolab/setup/setup_imap.py:45 -msgid "Setup IMAP." -msgstr "" - -#: ../pykolab/setup/setup_imap.py:89 ../pykolab/setup/setup_imap.py:114 -msgid "Could not write out Cyrus IMAP configuration file /etc/imapd.conf" -msgstr "" - -#: ../pykolab/setup/setup_imap.py:154 -msgid "Could not start the cyrus-imapd and kolab-saslauthd services." -msgstr "" - #: ../pykolab/setup/setup_kolabd.py:43 msgid "Setup the Kolab daemon." msgstr "" @@ -1552,8 +2109,7 @@ #, python-format msgid "" "\n" -" Copying the configuration section for 'example." -"org' over to\n" +" Copying the configuration section for 'example.org' over to\n" " a section applicable to your domain '%s'.\n" " " msgstr "" @@ -1574,220 +2130,250 @@ msgid "Allow anonymous binds (default: no)." msgstr "" -#: ../pykolab/setup/setup_ldap.py:64 -msgid "Setup LDAP." +#: ../pykolab/setup/setup_ldap.py:68 +msgid "Skip setting up the LDAP server." msgstr "" #: ../pykolab/setup/setup_ldap.py:76 +msgid "Setup configuration for OpenLDAP compatibility." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:84 +msgid "Setup configuration for Active Directory compatibility." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:88 +msgid "Setup LDAP." +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:97 +msgid "Skipping setup of LDAP, as specified" +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:126 +msgid "" +"\n" +" You can not configure Kolab to run against OpenLDAP\n" +" and Active Directory simultaneously.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:139 +msgid "" +"\n" +" It seems 389 Directory Server has an existing\n" +" instance configured. This setup script does not\n" +" intend to destroy or overwrite your data. Please\n" +" make sure /etc/dirsrv/ and /var/lib/dirsrv/ are\n" +" clean so that this setup does not have to worry.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:154 msgid "" "\n" -" Please supply a password for the LDAP administrator " -"user\n" -" 'admin', used to login to the graphical console of " -"389\n" +" Please supply a password for the LDAP administrator user\n" +" 'admin', used to login to the graphical console of 389\n" " Directory server.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:84 +#: ../pykolab/setup/setup_ldap.py:162 msgid "Administrator password" msgstr "" -#: ../pykolab/setup/setup_ldap.py:91 +#: ../pykolab/setup/setup_ldap.py:169 msgid "" "\n" -" Please supply a password for the LDAP Directory " -"Manager\n" -" user, which is the administrator user you will be " -"using\n" -" to at least initially log in to the Web Admin, and " -"that\n" +" Please supply a password for the LDAP Directory Manager\n" +" user, which is the administrator user you will be using\n" +" to at least initially log in to the Web Admin, and that\n" " Kolab uses to perform administrative tasks.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:100 +#: ../pykolab/setup/setup_ldap.py:178 msgid "Directory Manager password" msgstr "" -#: ../pykolab/setup/setup_ldap.py:107 +#: ../pykolab/setup/setup_ldap.py:185 msgid "" "\n" " Please choose the system user and group the service\n" " should use to run under. These should be existing,\n" -" unprivileged, local system POSIX accounts with no " -"shell.\n" +" unprivileged, local system POSIX accounts with no shell.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:117 ../pykolab/setup/setup_ldap.py:120 +#: ../pykolab/setup/setup_ldap.py:195 ../pykolab/setup/setup_ldap.py:198 msgid "User" msgstr "" -#: ../pykolab/setup/setup_ldap.py:118 ../pykolab/setup/setup_ldap.py:121 +#: ../pykolab/setup/setup_ldap.py:196 ../pykolab/setup/setup_ldap.py:199 msgid "Group" msgstr "" -#: ../pykolab/setup/setup_ldap.py:157 +#: ../pykolab/setup/setup_ldap.py:234 msgid "" "\n" -" This setup procedure plans to set up Kolab Groupware " -"for\n" -" the following domain name space. This domain name " -"is\n" +" This setup procedure plans to set up Kolab Groupware for\n" +" the following domain name space. This domain name is\n" " obtained from the reverse DNS entry on your network\n" -" interface. Please confirm this is the appropriate " -"domain\n" +" interface. Please confirm this is the appropriate domain\n" " name space.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:171 +#: ../pykolab/setup/setup_ldap.py:248 msgid "Domain name to use" msgstr "" -#: ../pykolab/setup/setup_ldap.py:176 ../pykolab/setup/setup_ldap.py:201 +#: ../pykolab/setup/setup_ldap.py:253 ../pykolab/setup/setup_ldap.py:278 msgid "" "\n" " Invalid input. Please try again.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:185 +#: ../pykolab/setup/setup_ldap.py:262 msgid "" "\n" -" The standard root dn we composed for you follows. " -"Please\n" +" The standard root dn we composed for you follows. Please\n" " confirm this is the root dn you wish to use.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:196 +#: ../pykolab/setup/setup_ldap.py:273 msgid "Root DN to use" msgstr "" -#: ../pykolab/setup/setup_ldap.py:244 +#: ../pykolab/setup/setup_ldap.py:325 msgid "No directory server setup tool available." msgstr "" -#: ../pykolab/setup/setup_ldap.py:255 +#: ../pykolab/setup/setup_ldap.py:337 msgid "" "\n" -" Setup is now going to set up the 389 Directory Server. " -"This\n" -" may take a little while (during which period there is " -"no\n" +" Setup is now going to set up the 389 Directory Server. This\n" +" may take a little while (during which period there is no\n" " output and no progress indication).\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:262 +#: ../pykolab/setup/setup_ldap.py:344 msgid "Setting up 389 Directory Server" msgstr "" -#. TODO: Get the return code and display output if not successful. -#: ../pykolab/setup/setup_ldap.py:274 +#: ../pykolab/setup/setup_ldap.py:356 +msgid "" +"\n" +" An error was detected in the setup procedure for 389\n" +" Directory Server. This setup will write out stderr and\n" +" stdout to /var/log/kolab/setup.error.log and\n" +" /var/log/kolab/setup.out.log respectively, before it\n" +" exits.\n" +" " +msgstr "" + +#: ../pykolab/setup/setup_ldap.py:373 msgid "Setup DS stdout:" msgstr "" -#: ../pykolab/setup/setup_ldap.py:277 +#: ../pykolab/setup/setup_ldap.py:376 msgid "Setup DS stderr:" msgstr "" -#: ../pykolab/setup/setup_ldap.py:303 +#: ../pykolab/setup/setup_ldap.py:402 msgid "Could not copy the LDAP extensions for Kolab" msgstr "" -#: ../pykolab/setup/setup_ldap.py:306 +#: ../pykolab/setup/setup_ldap.py:405 msgid "Could not find the ldap Kolab schema file" msgstr "" -#: ../pykolab/setup/setup_ldap.py:318 +#: ../pykolab/setup/setup_ldap.py:417 msgid "Could not start the directory server service." msgstr "" -#: ../pykolab/setup/setup_ldap.py:332 +#: ../pykolab/setup/setup_ldap.py:431 msgid "" "\n" " Please supply a Cyrus Administrator password. This\n" " password is used by Kolab to execute administrative\n" " tasks in Cyrus IMAP. You may also need the password\n" " yourself to troubleshoot Cyrus IMAP and/or perform\n" -" other administrative tasks against Cyrus IMAP " -"directly.\n" +" other administrative tasks against Cyrus IMAP directly.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:342 +#: ../pykolab/setup/setup_ldap.py:441 msgid "Cyrus Administrator password" msgstr "" -#: ../pykolab/setup/setup_ldap.py:349 +#: ../pykolab/setup/setup_ldap.py:448 msgid "" "\n" -" Please supply a Kolab Service account password. " -"This\n" -" account is used by various services such as " -"Postfix,\n" -" and Roundcube, as anonymous binds to the LDAP " -"server\n" +" Please supply a Kolab Service account password. This\n" +" account is used by various services such as Postfix,\n" +" and Roundcube, as anonymous binds to the LDAP server\n" " will not be allowed.\n" " " msgstr "" -#: ../pykolab/setup/setup_ldap.py:358 +#: ../pykolab/setup/setup_ldap.py:457 msgid "Kolab Service password" msgstr "" -#: ../pykolab/setup/setup_ldap.py:368 +#: ../pykolab/setup/setup_ldap.py:467 msgid "Writing out configuration to kolab.conf" msgstr "" -#: ../pykolab/setup/setup_ldap.py:382 +#: ../pykolab/setup/setup_ldap.py:481 msgid "Inserting service users into LDAP." msgstr "" -#: ../pykolab/setup/setup_ldap.py:456 +#: ../pykolab/setup/setup_ldap.py:555 msgid "Writing out cn=kolab,cn=config" msgstr "" #. TODO: Add kolab-admin role #. TODO: Assign kolab-admin admin ACLs -#: ../pykolab/setup/setup_ldap.py:480 +#: ../pykolab/setup/setup_ldap.py:579 #, python-format msgid "Adding domain %s to list of domains for this deployment" msgstr "" -#: ../pykolab/setup/setup_ldap.py:497 +#: ../pykolab/setup/setup_ldap.py:607 msgid "Disabling anonymous binds" msgstr "" #. TODO: Ensure the uid attribute is unique -#. TODO^2: Consider renaming the general "attribute uniqueness to "uid attribute uniqueness" -#: ../pykolab/setup/setup_ldap.py:505 +#. TODO^2: Consider renaming the general "attribute uniqueness to "uid +#. attribute uniqueness" +#: ../pykolab/setup/setup_ldap.py:615 msgid "Enabling attribute uniqueness plugin" msgstr "" -#: ../pykolab/setup/setup_ldap.py:511 +#: ../pykolab/setup/setup_ldap.py:621 msgid "Enabling referential integrity plugin" msgstr "" -#: ../pykolab/setup/setup_ldap.py:517 +#: ../pykolab/setup/setup_ldap.py:627 msgid "Enabling and configuring account policy plugin" msgstr "" #. TODO: Add kolab-admin role -#: ../pykolab/setup/setup_ldap.py:532 +#: ../pykolab/setup/setup_ldap.py:642 msgid "Adding the kolab-admin role" msgstr "" #. TODO: User writeable attributes on root_dn -#: ../pykolab/setup/setup_ldap.py:543 +#: ../pykolab/setup/setup_ldap.py:653 #, python-format msgid "Setting access control to %s" msgstr "" -#: ../pykolab/setup/setup_ldap.py:568 +#: ../pykolab/setup/setup_ldap.py:679 msgid "Could not start and configure to start on boot, the " msgstr "" @@ -1795,24 +2381,24 @@ msgid "Setup MTA." msgstr "" -#: ../pykolab/setup/setup_mta.py:245 ../pykolab/setup/setup_php.py:104 +#: ../pykolab/setup/setup_mta.py:317 ../pykolab/setup/setup_php.py:106 #, python-format msgid "Setting key %r to %r" msgstr "" -#: ../pykolab/setup/setup_mta.py:278 +#: ../pykolab/setup/setup_mta.py:350 msgid "Could not write out Postfix configuration file /etc/postfix/master.cf" msgstr "" -#: ../pykolab/setup/setup_mta.py:321 -msgid "Could not write out Amavis configuration file /etc/amavisd/amavisd.conf" +#: ../pykolab/setup/setup_mta.py:397 +msgid "Could not write out Amavis configuration file amavisd.conf" msgstr "" -#: ../pykolab/setup/setup_mta.py:329 +#: ../pykolab/setup/setup_mta.py:405 msgid "Not writing out any configuration for Amavis." msgstr "" -#: ../pykolab/setup/setup_mta.py:360 +#: ../pykolab/setup/setup_mta.py:437 msgid "Could not start the postfix, clamav and amavisd services services." msgstr "" @@ -1824,55 +2410,50 @@ msgid "Could not start the MySQL database service." msgstr "" -#: ../pykolab/setup/setup_mysql.py:68 +#: ../pykolab/setup/setup_mysql.py:71 msgid "What MySQL server are we setting up?" msgstr "" -#: ../pykolab/setup/setup_mysql.py:72 +#: ../pykolab/setup/setup_mysql.py:75 msgid "" "\n" -" Please supply the root password for MySQL, so we can " -"set\n" -" up user accounts for other components that use " -"MySQL.\n" +" Please supply the root password for MySQL, so we can set\n" +" up user accounts for other components that use MySQL.\n" " " msgstr "" -#: ../pykolab/setup/setup_mysql.py:79 ../pykolab/setup/setup_mysql.py:96 +#: ../pykolab/setup/setup_mysql.py:82 ../pykolab/setup/setup_mysql.py:99 +#: ../pykolab/setup/setup_roundcube.py:183 +#: ../pykolab/setup/setup_syncroton.py:63 msgid "MySQL root password" msgstr "" -#: ../pykolab/setup/setup_mysql.py:85 +#: ../pykolab/setup/setup_mysql.py:88 msgid "" "\n" -" Please supply a root password for MySQL. This " -"password\n" -" will be the administrative user for this MySQL " -"server,\n" -" and it should be kept a secret. After this setup " -"process\n" +" Please supply a root password for MySQL. This password\n" +" will be the administrative user for this MySQL server,\n" +" and it should be kept a secret. After this setup process\n" " has completed, Kolab is going to discard and forget\n" " about this password, but you will need it for\n" " administrative tasks in MySQL.\n" " " msgstr "" -#: ../pykolab/setup/setup_mysql.py:136 +#: ../pykolab/setup/setup_mysql.py:139 msgid "" "\n" -" Please supply a password for the MySQL user " -"'kolab'.\n" -" This password will be used by Kolab services, such " -"as\n" +" Please supply a password for the MySQL user 'kolab'.\n" +" This password will be used by Kolab services, such as\n" " the Web Administration Panel.\n" " " msgstr "" -#: ../pykolab/setup/setup_mysql.py:144 +#: ../pykolab/setup/setup_mysql.py:147 msgid "MySQL kolab password" msgstr "" -#: ../pykolab/setup/setup_mysql.py:162 +#: ../pykolab/setup/setup_mysql.py:165 msgid "Could not find the MySQL Kolab schema file" msgstr "" @@ -1896,19 +2477,21 @@ msgid "" "\n" " Please supply the timezone PHP should be using.\n" +" You have to use a Continent or Country / City locality name\n" +" like 'Europe/Berlin', but not just 'CEST'.\n" " " msgstr "" -#: ../pykolab/setup/setup_php.py:72 +#: ../pykolab/setup/setup_php.py:74 msgid "Timezone ID" msgstr "" -#: ../pykolab/setup/setup_php.py:78 +#: ../pykolab/setup/setup_php.py:80 #, python-format msgid "Cannot configure PHP through %r (No such file or directory)" msgstr "" -#: ../pykolab/setup/setup_php.py:89 +#: ../pykolab/setup/setup_php.py:91 msgid "Could not find PHP configuration file php.ini" msgstr "" @@ -1919,23 +2502,33 @@ #: ../pykolab/setup/setup_roundcube.py:48 msgid "" "\n" -" Please supply a password for the MySQL user " -"'roundcube'.\n" +" Please supply a password for the MySQL user 'roundcube'.\n" " This password will be used by the Roundcube webmail\n" " interface.\n" " " msgstr "" -#: ../pykolab/setup/setup_syncroton.py:40 -msgid "Setup Syncroton." +#: ../pykolab/setup/setup_roundcube.py:56 +msgid "MySQL roundcube password" msgstr "" -#: ../pykolab/setup/setup_zpush.py:41 -msgid "Setup zpush." +#: ../pykolab/setup/setup_roundcube.py:120 +#, python-format +msgid "Using template file %r" +msgstr "" + +#: ../pykolab/setup/setup_roundcube.py:127 +#, python-format +msgid "Successfully compiled template %r, writing out to %r" msgstr "" -#: ../pykolab/setup/setup_zpush.py:45 -msgid "Z-Push is not installed on this system" +#: ../pykolab/setup/setup_roundcube.py:228 +#: ../pykolab/setup/setup_syncroton.py:93 +msgid "Could not start the webserver server service." +msgstr "" + +#: ../pykolab/setup/setup_syncroton.py:40 +msgid "Setup Syncroton." msgstr "" #. start_max = (int)(time.time()) @@ -1963,198 +2556,616 @@ msgid "No database available" msgstr "" -#: ../pykolab/utils.py:60 ../pykolab/utils.py:62 +#: ../pykolab/utils.py:62 ../pykolab/utils.py:64 #, python-format msgid "Confirm %s: " msgstr "" -#: ../pykolab/utils.py:65 +#: ../pykolab/utils.py:67 msgid "Incorrect confirmation. " msgstr "" -#: ../pykolab/utils.py:70 ../pykolab/utils.py:75 +#: ../pykolab/utils.py:72 ../pykolab/utils.py:77 #, python-format msgid "%s: " msgstr "" -#: ../pykolab/utils.py:72 ../pykolab/utils.py:77 +#: ../pykolab/utils.py:74 ../pykolab/utils.py:79 #, python-format msgid "%s [%s]: " msgstr "" -#: ../pykolab/utils.py:122 +#: ../pykolab/utils.py:124 msgid "Please answer 'yes' or 'no'." msgstr "" -#: ../pykolab/utils.py:148 +#: ../pykolab/utils.py:164 msgid "Choice" msgstr "" -#: ../pykolab/utils.py:214 +#: ../pykolab/utils.py:167 +msgid "Choice (type '?' for options)" +msgstr "" + +#: ../pykolab/utils.py:268 #, python-format msgid "Could not change the permissions on %s" msgstr "" -#: ../pykolab/utils.py:395 +#: ../pykolab/utils.py:479 #, python-format msgid "Transliterating string %r with locale %r" msgstr "" -#: ../pykolab/utils.py:403 +#: ../pykolab/utils.py:487 msgid "Attempting to set locale" msgstr "" -#: ../pykolab/utils.py:405 +#: ../pykolab/utils.py:489 msgid "Success setting locale" msgstr "" -#: ../pykolab/utils.py:407 +#: ../pykolab/utils.py:491 msgid "Failure to set locale" msgstr "" -#: ../pykolab/utils.py:415 +#: ../pykolab/utils.py:499 #, python-format msgid "Executing '%s | %s'" msgstr "" -#: ../pykolab/wap_client/__init__.py:257 +#: ../pykolab/utils.py:510 +#, python-format +msgid "Could not translate %s using locale %s" +msgstr "" + +#: ../pykolab/wap_client/__init__.py:320 #, python-format msgid "Requesting %r with params %r" msgstr "" -#: ../pykolab/wap_client/__init__.py:263 +#: ../pykolab/wap_client/__init__.py:328 #, python-format msgid "Got response: %r" msgstr "" #. Some data is not JSON -#: ../pykolab/wap_client/__init__.py:268 +#: ../pykolab/wap_client/__init__.py:334 msgid "Response data is not JSON" msgstr "" -#: ../pykolab/xml/attendee.py:79 ../pykolab/xml/attendee.py:99 +#. support integer values, too +#: ../pykolab/xml/attendee.py:9 ../pykolab/xml/attendee.py:17 +msgid "Needs Action" +msgstr "" + +#: ../pykolab/xml/attendee.py:10 ../pykolab/xml/attendee.py:18 +msgid "Accepted" +msgstr "Akzeptiert" + +#: ../pykolab/xml/attendee.py:11 ../pykolab/xml/attendee.py:19 +msgid "Declined" +msgstr "Abgelehnt" + +#: ../pykolab/xml/attendee.py:12 ../pykolab/xml/attendee.py:20 +msgid "Tentatively Accepted" +msgstr "Provisorisch Akzeptiert" + +#: ../pykolab/xml/attendee.py:13 ../pykolab/xml/attendee.py:21 +msgid "Delegated" +msgstr "Delegiert" + +#: ../pykolab/xml/attendee.py:14 +msgid "Completed" +msgstr "" + +#: ../pykolab/xml/attendee.py:15 +msgid "In Process" +msgstr "" + +#: ../pykolab/xml/attendee.py:108 ../pykolab/xml/attendee.py:130 msgid "Not a valid attendee" msgstr "" -#: ../pykolab/xml/attendee.py:84 +#: ../pykolab/xml/attendee.py:115 msgid "No valid delegator references found" msgstr "" -#: ../pykolab/xml/attendee.py:104 +#: ../pykolab/xml/attendee.py:135 msgid "No valid delegatee references found" msgstr "" -#: ../pykolab/xml/attendee.py:140 +#: ../pykolab/xml/attendee.py:180 #, python-format msgid "Invalid cutype %r" msgstr "" -#: ../pykolab/xml/attendee.py:151 +#: ../pykolab/xml/attendee.py:192 #, python-format msgid "Invalid participant status %r" msgstr "" -#: ../pykolab/xml/attendee.py:159 +#: ../pykolab/xml/attendee.py:200 #, python-format msgid "Invalid role %r" msgstr "" -#: ../pykolab/xml/event.py:172 +#: ../pykolab/xml/event.py:100 ../pykolab/xml/event.py:708 +#: ../pykolab/xml/event.py:751 +msgid "Event start needs datetime.date or datetime.datetime instance" +msgstr "" + +#: ../pykolab/xml/event.py:241 #, python-format msgid "No attendee with email or name %r" msgstr "" -#: ../pykolab/xml/event.py:180 +#: ../pykolab/xml/event.py:249 #, python-format msgid "Invalid argument value attendee %r, must be basestring or Attendee" msgstr "" -#: ../pykolab/xml/event.py:186 +#: ../pykolab/xml/event.py:255 #, python-format msgid "No attendee with email %r" msgstr "" -#: ../pykolab/xml/event.py:192 +#: ../pykolab/xml/event.py:261 #, python-format msgid "No attendee with name %r" msgstr "" -#: ../pykolab/xml/event.py:338 +#: ../pykolab/xml/event.py:426 msgid "Invalid participant status" msgstr "" -#: ../pykolab/xml/event.py:538 -msgid "Event end needs datetime.date or datetime.datetime instance" +#: ../pykolab/xml/event.py:542 +#, python-format +msgid "Invalid status %r" msgstr "" -#: ../pykolab/xml/event.py:657 +#: ../pykolab/xml/event.py:550 #, python-format -msgid "Invalid status %r" +msgid "Invalid classification %r" msgstr "" -#: ../pykolab/xml/event.py:678 ../pykolab/xml/event.py:728 -msgid "Event start needs datetime.date or datetime.datetime instance" +#: ../pykolab/xml/event.py:577 +msgid "Event end needs datetime.date or datetime.datetime instance" msgstr "" -#: ../pykolab/xml/event.py:764 +#: ../pykolab/xml/event.py:761 #, python-format msgid "Invalid status set: %r" msgstr "" -#: ../pykolab/xml/event.py:882 +#: ../pykolab/xml/event.py:923 msgid "No sender specified" msgstr "" -#: ../saslauthd/__init__.py:126 ../saslauthd/__init__.py:134 -msgid "Traceback occurred, please report a bug at http://bugzilla.kolabsys.com" +#: ../pykolab/xml/event.py:932 +#, python-format +msgid "Invitation for %s was %s" +msgstr "" + +#: ../pykolab/xml/event.py:937 +msgid "This is an automated response to one of your event requests." +msgstr "" + +#: ../saslauthd/__init__.py:99 +#, python-format +msgid "Could not create %r: %r" +msgstr "" + +#: ../saslauthd/__init__.py:137 ../saslauthd/__init__.py:145 +#: ../wallace/__init__.py:403 ../wallace/__init__.py:412 +msgid "" +"Traceback occurred, please report a bug at http://bugzilla.kolabsys.com" +msgstr "" + +#: ../saslauthd/__init__.py:185 +msgid "kolab-saslauthd could not accept " +msgstr "" + +#: ../saslauthd/__init__.py:190 +msgid "Maximum tries exceeded, exiting" +msgstr "" + +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:190 +#: ../wallace/module_resources.py:879 +#, python-format +msgid "Reservation Request for %(summary)s was %(status)s" +msgstr "" + +#. check notification message sent to resource owner (jane) +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:605 +#: ../tests/functional/test_wallace/test_005_resource_invitation.py:621 +#: ../wallace/module_resources.py:954 +#, python-format +msgid "Booking for %s has been %s" +msgstr "" + +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:146 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:720 +#: ../wallace/module_invitationpolicy.py:374 +#, python-format +msgid "\"%(summary)s\" has been %(status)s" +msgstr "" + +#. check for notification message +#. this notification should be suppressed until mark has replied, too +#. this triggers an additional notification +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:616 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:622 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:635 +#: ../wallace/module_invitationpolicy.py:925 +#, python-format +msgid "\"%s\" has been updated" msgstr "" -#: ../wallace/__init__.py:62 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:627 +#: ../tests/functional/test_wallace/test_007_invitationpolicy.py:639 +msgid "PENDING" +msgstr "" + +#: ../wallace/__init__.py:57 +#, python-format +msgid "Wallace modules: %r" +msgstr "" + +#: ../wallace/__init__.py:69 +#, python-format +msgid "Module %s.execute() failed on message %r with error: %s" +msgstr "" + +#: ../wallace/__init__.py:78 #, python-format msgid "Worker process %s initializing" msgstr "" -#: ../wallace/__init__.py:81 +#: ../wallace/__init__.py:100 msgid "Bind address for Wallace." msgstr "" -#: ../wallace/__init__.py:107 +#: ../wallace/__init__.py:126 msgid "Port that Wallace is supposed to use." msgstr "" -#: ../wallace/__init__.py:158 +#: ../wallace/__init__.py:177 #, python-format msgid "Could not bind to socket on port %d on bind " msgstr "" -#: ../wallace/__init__.py:170 +#: ../wallace/__init__.py:189 msgid "Could not shut down socket" msgstr "" -#: ../wallace/__init__.py:227 +#: ../wallace/__init__.py:253 msgid "Accepted connection" msgstr "" -#: ../wallace/__init__.py:398 +#: ../wallace/__init__.py:428 #, python-format msgid "Could not write pid file %s" msgstr "" -#: ../wallace/module_optout.py:61 ../wallace/module_resources.py:93 +#: ../wallace/module_footer.py:60 ../wallace/module_gpgencrypt.py:60 +#: ../wallace/module_invitationpolicy.py:168 ../wallace/module_optout.py:61 +#: ../wallace/module_resources.py:120 #, python-format msgid "Issuing callback after processing to stage %s" msgstr "" -#: ../wallace/module_optout.py:62 ../wallace/module_resources.py:99 +#: ../wallace/module_footer.py:61 ../wallace/module_gpgencrypt.py:61 +#: ../wallace/module_invitationpolicy.py:170 ../wallace/module_optout.py:62 +#: ../wallace/module_resources.py:126 #, python-format msgid "Testing cb_action_%s()" msgstr "" -#: ../wallace/module_optout.py:64 ../wallace/module_resources.py:102 +#: ../wallace/module_footer.py:63 ../wallace/module_gpgencrypt.py:63 +#: ../wallace/module_invitationpolicy.py:172 ../wallace/module_optout.py:64 +#: ../wallace/module_resources.py:129 #, python-format msgid "Attempting to execute cb_action_%s()" msgstr "" +#: ../wallace/module_footer.py:67 +#, python-format +msgid "Executing module footer for %r, %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:66 +#, python-format +msgid "Executing module gpgencrypt for %r, %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:98 +msgid "Message is already encrypted (app/pgp-enc content-type)" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:102 +msgid "Message already encrypted by main content-type header" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:131 +msgid "" +"Configured to encrypt to a key not configured, and strict policy enabled. " +"Bailing out." +msgstr "" + +#: ../wallace/module_gpgencrypt.py:134 +msgid "" +"Configured to encrypt to a key not configured, but continuing anyway (see " +"'gpgencrypt_strict')." +msgstr "" + +#: ../wallace/module_gpgencrypt.py:171 +#, python-format +msgid "Recipients: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:183 +#, python-format +msgid "Current keys: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:188 +#, python-format +msgid "Retrieving key for recipient: %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:192 ../wallace/module_gpgencrypt.py:208 +#, python-format +msgid "Found matching address %r" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:200 +#, python-format +msgid "Found matching address %r in remote keys" +msgstr "" + +#: ../wallace/module_gpgencrypt.py:232 +#, python-format +msgid "An error occurred: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:154 +#, python-format +msgid "Invitation policy called for %r, %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:211 +#: ../wallace/module_resources.py:169 +#, python-format +msgid "Failed to parse iTip events from message: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:215 +msgid "" +"Message is not an iTip message or does not contain any (valid) iTip events." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:219 +#, python-format +msgid "" +"iTip events attached to this message contain the following information: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:232 +#, python-format +msgid "No itips, no users, pass along %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:235 +#, python-format +msgid "iTips, but no users, pass along %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:255 +#, python-format +msgid "No user attendee matching envelope recipient %s, skip message" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:259 +#, python-format +msgid "Receiving user: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:284 +#, python-format +msgid "Apply invitation policy %r for domain %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:295 +#, python-format +msgid "Ignoring '%s' iTip method" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:299 +#, python-format +msgid "iTip message %r consumed by the invitationpolicy module" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:315 +msgid "Pass invitation for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:320 +#, python-format +msgid "Receiving Attendee: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:339 +#, python-format +msgid "Existing event: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:350 +#, python-format +msgid "Precondition for event %r fulfilled: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:386 +#, python-format +msgid "No RSVP for recipient %r requested" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:412 +msgid "Pass reply for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:419 +#, python-format +msgid "Sender Attendee: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:431 +#, python-format +msgid "" +"The iTip reply sequence (%r) doesn't match the referred event version (%r). " +"Forwarding to Inbox." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:437 +#, python-format +msgid "Auto-updating event %r on iTip REPLY" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:459 +#: ../wallace/module_invitationpolicy.py:488 +msgid "" +"The event referred by this reply was not found in the user's calendars. " +"Forwarding to Inbox." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:472 +msgid "Pass cancellation for manual processing" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:517 +#, python-format +msgid "Checking if email address %r belongs to a local user" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:522 +#, python-format +msgid "User DN: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:524 +#, python-format +msgid "No user record(s) found for %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:577 +#, python-format +msgid "User record doesn't have the mailbox attribute %r set" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:590 +#, python-format +msgid "IMAP proxy authentication failed: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:612 +#, python-format +msgid "List calendar folders for user %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:628 +#, python-format +msgid "IMAP metadata for %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:658 +#, python-format +msgid "Searching folder %r for event %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:670 +#: ../wallace/module_invitationpolicy.py:709 +#: ../wallace/module_resources.py:486 +#, python-format +msgid "Failed to parse event from message %s/%s: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:696 +#, python-format +msgid "Listing events from folder %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:715 +#, python-format +msgid "Existing event %r conflicts with invitation %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:722 +#: ../wallace/module_resources.py:344 +#, python-format +msgid "start: %r, end: %r, total: %r, messages: %d" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:748 +#, python-format +msgid "%r is locked, waiting..." +msgstr "" + +#: ../wallace/module_invitationpolicy.py:811 +#, python-format +msgid "Failed to save event: no calendar folder found for user %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:814 +#, python-format +msgid "Save event %r to user calendar %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:827 +#, python-format +msgid "Failed to save event to user calendar at %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:843 +#, python-format +msgid "Delete event %r in %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:863 +#, python-format +msgid "Compose participation status summary for event %r to user %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:901 +#, python-format +msgid "" +"Waiting for more automated replies (got %d of %d); skipping notification" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:998 +#, python-format +msgid "Updated %s's copy of %r: %r" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1001 +#, python-format +msgid "Attendee %s's copy of %r not found" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1004 +#, python-format +msgid "Attendee %r not found in LDAP" +msgstr "" + +#: ../wallace/module_invitationpolicy.py:1008 +#, python-format +msgid "" +"\n" +" %(name)s has %(status)s your invitation for %(summary)s.\n" +"\n" +" *** This is an automated response sent by the Kolab Invitation system ***\n" +" " +msgstr "" + #. modules.next_module('optout') #: ../wallace/module_optout.py:70 #, python-format @@ -2176,171 +3187,256 @@ msgid "Could not send request to optout_url %s" msgstr "" -#: ../wallace/module_resources.py:80 +#: ../wallace/module_resources.py:110 #, python-format msgid "Resource Management called for %r, %r" msgstr "" -#: ../wallace/module_resources.py:143 +#: ../wallace/module_resources.py:174 msgid "Message is not an iTip message or does not contain any " msgstr "" -#: ../wallace/module_resources.py:151 +#: ../wallace/module_resources.py:182 msgid "iTip events attached to this message contain the " msgstr "" -#: ../wallace/module_resources.py:171 +#: ../wallace/module_resources.py:205 msgid "Not an iTip message, but sent to resource nonetheless. Reject message" msgstr "" -#: ../wallace/module_resources.py:179 -msgid "No itips, no resources, pass along" +#: ../wallace/module_resources.py:213 +#, python-format +msgid "No itips, no resources, pass along %r" msgstr "" -#: ../wallace/module_resources.py:183 -msgid "iTips, but no resources, pass along" +#: ../wallace/module_resources.py:216 +#, python-format +msgid "iTips, but no resources, pass along %r" msgstr "" -#: ../wallace/module_resources.py:215 +#: ../wallace/module_resources.py:225 #, python-format -msgid "Resources: %r" +msgid "No resource attendees matching envelope recipient %s, Reject message" msgstr "" -#: ../wallace/module_resources.py:233 +#: ../wallace/module_resources.py:234 #, python-format -msgid "Checking events in resource folder %r" +msgid "Resources: %r; %r" msgstr "" -#: ../wallace/module_resources.py:240 +#: ../wallace/module_resources.py:244 #, python-format -msgid "Mailbox for resource %r doesn't exist" +msgid "Receiving Resource: %r; %r" msgstr "" -#: ../wallace/module_resources.py:253 +#: ../wallace/module_resources.py:252 #, python-format -msgid "Fetching message UID %r from folder %r" +msgid "Recipient %r is non-participant, ignoring message" msgstr "" -#: ../wallace/module_resources.py:292 +#: ../wallace/module_resources.py:279 #, python-format -msgid "Event %r conflicts with event " +msgid "Accept invitation for individual resource %r / %r" msgstr "" -#: ../wallace/module_resources.py:305 +#: ../wallace/module_resources.py:308 #, python-format -msgid "start: %r, end: %r, total: %r, messages: %r" +msgid "Delegate invitation for resource collection %r to %r" msgstr "" -#: ../wallace/module_resources.py:312 +#: ../wallace/module_resources.py:340 +#, python-format +msgid "Failed to read resource calendar for %r: %r" +msgstr "" + +#: ../wallace/module_resources.py:350 #, python-format msgid "Polling for resource %r" msgstr "" -#: ../wallace/module_resources.py:316 +#: ../wallace/module_resources.py:353 #, python-format msgid "Resource %r has been popped from the list" msgstr "" -#: ../wallace/module_resources.py:323 +#: ../wallace/module_resources.py:357 msgid "Resource is a collection" msgstr "" -#: ../wallace/module_resources.py:371 ../wallace/module_resources.py:421 +#: ../wallace/module_resources.py:368 #, python-format -msgid "Adding event to %r" +msgid "Removed conflicting resources from %r: (%r) => %r" msgstr "" -#: ../wallace/module_resources.py:470 +#: ../wallace/module_resources.py:380 #, python-format -msgid "Method %r not really interesting for us." +msgid "Conflicting events: %r for resource %r" msgstr "" -#: ../wallace/module_resources.py:478 +#: ../wallace/module_resources.py:397 #, python-format -msgid "Raw iTip payload: %s" +msgid "Delegate to another resource collection member: %r to %r" msgstr "" -#: ../wallace/module_resources.py:488 -msgid "Could not read iTip from message." +#: ../wallace/module_resources.py:459 +#, python-format +msgid "Checking events in resource folder %r" msgstr "" -#: ../wallace/module_resources.py:510 -msgid "iTip event without a start" +#: ../wallace/module_resources.py:475 +#, python-format +msgid "Fetching message UID %r from folder %r" msgstr "" -#. end if c.name == "VEVENT" -#. end for c in cal.walk() -#. end if part.get_content_type() == "text/calendar" -#. end for part in message.walk() -#. if message.is_multipart() -#: ../wallace/module_resources.py:540 -msgid "Message is not an iTip message (non-multipart message)" +#: ../wallace/module_resources.py:498 +#, python-format +msgid "Event %r conflicts with event %r" msgstr "" -#: ../wallace/module_resources.py:561 +#: ../wallace/module_resources.py:525 #, python-format -msgid "Checking if email address %r belongs to a resource (collection)" +msgid "Adding event to %r: %r" msgstr "" -#: ../wallace/module_resources.py:572 ../wallace/module_resources.py:646 -#: ../wallace/module_resources.py:696 +#: ../wallace/module_resources.py:573 #, python-format -msgid "No resource (collection) records found for %r" +msgid "Failed to save event to resource calendar at %r: %r" msgstr "" -#: ../wallace/module_resources.py:580 ../wallace/module_resources.py:654 -#: ../wallace/module_resources.py:704 +#: ../wallace/module_resources.py:590 +#, python-format +msgid "Delete resource calendar object %r in %r: %r" +msgstr "" + +#: ../wallace/module_resources.py:633 +#, python-format +msgid "Checking if email address %r belongs to a resource (collection)" +msgstr "" + +#: ../wallace/module_resources.py:641 ../wallace/module_resources.py:709 +#: ../wallace/module_resources.py:743 #, python-format msgid "Resource record(s): %r" msgstr "" -#: ../wallace/module_resources.py:586 ../wallace/module_resources.py:661 -#: ../wallace/module_resources.py:711 +#: ../wallace/module_resources.py:643 ../wallace/module_resources.py:711 +#: ../wallace/module_resources.py:746 +#, python-format +msgid "No resource (collection) records found for %r" +msgstr "" + +#: ../wallace/module_resources.py:647 ../wallace/module_resources.py:715 +#: ../wallace/module_resources.py:750 #, python-format msgid "Resource record: %r" msgstr "" -#: ../wallace/module_resources.py:605 +#: ../wallace/module_resources.py:667 #, python-format msgid "Raw itip_events: %r" msgstr "" -#: ../wallace/module_resources.py:613 +#: ../wallace/module_resources.py:675 #, python-format msgid "Raw set of attendees: %r" msgstr "" -#: ../wallace/module_resources.py:621 +#: ../wallace/module_resources.py:683 #, python-format msgid "Raw set of resources: %r" msgstr "" -#: ../wallace/module_resources.py:635 +#: ../wallace/module_resources.py:702 #, python-format msgid "Checking if attendee %r is a resource (collection)" msgstr "" -#: ../wallace/module_resources.py:668 ../wallace/module_resources.py:714 +#: ../wallace/module_resources.py:718 ../wallace/module_resources.py:752 msgid "Resource reservation made but no resource records found" msgstr "" -#: ../wallace/module_resources.py:686 +#: ../wallace/module_resources.py:737 #, python-format msgid "Checking if resource %r is a resource (collection)" msgstr "" -#: ../wallace/module_resources.py:718 +#: ../wallace/module_resources.py:755 msgid "The following resources are being referred to in the " msgstr "" +#: ../wallace/module_resources.py:894 +#, python-format +msgid "" +"\n" +" *** This is an automated response, please do not reply! ***\n" +"\n" +" Your reservation was delegated to \"%s\" which is available for the requested time.\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:905 +#, python-format +msgid "" +"\n" +" *** This is an automated response, please do not reply! ***\n" +" \n" +" We hereby inform you that your reservation was %s.\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:912 +#, python-format +msgid "" +"\n" +" If you have questions about this reservation, please contact\n" +" %s <%s> %s\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:941 +#, python-format +msgid "Sending booking notification for event %r to %r from %r" +msgstr "" + +#: ../wallace/module_resources.py:954 +msgid "failed" +msgstr "" + +#: ../wallace/module_resources.py:973 +#, python-format +msgid "" +"\n" +" The resource booking for %(resource)s by %(orgname)s <%(orgemail)s> has been %(status)s for %(date)s.\n" +"\n" +" *** This is an automated message, sent to you as the resource owner. ***\n" +" " +msgstr "" + +#: ../wallace/module_resources.py:979 +#, python-format +msgid "" +"\n" +" A reservation request for %(resource)s could not be processed automatically.\n" +" Please contact %(orgname)s <%(orgemail)s> who requested this resource for %(date)s. Subject: %(summary)s.\n" +"\n" +" *** This is an automated message, sent to you as the resource owner. ***\n" +" " +msgstr "" + #. This is a nested module #: ../wallace/modules.py:97 #, python-format msgid "Module Group: %s" msgstr "" -#: ../wallace/modules.py:108 ../wallace/modules.py:113 -msgid "No such module." +#: ../wallace/modules.py:108 +#, python-format +msgid "No such module %r in modules %r (1)." +msgstr "" + +#: ../wallace/modules.py:113 +#, python-format +msgid "No such module %r in modules %r (2)." msgstr "" #: ../wallace/modules.py:119 @@ -2353,33 +3449,33 @@ msgid "Deferring message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:133 +#: ../wallace/modules.py:134 #, python-format msgid "The time when the message was sent: %r" msgstr "" -#: ../wallace/modules.py:134 +#: ../wallace/modules.py:135 #, python-format msgid "The time now: %r" msgstr "" -#: ../wallace/modules.py:135 +#: ../wallace/modules.py:136 #, python-format msgid "The time delta: %r" msgstr "" #. TODO: Send NDR back to user -#: ../wallace/modules.py:139 +#: ../wallace/modules.py:140 #, python-format msgid "Message in file %s older then 5 days, deleting" msgstr "" -#: ../wallace/modules.py:164 +#: ../wallace/modules.py:165 #, python-format msgid "Rejecting message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:185 +#: ../wallace/modules.py:186 #, python-format msgid "" "This is the email system Wallace at %s.\n" @@ -2394,19 +3490,29 @@ "recipients.\n" msgstr "" -#: ../wallace/modules.py:200 +#: ../wallace/modules.py:201 #, python-format msgid "" "X-Wallace-Module: %s\n" "X-Wallace-Result: REJECT\n" msgstr "" -#: ../wallace/modules.py:253 +#: ../wallace/modules.py:260 #, python-format msgid "Accepting message in %s (by module %s)" msgstr "" -#: ../wallace/modules.py:326 +#: ../wallace/modules.py:262 +#, python-format +msgid "Accepting message in: %r" +msgstr "" + +#: ../wallace/modules.py:269 +#, python-format +msgid "recipients: %r" +msgstr "" + +#: ../wallace/modules.py:347 #, python-format msgid "Module '%s' already registered" msgstr ""
View file
pykolab-0.7.tar.gz/pykolab.spec
Changed
@@ -400,6 +400,6 @@ %attr(0700,%{kolab_user},%{kolab_group}) %dir %{_var}/spool/pykolab/wallace %changelog -* Wed Jun 25 2014 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> 0.7-0.1 +* Wed Jul 30 2014 Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> 0.7-0.1 - Initial package of new upstream version
View file
pykolab-0.7.tar.gz/pykolab/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # """
View file
pykolab-0.7.tar.gz/pykolab/auth/__init__.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging @@ -205,7 +205,10 @@ return result def find_user(self, attr, value, **kw): - return self._auth._find_user(attr, value, **kw) + return self._auth.search_entry_by_attribute(attr, value, **kw) + + def find_user_dn(self, login, kolabuser=False): + return self._auth._find_user_dn(login, kolabuser); def list_domains(self, domain=None): """
View file
pykolab-0.7.tar.gz/pykolab/auth/ldap/__init__.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime @@ -1987,16 +1987,17 @@ else: return _type - def _find_user_dn(self, login, realm): + def _find_user_dn(self, login, kolabuser=False): """ - Find the distinguished name (DN) for an entry in LDAP. + Find the distinguished name (DN) for a (Kolab) user entry in LDAP. """ + conf_prefix = 'kolab_' if kolabuser else '' domain_root_dn = self._kolab_domain_root_dn(self.domain) - base_dn = self.config_get('user_base_dn') - if base_dn == None: - base_dn = self.config_get('base_dn') + user_base_dn = self.config_get(conf_prefix + 'user_base_dn') + if user_base_dn == None: + user_base_dn = self.config_get('base_dn') auth_attrs = self.config_get_list('auth_attributes') @@ -2004,18 +2005,21 @@ for auth_attr in auth_attrs: auth_search_filter.append('(%s=%s)' % (auth_attr,login)) - auth_search_filter.append( - '(%s=%s@%s)' % ( - auth_attr, - login, - self.domain - ) - ) + if not '@' in login: + auth_search_filter.append( + '(%s=%s@%s)' % ( + auth_attr, + login, + self.domain + ) + ) auth_search_filter.append(')') auth_search_filter = ''.join(auth_search_filter) + user_filter = self.config_get(conf_prefix + 'user_filter') + search_filter = "(&%s%s)" % ( auth_search_filter, user_filter @@ -2700,9 +2704,13 @@ except Exception, errmsg: log.error(_("An error occured using %s: %r") % (supported_control, errmsg)) + import traceback + if conf.debuglevel > 8: - import traceback traceback.print_exc() + + log.error(_("%s") % (traceback.format_exc())) + continue return _results
View file
pykolab-0.7.tar.gz/pykolab/auth/ldap/auth_cache.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime
View file
pykolab-0.7.tar.gz/pykolab/auth/ldap/cache.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime @@ -63,7 +63,7 @@ self.uniqueid = uniqueid self.result_attribute = result_attr - modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format') + modifytimestamp_format = conf.get_raw('ldap', 'modifytimestamp_format') if modifytimestamp_format == None: modifytimestamp_format = "%Y%m%d%H%M%SZ" @@ -95,7 +95,7 @@ ## def delete_entry(domain, entry): - result_attribute = conf.get('cyrus-sasl', 'result_attribute') + result_attribute = conf.get_raw('cyrus-sasl', 'result_attribute') db = init_db(domain) _entry = db.query(Entry).filter_by(uniqueid=entry['id']).first() @@ -105,7 +105,7 @@ db.commit() def get_entry(domain, entry, update=True): - result_attribute = conf.get('cyrus-sasl', 'result_attribute') + result_attribute = conf.get_raw('cyrus-sasl', 'result_attribute') _entry = None @@ -139,7 +139,7 @@ db.commit() _entry = db.query(Entry).filter_by(uniqueid=entry['id']).first() else: - modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format') + modifytimestamp_format = conf.get_raw('ldap', 'modifytimestamp_format') if modifytimestamp_format == None: modifytimestamp_format = "%Y%m%d%H%M%SZ" @@ -188,7 +188,7 @@ db = init_db(domain) last_change = db.query(Entry).order_by(desc(Entry.last_change)).first() - modifytimestamp_format = conf.get('ldap', 'modifytimestamp_format') + modifytimestamp_format = conf.get_raw('ldap', 'modifytimestamp_format') if modifytimestamp_format == None: modifytimestamp_format = "%Y%m%d%H%M%SZ"
View file
pykolab-0.7.tar.gz/pykolab/base.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import ldap
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_acl_cleanup.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_add_alias.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_add_domain.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_add_user.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_add_user_subscription.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_count_domain_mailboxes.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_create_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_delete_domain.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_delete_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_delete_mailbox_acl.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_delete_message.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_export_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_find_domain.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_deleted_mailboxes.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_domain_mailboxes.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_domains.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_mailbox_acls.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_mailbox_metadata.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_mailboxes.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_messages.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_ous.py
Added
@@ -0,0 +1,39 @@ +# -*- 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, 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 commands + +import pykolab + +from pykolab import utils +from pykolab.translate import _ + +log = pykolab.getLogger('pykolab.cli') +conf = pykolab.getConf() + +def __init__(): + commands.register('list_ous', execute, description="List organizational units.") + +def execute(*args, **kw): + from pykolab import wap_client + + wap_client.authenticate(username=conf.get("ldap", "bind_dn"), password=conf.get("ldap", "bind_pw")) + + ous = wap_client.ous_list() + print '\n'.join(ous['list'].keys())
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_quota.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_list_user_subscriptions.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_mailbox_cleanup.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_remove_mailaddress.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_remove_user_subscription.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_rename_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_server_info.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_set_language.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_set_mail.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_set_mailbox_acl.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_set_mailbox_metadata.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_sync.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_sync_mailhost_attrs.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_transfer_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_undelete_mailbox.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/cmd_user_info.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import commands
View file
pykolab-0.7.tar.gz/pykolab/cli/commands.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/cli/sieve/cmd_list.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/sieve/cmd_put.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/sieve/cmd_refresh.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/sieve/cmd_test.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/telemetry/cmd_examine_command_issue.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/telemetry/cmd_examine_session.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/telemetry/cmd_expire_sessions.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/telemetry/cmd_list_sessions.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/cli/wap/cmd_system_capabilities.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/pykolab/cli/wap/cmd_user_types_list.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/conf/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/pykolab/conf/defaults.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/pykolab/conf/entitlement.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from ConfigParser import ConfigParser
View file
pykolab-0.7.tar.gz/pykolab/constants.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import math
View file
pykolab-0.7.tar.gz/pykolab/constants.py.in
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import math
View file
pykolab-0.7.tar.gz/pykolab/errors.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from pykolab.translate import _
View file
pykolab-0.7.tar.gz/pykolab/imap/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # @@ -211,8 +211,7 @@ folder_path = self.folder_utf7(folder_path) if not server == None: - if not self._imap.has_key(server): - self.connect(server=server) + self.connect(server=server) try: self._imap[server].cm(folder_path, partition=partition)
View file
pykolab-0.7.tar.gz/pykolab/imap/cyrus.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import cyruslib
View file
pykolab-0.7.tar.gz/pykolab/logger.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import grp
View file
pykolab-0.7.tar.gz/pykolab/plugins/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/pykolab/plugins/defaultfolders/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/plugins/dynamicquota/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/plugins/recipientpolicy/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/plugins/sievemgmt/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/setup/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/setup/components.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_freebusy.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from ConfigParser import RawConfigParser
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_imap.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from augeas import Augeas
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_kolabd.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_ldap.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import ldap
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_mta.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from augeas import Augeas
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_mysql.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_php.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from augeas import Augeas
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_roundcube.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # from Cheetah.Template import Template
View file
pykolab-0.7.tar.gz/pykolab/setup/setup_syncroton.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/telemetry.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/pykolab/translate.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # try: @@ -26,7 +26,10 @@ import os N_ = lambda x: x -_ = lambda x: gettext.ldgettext(domain, x) +_ = lambda x: current.lgettext(x) + +localedir = '/usr/local/share/locale' +current = gettext.translation(domain, localedir, fallback=True) def getDefaultLangs(): languages = [] @@ -45,3 +48,16 @@ if nelang not in nelangs: nelangs.append(nelang) return nelangs + +def setUserLanguage(lang): + global current + + langs = [] + for l in gettext._expand_lang(lang): + if l not in langs: + langs.append(l) + + try: + current = gettext.translation(domain, localedir, languages=langs, fallback=True) + except: + pass
View file
pykolab-0.7.tar.gz/pykolab/translit.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import pykolab
View file
pykolab-0.7.tar.gz/pykolab/utils.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import base64
View file
pykolab-0.7.tar.gz/pykolab/wap_client/__init__.py
Changed
@@ -69,6 +69,7 @@ if response.has_key('session_token'): session_id = response['session_token'] + return True def connect(): global conn @@ -288,8 +289,17 @@ def group_types_list(): return request('GET', 'group_types.list') -def groups_list(): - return request('GET', 'groups.list') +def groups_list(params={}): + return request('POST', 'groups.list', post=json.dumps(params)) + +def ou_add(params={}): + return request('POST', 'ou.add', post=json.dumps(params)) + +def ou_delete(params={}): + return request('POST', 'ou.delete', post=json.dumps(params)) + +def ous_list(params={}): + return request('POST', 'ous.list', post=json.dumps(params)) def request(method, api_uri, get=None, post=None, headers={}): response_data = request_raw(method, api_uri, get, post, headers) @@ -312,8 +322,6 @@ if conf.debuglevel > 8: conn.set_debuglevel(9) - conn.set_debuglevel(9) - if not get == None: _get = "?%s" % (urllib.urlencode(get)) else: @@ -527,8 +535,8 @@ def user_types_list(): return request('GET', 'user_types.list') -def users_list(): - return request('GET', 'users.list') +def users_list(params={}): + return request('POST', 'users.list', post=json.dumps(params)) def resource_types_list(): return request('GET', 'resource_types.list')
View file
pykolab-0.7.tar.gz/pykolab/xml/__init__.py
Changed
@@ -1,14 +1,17 @@ from attendee import Attendee from attendee import InvalidAttendeeParticipantStatusError +from attendee import participant_status_label from contact import Contact from contact_reference import ContactReference +from recurrence_rule import RecurrenceRule from event import Event from event import EventIntegrityError from event import InvalidEventDateError from event import event_from_ical from event import event_from_string +from event import event_from_message from utils import to_dt @@ -17,6 +20,7 @@ "Contact", "ContactReference", "Event", + "RecurrenceRule", "event_from_ical", "event_from_string", "to_dt",
View file
pykolab-0.7.tar.gz/pykolab/xml/attendee.py
Changed
@@ -1,9 +1,30 @@ import kolabformat from pykolab.translate import _ +from pykolab.translate import N_ from contact_reference import ContactReference +participant_status_labels = { + "NEEDS-ACTION": N_("Needs Action"), + "ACCEPTED": N_("Accepted"), + "DECLINED": N_("Declined"), + "TENTATIVE": N_("Tentatively Accepted"), + "DELEGATED": N_("Delegated"), + "COMPLETED": N_("Completed"), + "IN-PROCESS": N_("In Process"), + # support integer values, too + kolabformat.PartNeedsAction: N_("Needs Action"), + kolabformat.PartAccepted: N_("Accepted"), + kolabformat.PartDeclined: N_("Declined"), + kolabformat.PartTentative: N_("Tentatively Accepted"), + kolabformat.PartDelegated: N_("Delegated"), + } + +def participant_status_label(status): + return _(participant_status_labels[status]) if participant_status_labels.has_key(status) else _(status) + + class Attendee(kolabformat.Attendee): cutype_map = { "INDIVIDUAL": kolabformat.CutypeIndividual, @@ -35,6 +56,13 @@ "FALSE": False, } + properties_map = { + 'role': 'get_role', + 'rsvp': 'rsvp', + 'partstat': 'get_participant_status', + 'cutype': 'get_cutype', + } + def __init__( self, email, @@ -76,6 +104,12 @@ if not participant_status == None: self.set_participant_status(participant_status) + def copy_from(self, obj): + if isinstance(obj, kolabformat.Attendee): + kolabformat.Attendee.__init__(self, obj) + self.contactreference = ContactReference(obj.contact()) + self.email = self.contactreference.get_email() + def delegate_from(self, delegators): crefs = [] @@ -117,8 +151,11 @@ self.setDelegatedTo(list(set(crefs))) - def get_cutype(self): - return self.cutype() + def get_cutype(self, translated=False): + cutype = self.cutype() + if translated: + return self._translate_value(cutype, self.cutype_map) + return cutype def get_delegated_from(self): return self.delegatedFrom() @@ -132,15 +169,30 @@ def get_name(self): return self.contactreference.get_name() - def get_participant_status(self): - return self.partStat() + def get_displayname(self): + name = self.contactreference.get_name() + email = self.contactreference.get_email() + return "%s <%s>" % (name, email) if name is not None else email + + def get_participant_status(self, translated=False): + partstat = self.partStat() + if translated: + return self._translate_value(partstat, self.participant_status_map) + return partstat - def get_role(self): - return self.role() + def get_role(self, translated=False): + role = self.role() + if translated: + return self._translate_value(role, self.role_map) + return role def get_rsvp(self): return self.rsvp() + def _translate_value(self, val, map): + name_map = dict([(v, k) for (k, v) in map.iteritems()]) + return name_map[val] if name_map.has_key(val) else 'UNKNOWN' + def set_cutype(self, cutype): if cutype in self.cutype_map.keys(): self.setCutype(self.cutype_map[cutype]) @@ -151,6 +203,7 @@ def set_name(self, name): self.contactreference.set_name(name) + self.setContact(self.contactreference) def set_participant_status(self, participant_status): if participant_status in self.participant_status_map.keys(): @@ -171,6 +224,22 @@ def set_rsvp(self, rsvp): self.setRSVP(rsvp) + def to_dict(self): + data = self.contactreference.to_dict() + data.pop('type', None) + + for p, getter in self.properties_map.iteritems(): + val = None + args = {} + if hasattr(self, getter): + if getter.startswith('get_'): + args = dict(translated=True) + val = getattr(self, getter)(**args) + if val is not None: + data[p] = val + + return data + def __str__(self): return self.email
View file
pykolab-0.7.tar.gz/pykolab/xml/contact.py
Changed
@@ -39,5 +39,9 @@ def set_name(self, name): self.setName(name) + def to_ditc(self): + # TODO: implement this + return dict(name=self.name()) + def __str__(self): return kolabformat.writeContact(self)
View file
pykolab-0.7.tar.gz/pykolab/xml/contact_reference.py
Changed
@@ -11,9 +11,18 @@ """ class ContactReference(kolabformat.ContactReference): + properties_map = { + 'email': 'email', + 'name': 'name', + 'type': 'type', + 'uid': 'uid', + } + def __init__(self, email=None): if email == None: kolabformat.ContactReference.__init__(self) + elif isinstance(email, kolabformat.ContactReference): + kolabformat.ContactReference.__init__(self, email.email(), email.name(), email.uid()) else: kolabformat.ContactReference.__init__(self, email) @@ -31,3 +40,15 @@ def set_name(self, name): self.setName(name) + + def to_dict(self): + data = dict() + + for p, getter in self.properties_map.iteritems(): + val = None + if hasattr(self, getter): + val = getattr(self, getter)() + if val is not None: + data[p] = val + + return data
View file
pykolab-0.7.tar.gz/pykolab/xml/event.py
Changed
@@ -6,15 +6,20 @@ import pytz import time import uuid +import base64 +import re import pykolab from pykolab import constants from pykolab import utils from pykolab.xml import utils as xmlutils +from pykolab.xml import participant_status_label from pykolab.translate import _ +from os import path from attendee import Attendee from contact_reference import ContactReference +from recurrence_rule import RecurrenceRule log = pykolab.getLogger('pykolab.xml_event') @@ -24,6 +29,21 @@ def event_from_string(string): return Event(from_string=string) +def event_from_message(message): + event = None + if message.is_multipart(): + for part in message.walk(): + if part.get_content_type() == "application/calendar+xml": + payload = part.get_payload(decode=True) + event = event_from_string(payload) + + # append attachment parts to Event object + elif event and part.has_key('Content-ID'): + event._attachment_parts.append(part) + + return event + + class Event(object): status_map = { "TENTATIVE": kolabformat.StatusTentative, @@ -31,27 +51,81 @@ "CANCELLED": kolabformat.StatusCancelled, } + classification_map = { + "PUBLIC": kolabformat.ClassPublic, + "PRIVATE": kolabformat.ClassPrivate, + "CONFIDENTIAL": kolabformat.ClassConfidential, + } + + alarm_type_map = { + 'EMAIL': kolabformat.Alarm.EMailAlarm, + 'DISPLAY': kolabformat.Alarm.DisplayAlarm, + 'AUDIO': kolabformat.Alarm.AudioAlarm + } + + related_map = { + 'START': kolabformat.Start, + 'END': kolabformat.End + } + + properties_map = { + # property: getter + "uid": "get_uid", + "created": "get_created", + "lastmodified-date": "get_lastmodified", + "sequence": "sequence", + "classification": "get_classification", + "categories": "categories", + "start": "get_start", + "end": "get_end", + "duration": "get_duration", + "transparency": "transparency", + "rrule": "recurrenceRule", + "rdate": "recurrenceDates", + "exdate": "exceptionDates", + "recurrence-id": "recurrenceID", + "summary": "summary", + "description": "description", + "priority": "priority", + "status": "get_status", + "location": "location", + "organizer": "organizer", + "attendee": "get_attendees", + "attach": "attachments", + "url": "url", + "alarm": "alarms", + "x-custom": "customProperties", + # TODO: add to_dict() support for these + # "exception": "exceptions", + } + def __init__(self, from_ical="", from_string=""): self._attendees = [] self._categories = [] + self._attachment_parts = [] if from_ical == "": if from_string == "": self.event = kolabformat.Event() else: self.event = kolabformat.readEvent(from_string, False) + self._load_attendees() else: self.from_ical(from_ical) self.uid = self.get_uid() + def _load_attendees(self): + for a in self.event.attendees(): + self._attendees.append(Attendee(a.contact().email(), a.contact().name(), a.rsvp(), a.role(), a.partStat(), a.cutype())) + def add_attendee(self, email, name=None, rsvp=False, role=None, participant_status=None, cutype="INDIVIDUAL", params=None): attendee = Attendee(email, name, rsvp, role, participant_status, cutype, params) self._attendees.append(attendee) self.event.setAttendees(self._attendees) def add_category(self, category): - self._categories.append(category) + self._categories.append(str(category)) self.event.setCategories(self._categories) def add_exception_date(self, _datetime): @@ -97,29 +171,31 @@ # NOTE: Make sure to list(set()) or duplicates may arise for attr in list(set(event.singletons)): - if hasattr(self, 'get_ical_%s' % (attr.lower())): - exec("retval = self.get_ical_%s()" % (attr.lower())) + ical_getter = 'get_ical_%s' % (attr.lower()) + default_getter = 'get_%s' % (attr.lower()) + retval = None + if hasattr(self, ical_getter): + retval = getattr(self, ical_getter)() if not retval == None and not retval == "": event.add(attr.lower(), retval) - - elif hasattr(self, 'get_%s' % (attr.lower())): - exec("retval = self.get_%s()" % (attr.lower())) + elif hasattr(self, default_getter): + retval = getattr(self, default_getter)() if not retval == None and not retval == "": event.add(attr.lower(), retval, encode=0) # NOTE: Make sure to list(set()) or duplicates may arise for attr in list(set(event.multiple)): - if hasattr(self, 'get_ical_%s' % (attr.lower())): - exec("retval = self.get_ical_%s()" % (attr.lower())) - if isinstance(retval, list) and not len(retval) == 0: - for _retval in retval: - event.add(attr.lower(), _retval, encode=0) - - elif hasattr(self, 'get_%s' % (attr.lower())): - exec("retval = self.get_%s()" % (attr.lower())) - if isinstance(retval, list) and not len(retval) == 0: - for _retval in retval: - event.add(attr.lower(), _retval, encode=0) + ical_getter = 'get_ical_%s' % (attr.lower()) + default_getter = 'get_%s' % (attr.lower()) + retval = None + if hasattr(self, ical_getter): + retval = getattr(self, ical_getter)() + elif hasattr(self, default_getter): + retval = getattr(self, default_getter)() + + if isinstance(retval, list) and not len(retval) == 0: + for _retval in retval: + event.add(attr.lower(), _retval, encode=0) cal.add_component(event) @@ -161,12 +237,18 @@ self.event.setAttendees(self._attendees) def from_ical(self, ical): - self.event = kolabformat.Event() if hasattr(icalendar.Event, 'from_ical'): ical_event = icalendar.Event.from_ical(ical) elif hasattr(icalendar.Event, 'from_string'): ical_event = icalendar.Event.from_string(ical) + # use the libkolab calendaring bindings to load the full iCal data + if ical_event.has_key('RRULE') or ical_event.has_key('ATTACH') \ + or [part for part in ical_event.walk() if part.name == 'VALARM']: + self._xml_from_ical(ical) + else: + self.event = kolabformat.Event() + # TODO: Clause the timestamps for zulu suffix causing datetime.datetime # to fail substitution. for attr in list(set(ical_event.required)): @@ -183,13 +265,10 @@ if ical_event.has_key(attr): self.set_from_ical(attr.lower(), ical_event[attr]) - # HACK: use calendaring::EventCal::fromICal() to parse RRULEs - if ical_event.has_key('RRULE'): - from kolab.calendaring import EventCal - event_xml = EventCal() - event_xml.fromICal("BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR") - self.event.setRecurrenceRule(event_xml.recurrenceRule()) - self.event.setExceptionDates(event_xml.exceptionDates()) + def _xml_from_ical(self, ical): + from kolab.calendaring import EventCal + self.event = EventCal() + self.event.fromICal("BEGIN:VCALENDAR\nVERSION:2.0\n" + ical + "\nEND:VCALENDAR") def get_attendee_participant_status(self, attendee): return attendee.get_participant_status() @@ -229,14 +308,14 @@ return self._attendees def get_categories(self): - return self.event.categories() + return [str(c) for c in self.event.categories()] def get_classification(self): - return self.classification() + return self.event.classification() def get_created(self): try: - return xmlutils.from_cdatetime(self.event.created(), False) + return xmlutils.from_cdatetime(self.event.created(), True) except ValueError: return datetime.datetime.now() @@ -265,9 +344,50 @@ dt = self.get_start() + duration return dt + def get_date_text(self, date_format='%Y-%m-%d', time_format='%H:%M %Z'): + start = self.get_start() + end = self.get_end() + all_day = not hasattr(start, 'date') + start_date = start.date() if not all_day else start + end_date = end.date() if not all_day else end + + if start_date == end_date: + end_format = time_format + else: + end_format = date_format + " " + time_format + + if all_day: + time_format = '' + if start_date == end_date: + return start.strftime(date_format) + + return "%s - %s" % (start.strftime(date_format + " " + time_format), end.strftime(end_format)) + def get_exception_dates(self): return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates()) + def get_attachments(self): + return self.event.attachments() + + def get_attachment_data(self, i): + vattach = self.event.attachments() + if i < len(vattach): + attachment = vattach[i] + uri = attachment.uri() + if uri and uri[0:4] == 'cid:': + # get data from MIME part with matching content-id + cid = '<' + uri[4:] + '>' + for p in self._attachment_parts: + if p['Content-ID'] == cid: + return p.get_payload(decode=True) + else: + return attachment.data() + + return None + + def get_alarms(self): + return self.event.alarms() + def get_ical_attendee(self): # TODO: Formatting, aye? See also the example snippet: # @@ -353,7 +473,11 @@ return self.get_created() def get_ical_dtend(self): - return self.get_end() + dtend = self.get_end() + # shift end by one day on all-day events + if not hasattr(dtend, 'hour'): + dtend = dtend + datetime.timedelta(days=1) + return dtend def get_ical_dtstamp(self): try: @@ -382,12 +506,14 @@ if status in self.status_map.keys(): return status - if status in self.status_map.values(): - return [k for k, v in self.status_map.iteritems() if v == status][0] + return self._translate_value(status, self.status_map) def get_ical_sequence(self): return str(self.event.sequence()) if self.event.sequence() else None + def get_location(self): + return self.event.location() + def get_lastmodified(self): try: _datetime = self.event.lastModified() @@ -396,7 +522,7 @@ except: self.__str__() - return xmlutils.from_cdatetime(self.event.lastModified(), False) + return xmlutils.from_cdatetime(self.event.lastModified(), True) def get_organizer(self): organizer = self.event.organizer() @@ -428,7 +554,13 @@ def get_sequence(self): return self.event.sequence() - def set_attendee_participant_status(self, attendee, status): + def get_url(self): + return self.event.url() + + def get_transparency(self): + return self.event.transparency() + + def set_attendee_participant_status(self, attendee, status, rsvp=None): """ Set the participant status of an attendee to status. @@ -437,12 +569,28 @@ attendees for this event. """ attendee = self.get_attendee(attendee) - attendee.set_participant_status(status) + + if rsvp is not None: + attendee.set_rsvp(rsvp) + self.event.setAttendees(self._attendees) + def set_status(self, status): + if status in self.status_map.keys(): + self.event.setStatus(self.status_map[status]) + elif status in self.status_map.values(): + self.event.setStatus(status) + else: + raise ValueError, _("Invalid status %r") % (status) + def set_classification(self, classification): - self.event.setClassification(classification) + if classification in self.classification_map.keys(): + self.event.setClassification(self.classification_map[classification]) + elif classification in self.classification_map.values(): + self.event.setClassification(status) + else: + raise ValueError, _("Invalid classification %r") % (classification) def set_created(self, _datetime=None): if _datetime == None: @@ -451,7 +599,7 @@ self.event.setCreated(xmlutils.to_cdatetime(_datetime, False)) def set_description(self, description): - self.event.setDescription(description) + self.event.setDescription(str(description)) def set_dtstamp(self, _datetime): self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False)) @@ -478,26 +626,27 @@ self.add_exception_date(_datetime) def set_from_ical(self, attr, value): + ical_setter = 'set_ical_' + attr + default_setter = 'set_' + attr + if attr == "dtend": self.set_ical_dtend(value.dt) elif attr == "dtstart": self.set_ical_dtstart(value.dt) - elif attr == "duration": - self.set_ical_duration(value) - elif attr == "status": - self.set_ical_status(value) - elif attr == "summary": - self.set_ical_summary(value) - elif attr == "priority": - self.set_ical_priority(value) - elif attr == "sequence": - self.set_ical_sequence(value) - elif attr == "attendee": - self.set_ical_attendee(value) - elif attr == "organizer": - self.set_ical_organizer(value) - elif attr == "uid": - self.set_ical_uid(value) + elif attr == "dtstamp": + self.set_ical_dtstamp(value.dt) + elif attr == "created": + self.set_created(value.dt) + elif attr == "lastmodified": + self.set_lastmodified(value.dt) + elif attr == "categories": + self.add_category(value) + elif attr == "class": + self.set_classification(value) + elif hasattr(self, ical_setter): + getattr(self, ical_setter)(value) + elif hasattr(self, default_setter): + getattr(self, default_setter)(value) def set_ical_attendee(self, _attendee): if isinstance(_attendee, basestring): @@ -540,6 +689,9 @@ att = self.add_attendee(address, name=name, rsvp=rsvp, role=role, participant_status=partstat, cutype=cutype, params=params) def set_ical_dtend(self, dtend): + # shift end by one day on all-day events + if not hasattr(dtend, 'hour'): + dtend = dtend - datetime.timedelta(days=1) self.set_end(dtend) def set_ical_dtstamp(self, dtstamp): @@ -548,6 +700,9 @@ def set_ical_dtstart(self, dtstart): self.set_start(dtstart) + def set_ical_lastmodified(self, lastmod): + self.set_lastmodified(lastmod) + def set_ical_duration(self, value): if value.dt: duration = kolabformat.Duration(value.dt.days, 0, 0, value.dt.seconds, False) @@ -574,14 +729,6 @@ def set_ical_sequence(self, sequence): self.set_sequence(sequence) - def set_ical_status(self, status): - if status in self.status_map.keys(): - self.event.setStatus(self.status_map[status]) - elif status in self.status_map.values(): - self.event.setStatus(status) - else: - raise ValueError, _("Invalid status %r") % (status) - def set_ical_summary(self, summary): self.set_summary(str(summary)) @@ -606,7 +753,7 @@ self.event.setLastModified(xmlutils.to_cdatetime(_datetime, False)) def set_location(self, location): - self.event.setLocation(location) + self.event.setLocation(str(location)) def set_organizer(self, email, name=None): contactreference = ContactReference(email) @@ -621,6 +768,9 @@ def set_sequence(self, sequence): self.event.setSequence(int(sequence)) + def set_url(self, url): + self.event.setUrl(str(url)) + def set_recurrence(self, recurrence): self.event.setRecurrenceRule(recurrence) @@ -657,8 +807,12 @@ self.event.setSummary(summary) def set_uid(self, uid): + self.uid = uid self.event.setUid(str(uid)) + def set_transparency(self, transp): + return self.event.setTransparency(transp) + def __str__(self): event_xml = kolabformat.writeEvent(self.event) @@ -669,6 +823,72 @@ else: raise EventIntegrityError, kolabformat.errorMessage() + def to_dict(self): + data = dict() + + for p, getter in self.properties_map.iteritems(): + val = None + if hasattr(self, getter): + val = getattr(self, getter)() + elif hasattr(self.event, getter): + val = getattr(self.event, getter)() + + if isinstance(val, kolabformat.cDateTime): + val = xmlutils.from_cdatetime(val, True) + elif isinstance(val, kolabformat.vectordatetime): + val = [xmlutils.from_cdatetime(x, True) for x in val] + elif isinstance(val, kolabformat.vectors): + val = [str(x) for x in val] + elif isinstance(val, kolabformat.vectorcs): + for x in val: + data[x.identifier] = x.value + val = None + elif isinstance(val, kolabformat.ContactReference): + val = ContactReference(val).to_dict() + elif isinstance(val, kolabformat.RecurrenceRule): + val = RecurrenceRule(val).to_dict() + elif isinstance(val, kolabformat.vectorattachment): + val = [dict(fmttype=x.mimetype(), label=x.label(), uri=x.uri()) for x in val] + elif isinstance(val, kolabformat.vectoralarm): + val = [self._alarm_to_dict(x) for x in val] + elif isinstance(val, list): + val = [x.to_dict() for x in val if hasattr(x, 'to_dict')] + + if val is not None: + data[p] = val + + return data + + def _alarm_to_dict(self, alarm): + ret = dict( + action=self._translate_value(alarm.type(), self.alarm_type_map), + summary=alarm.summary(), + description=alarm.description(), + trigger=None + ) + + start = alarm.start() + if start and start.isValid(): + ret['trigger'] = xmlutils.from_cdatetime(start, True) + else: + ret['trigger'] = dict(related=self._translate_value(alarm.relativeTo(), self.related_map)) + duration = alarm.relativeStart() + if duration and duration.isValid(): + prefix = '-' if duration.isNegative() else '+' + value = prefix + "P%dW%dDT%dH%dM%dS" % ( + duration.weeks(), duration.days(), duration.hours(), duration.minutes(), duration.seconds() + ) + ret['trigger']['value'] = re.sub(r"T$", '', re.sub(r"0[WDHMS]", '', value)) + + if alarm.type() == kolabformat.Alarm.EMailAlarm: + ret['attendee'] = [ContactReference(a).to_dict() for a in alarm.attendees()] + + return ret + + def _translate_value(self, val, map): + name_map = dict([(v, k) for (k, v) in map.iteritems()]) + return name_map[val] if name_map.has_key(val) else 'UNKNOWN' + def to_message(self): from email.MIMEMultipart import MIMEMultipart from email.MIMEBase import MIMEBase @@ -706,6 +926,39 @@ msg["Subject"] = self.get_uid() + # extract attachment data into separate MIME parts + vattach = self.event.attachments() + i = 0 + for attach in vattach: + if attach.uri(): + continue + + mimetype = attach.mimetype() + (primary, seconday) = mimetype.split('/') + name = attach.label() + if not name: + name = 'unknown.x' + + (basename, suffix) = path.splitext(name) + t = datetime.datetime.now() + cid = "%s.%s.%s%s" % (basename, time.mktime(t.timetuple()), t.microsecond + len(self._attachment_parts), suffix) + + p = MIMEBase(primary, seconday) + p.add_header('Content-Disposition', 'attachment', filename=name) + p.add_header('Content-Transfer-Encoding', 'base64') + p.add_header('Content-ID', '<' + cid + '>') + p.set_payload(base64.b64encode(attach.data())) + + self._attachment_parts.append(p) + + # modify attachment object + attach.setData('', mimetype) + attach.setUri('cid:' + cid, mimetype) + vattach[i] = attach + i += 1 + + self.event.setAttachments(vattach) + part.set_payload(str(self)) part.add_header('Content-Disposition', 'attachment; filename="kolab.xml"') @@ -713,6 +966,10 @@ msg.attach(part) + # append attachment parts + for p in self._attachment_parts: + msg.attach(p) + return msg def to_message_itip(self, from_address, method="REQUEST", participant_status="ACCEPTED", subject=None, message_text=None): @@ -725,6 +982,7 @@ msg = MIMEMultipart() msg_from = None + attendees = None if method == "REPLY": # TODO: Make user friendly name <email> @@ -737,6 +995,7 @@ if attendee.get_email() == from_address: # Only the attendee is supposed to be listed in a reply attendee.set_participant_status(participant_status) + attendee.set_rsvp(False) self._attendees = [attendee] self.event.setAttendees(self._attendees) @@ -779,7 +1038,7 @@ msg['Date'] = formatdate(localtime=True) if subject is None: - subject = _("Reservation Request for %s was %s") % (self.get_summary(), _(participant_status)) + subject = _("Invitation for %s was %s") % (self.get_summary(), participant_status_label(participant_status)) msg["Subject"] = subject @@ -798,6 +1057,12 @@ msg.attach(part) + # restore the original list of attendees + # attendees being reduced to the replying attendee above + if attendees is not None: + self._attendees = attendees + self.event.setAttendees(self._attendees) + return msg def is_recurring(self):
View file
pykolab-0.7.tar.gz/pykolab/xml/recurrence_rule.py
Added
@@ -0,0 +1,118 @@ +import kolabformat +from pykolab.xml import utils as xmlutils + +""" + def setFrequency(self, *args): return _kolabformat.RecurrenceRule_setFrequency(self, *args) + def frequency(self): return _kolabformat.RecurrenceRule_frequency(self) + def setWeekStart(self, *args): return _kolabformat.RecurrenceRule_setWeekStart(self, *args) + def weekStart(self): return _kolabformat.RecurrenceRule_weekStart(self) + def setEnd(self, *args): return _kolabformat.RecurrenceRule_setEnd(self, *args) + def end(self): return _kolabformat.RecurrenceRule_end(self) + def setCount(self, *args): return _kolabformat.RecurrenceRule_setCount(self, *args) + def count(self): return _kolabformat.RecurrenceRule_count(self) + def setInterval(self, *args): return _kolabformat.RecurrenceRule_setInterval(self, *args) + def interval(self): return _kolabformat.RecurrenceRule_interval(self) + def setBysecond(self, *args): return _kolabformat.RecurrenceRule_setBysecond(self, *args) + def bysecond(self): return _kolabformat.RecurrenceRule_bysecond(self) + def setByminute(self, *args): return _kolabformat.RecurrenceRule_setByminute(self, *args) + def byminute(self): return _kolabformat.RecurrenceRule_byminute(self) + def setByhour(self, *args): return _kolabformat.RecurrenceRule_setByhour(self, *args) + def byhour(self): return _kolabformat.RecurrenceRule_byhour(self) + def setByday(self, *args): return _kolabformat.RecurrenceRule_setByday(self, *args) + def byday(self): return _kolabformat.RecurrenceRule_byday(self) + def setBymonthday(self, *args): return _kolabformat.RecurrenceRule_setBymonthday(self, *args) + def bymonthday(self): return _kolabformat.RecurrenceRule_bymonthday(self) + def setByyearday(self, *args): return _kolabformat.RecurrenceRule_setByyearday(self, *args) + def byyearday(self): return _kolabformat.RecurrenceRule_byyearday(self) + def setByweekno(self, *args): return _kolabformat.RecurrenceRule_setByweekno(self, *args) + def byweekno(self): return _kolabformat.RecurrenceRule_byweekno(self) + def setBymonth(self, *args): return _kolabformat.RecurrenceRule_setBymonth(self, *args) + def bymonth(self): return _kolabformat.RecurrenceRule_bymonth(self) + def isValid(self): return _kolabformat.RecurrenceRule_isValid(self) +""" + +class RecurrenceRule(kolabformat.RecurrenceRule): + frequency_map = { + None: kolabformat.RecurrenceRule.FreqNone, + "YEARLY": kolabformat.RecurrenceRule.Yearly, + "MONTHLY": kolabformat.RecurrenceRule.Monthly, + "WEEKLY": kolabformat.RecurrenceRule.Weekly, + "DAILY": kolabformat.RecurrenceRule.Daily, + "HOURLY": kolabformat.RecurrenceRule.Hourly, + "MINUTELY": kolabformat.RecurrenceRule.Minutely, + "SECONDLY": kolabformat.RecurrenceRule.Secondly + } + + weekday_map = { + "MO": kolabformat.Monday, + "TU": kolabformat.Tuesday, + "WE": kolabformat.Wednesday, + "TH": kolabformat.Thursday, + "FR": kolabformat.Friday, + "SA": kolabformat.Saturday, + "SU": kolabformat.Sunday + } + + properties_map = { + 'frequency': 'get_frequency', + 'interval': 'interval', + 'count': 'count', + 'until': 'end', + 'bymonth': 'bymonth', + 'byday': 'byday', + 'bymonthday':'bymonthday', + 'byyearday': 'byyearday', + 'byweekno': 'byweekno', + 'byhour': 'byhour', + 'byminute': 'byminute', + 'wkst': 'get_weekstart' + } + + def __init__(self, rrule=None): + if rrule == None: + kolabformat.RecurrenceRule.__init__(self) + else: + kolabformat.RecurrenceRule.__init__(self, rrule) + + def get_frequency(self, translated=False): + freq = self.frequency() + if translated: + return self._translate_value(freq, self.frequency_map) + return freq + + def get_weekstart(self, translated=False): + wkst = self.weekStart() + if translated: + return self._translate_value(wkst, self.weekday_map) + return wkst + + def _translate_value(self, val, map): + name_map = dict([(v, k) for (k, v) in map.iteritems()]) + return name_map[val] if name_map.has_key(val) else 'UNKNOWN' + + def to_dict(self): + if not self.isValid() or self.frequency() == kolabformat.RecurrenceRule.FreqNone: + return None + + data = dict() + + for p, getter in self.properties_map.iteritems(): + val = None + args = {} + if hasattr(self, getter): + if getter.startswith('get_'): + args = dict(translated=True) + if hasattr(self, getter): + val = getattr(self, getter)(**args) + if isinstance(val, kolabformat.cDateTime): + val = xmlutils.from_cdatetime(val, True) + elif isinstance(val, kolabformat.vectori): + val = ",".join([int(v) for x in val]) + elif isinstance(val, kolabformat.vectordaypos): + val = ",".join(["%s%s" % (str(x.occurence()) if x.occurence() != 0 else '', self._translate_value(x.weekday(), self.weekday_map)) for x in val]) + if val is not None: + data[p] = val + + return data + +
View file
pykolab-0.7.tar.gz/saslauthd.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/saslauthd/__init__.py
Changed
@@ -2,18 +2,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # """
View file
pykolab-0.7.tar.gz/setup-kolab.py
Changed
@@ -5,18 +5,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import logging
View file
pykolab-0.7.tar.gz/tests/functional/resource_func.py
Changed
@@ -4,7 +4,7 @@ conf = pykolab.getConf() -def resource_add(type, cn, members=None, owner=None): +def resource_add(type, cn, members=None, owner=None, **kw): if type == None or type == '': raise Exception @@ -18,6 +18,8 @@ 'owner': owner } + resource_details.update(kw) + result = wap_client.authenticate(conf.get('ldap', 'bind_dn'), conf.get('ldap', 'bind_pw'), conf.get('kolab', 'primary_domain')) type_id = 0
View file
pykolab-0.7.tar.gz/tests/functional/test_wallace/test_005_resource_add.py
Changed
@@ -29,8 +29,8 @@ funcs.purge_resources() self.audi = funcs.resource_add("car", "Audi A4") self.passat = funcs.resource_add("car", "VW Passat") - self.boxter = funcs.resource_add("car", "Porsche Boxter S") - self.cars = funcs.resource_add("collection", "Company Cars", [ self.audi['dn'], self.passat['dn'], self.boxter['dn'] ]) + self.boxter = funcs.resource_add("car", "Porsche Boxter S", kolabinvitationpolicy='ACT_ACCEPT_AND_NOTIFY') + self.cars = funcs.resource_add("collection", "Company Cars", [ self.audi['dn'], self.passat['dn'], self.boxter['dn'] ], kolabinvitationpolicy='ACT_ACCEPT') from tests.functional.synchronize import synchronize_once synchronize_once() @@ -56,3 +56,16 @@ attrs = auth.get_entry_attributes(None, self.cars['dn'], ['*']) self.assertIn('groupofuniquenames', attrs['objectclass']) self.assertEqual(len(attrs['uniquemember']), 3) + self.assertEqual(attrs['kolabinvitationpolicy'], 'ACT_ACCEPT') + + def test_003_get_resource_records(self): + resource_dns = module_resources.resource_record_from_email_address(self.cars['mail']) + self.assertEqual(resource_dns[0], self.cars['dn']) + + resources = module_resources.get_resource_records(resource_dns) + self.assertEqual(len(resources), 4) + + # check for (inherited) kolabinvitationpolicy values (bitmasks) + self.assertEqual(resources[self.cars['dn']]['kolabinvitationpolicy'], [module_resources.ACT_ACCEPT]) + self.assertEqual(resources[self.audi['dn']]['kolabinvitationpolicy'], [module_resources.ACT_ACCEPT]) + self.assertEqual(resources[self.boxter['dn']]['kolabinvitationpolicy'], [module_resources.ACT_ACCEPT_AND_NOTIFY])
View file
pykolab-0.7.tar.gz/tests/functional/test_wallace/test_005_resource_invitation.py
Changed
@@ -8,6 +8,9 @@ from pykolab.imap import IMAP from wallace import module_resources +from pykolab.translate import _ +from pykolab.xml import event_from_message +from pykolab.xml import participant_status_label from email import message_from_string from twisted.trial import unittest @@ -23,7 +26,7 @@ METHOD:REQUEST BEGIN:VEVENT UID:%s -DTSTAMP:20140213T1254140 +DTSTAMP:20140213T125414Z DTSTART;TZID=Europe/London:%s DTEND;TZID=Europe/London:%s SUMMARY:test @@ -43,7 +46,7 @@ METHOD:REQUEST BEGIN:VEVENT UID:%s -DTSTAMP:20140215T1254140 +DTSTAMP:20140215T125414Z DTSTART;TZID=Europe/London:%s DTEND;TZID=Europe/London:%s SEQUENCE:2 @@ -90,7 +93,7 @@ METHOD:CANCEL BEGIN:VEVENT UID:%s -DTSTAMP:20140218T1254140 +DTSTAMP:20140218T125414Z DTSTART;TZID=Europe/London:20120713T100000 DTEND;TZID=Europe/London:20120713T110000 SUMMARY:test @@ -112,7 +115,7 @@ METHOD:REQUEST BEGIN:VEVENT UID:%s -DTSTAMP:20140213T1254140 +DTSTAMP:20140213T125414Z DTSTART;VALUE=DATE:%s DTEND;VALUE=DATE:%s SUMMARY:test @@ -133,7 +136,7 @@ METHOD:REQUEST BEGIN:VEVENT UID:%s -DTSTAMP:20140213T1254140 +DTSTAMP:20140213T125414Z DTSTART;TZID=Europe/Zurich:%s DTEND;TZID=Europe/Zurich:%s RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=10 @@ -184,6 +187,8 @@ @classmethod def setup_class(self, *args, **kw): + self.itip_reply_subject = _("Reservation Request for %(summary)s was %(status)s") + from tests.functional.purge_users import purge_users purge_users() @@ -213,9 +218,9 @@ self.boxter = funcs.resource_add("car", "Porsche Boxter S") self.cars = funcs.resource_add("collection", "Company Cars", [ self.audi['dn'], self.passat['dn'], self.boxter['dn'] ]) - self.room1 = funcs.resource_add("confroom", "Room 101", owner=self.jane['dn']) + self.room1 = funcs.resource_add("confroom", "Room 101", owner=self.jane['dn'], kolabinvitationpolicy='ACT_ACCEPT_AND_NOTIFY') self.room2 = funcs.resource_add("confroom", "Conference Room B-222") - self.rooms = funcs.resource_add("collection", "Rooms", [ self.room1['dn'], self.room2['dn'] ], self.jane['dn']) + self.rooms = funcs.resource_add("collection", "Rooms", [ self.room1['dn'], self.room2['dn'] ], self.jane['dn'], kolabinvitationpolicy='ACT_ACCEPT_AND_NOTIFY') time.sleep(1) from tests.functional.synchronize import synchronize_once @@ -328,12 +333,7 @@ if uid and event_message['subject'] != uid: continue - for part in event_message.walk(): - if part.get_content_type() == "application/calendar+xml": - payload = part.get_payload(decode=True) - found = pykolab.xml.event_from_string(payload) - break - + found = event_from_message(event_message) if found: break @@ -357,12 +357,10 @@ def find_resource_by_email(self, email): resource = None - if (email.find(self.audi['mail']) >= 0): - resource = self.audi - if (email.find(self.passat['mail']) >= 0): - resource = self.passat - if (email.find(self.boxter['mail']) >= 0): - resource = self.boxter + for r in [self.audi, self.passat, self.boxter, self.room1, self.room2]: + if (email.find(r['mail']) >= 0): + resource = r + break return resource @@ -379,7 +377,7 @@ def test_002_invite_resource(self): uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,7,13, 10,0,0)) - response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) event = self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid) @@ -390,7 +388,7 @@ def test_003_invite_resource_conflict(self): uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,7,13, 12,0,0)) - response = self.check_message_received("Reservation Request for test was DECLINED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DECLINED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) self.assertEqual(self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid), None) @@ -402,7 +400,7 @@ uid = self.send_itip_invitation(self.cars['mail'], datetime.datetime(2014,7,13, 12,0,0)) # one of the collection members accepted the reservation - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) delegatee = self.find_resource_by_email(accept['from']) @@ -412,7 +410,7 @@ self.assertIsInstance(self.check_resource_calendar_event(delegatee['kolabtargetfolder'], uid), pykolab.xml.Event) # resource collection responds with a DELEGATED message - response = self.check_message_received("Reservation Request for test was DELEGATED", self.cars['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DELEGATED') }, self.cars['mail']) self.assertIsInstance(response, email.message.Message) self.assertIn("ROLE=NON-PARTICIPANT;RSVP=FALSE", str(response)) @@ -422,13 +420,13 @@ uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,4,1, 10,0,0)) - response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) self.purge_mailbox(self.john['mailbox']) self.send_itip_update(self.audi['mail'], uid, datetime.datetime(2014,4,1, 12,0,0)) # conflict with myself - response = self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) event = self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid) @@ -443,13 +441,13 @@ uid = self.send_itip_invitation(self.cars['mail'], datetime.datetime(2014,4,24, 12,0,0)) # one of the collection members accepted the reservation - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) delegatee = self.find_resource_by_email(accept['from']) # book that resource for the next day self.send_itip_invitation(delegatee['mail'], datetime.datetime(2014,4,25, 14,0,0)) - accept2 = self.check_message_received("Reservation Request for test was ACCEPTED") + accept2 = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) # re-schedule first booking to a conflicting date self.purge_mailbox(self.john['mailbox']) @@ -457,7 +455,7 @@ self.send_itip_update(delegatee['mail'], uid, datetime.datetime(2014,4,25, 12,0,0), template=update_template) # expect response from another member of the initially delegated collection - new_accept = self.check_message_received("Reservation Request for test was ACCEPTED") + new_accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(new_accept, email.message.Message) new_delegatee = self.find_resource_by_email(new_accept['from']) @@ -468,7 +466,7 @@ self.assertIsInstance(event, pykolab.xml.Event) # old resource responds with a DELEGATED message - response = self.check_message_received("Reservation Request for test was DELEGATED", delegatee['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DELEGATED') }, delegatee['mail']) self.assertIsInstance(response, email.message.Message) # old reservation was removed from old delegate's calendar @@ -489,7 +487,7 @@ # make new reservation to the now free'd slot self.send_itip_invitation(self.boxter['mail'], datetime.datetime(2014,5,1, 9,0,0)) - response = self.check_message_received("Reservation Request for test was ACCEPTED", self.boxter['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.boxter['mail']) self.assertIsInstance(response, email.message.Message) @@ -500,7 +498,7 @@ uid = self.send_itip_invitation(self.cars['mail'], dt) # wait for accept notification - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) delegatee = self.find_resource_by_email(accept['from']) @@ -511,12 +509,12 @@ self.send_itip_update(delegatee['mail'], uid, dt, template=update_template) # get response from delegatee - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) self.assertIn(delegatee['mail'], accept['from']) # no delegation response on updates - self.assertEqual(self.check_message_received("Reservation Request for test was DELEGATED", self.cars['mail']), None) + self.assertEqual(self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DELEGATED') }, self.cars['mail']), None) def test_008_allday_reservation(self): @@ -524,7 +522,7 @@ uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,6,2), True) - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) event = self.check_resource_calendar_event(self.audi['kolabtargetfolder'], uid) @@ -532,7 +530,7 @@ self.assertIsInstance(event.get_start(), datetime.date) uid2 = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,6,2, 16,0,0)) - response = self.check_message_received("Reservation Request for test was DECLINED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DECLINED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) @@ -543,19 +541,19 @@ uid = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,2,20, 12,0,0), template=itip_recurring.replace(";COUNT=10", "")) - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) # check non-recurring against recurring uid2 = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,3,13, 10,0,0)) - response = self.check_message_received("Reservation Request for test was DECLINED", self.audi['mail']) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DECLINED') }, self.audi['mail']) self.assertIsInstance(response, email.message.Message) self.purge_mailbox(self.john['mailbox']) # check recurring against recurring uid3 = self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,2,22, 8,0,0), template=itip_recurring) - accept = self.check_message_received("Reservation Request for test was ACCEPTED") + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) self.assertIsInstance(accept, email.message.Message) @@ -570,7 +568,7 @@ itip_invalid = itip_invitation.replace("DTSTART;", "X-DTSTART;") self.send_itip_invitation(self.audi['mail'], datetime.datetime(2014,3,24, 19,30,0), template=itip_invalid) - self.assertEqual(self.check_message_received("Reservation Request for test was ACCEPTED", self.audi['mail']), None) + self.assertEqual(self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.audi['mail']), None) def test_011_owner_info(self): @@ -578,7 +576,7 @@ self.send_itip_invitation(self.room1['mail'], datetime.datetime(2014,6,19, 16,0,0)) - accept = self.check_message_received("Reservation Request for test was ACCEPTED", self.room1['mail']) + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.room1['mail']) self.assertIsInstance(accept, email.message.Message) respose_text = str(accept.get_payload(0)) self.assertIn(self.jane['mail'], respose_text) @@ -590,27 +588,36 @@ self.send_itip_invitation(self.room2['mail'], datetime.datetime(2014,6,19, 16,0,0)) - accept = self.check_message_received("Reservation Request for test was ACCEPTED", self.room2['mail']) + accept = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.room2['mail']) self.assertIsInstance(accept, email.message.Message) respose_text = str(accept.get_payload(0)) self.assertIn(self.jane['mail'], respose_text) self.assertIn(self.jane['displayname'], respose_text) - def TODO_test_012_owner_notification(self): + def test_012_owner_notification(self): self.purge_mailbox(self.john['mailbox']) self.purge_mailbox(self.jane['mailbox']) - self.send_itip_invitation(self.room1['mail'], datetime.datetime(2014,5,4, 13,0,0)) + self.send_itip_invitation(self.room1['mail'], datetime.datetime(2014,8,4, 13,0,0)) # check notification message sent to resource owner (jane) - notify = self.check_message_received("Reservation Request for test was ACCEPTED", self.room1['mail'], self.jane['mailbox']) + notify = self.check_message_received(_('Booking for %s has been %s') % (self.room1['cn'], participant_status_label('ACCEPTED')), self.room1['mail'], self.jane['mailbox']) self.assertIsInstance(notify, email.message.Message) - self.assertEqual(notify['From'], self.room1['mail']) - self.assertEqual(notify['Cc'], self.jane['mail']) + + notification_text = str(notify.get_payload()) + self.assertIn(self.john['mail'], notification_text) + self.assertIn(participant_status_label('ACCEPTED'), notification_text) + + self.purge_mailbox(self.john['mailbox']) # check notification sent to collection owner (jane) - self.send_itip_invitation(self.rooms['mail'], datetime.datetime(2014,5,4, 12,30,0)) + self.send_itip_invitation(self.rooms['mail'], datetime.datetime(2014,8,4, 12,30,0)) + + # one of the collection members accepted the reservation + accepted = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }) + delegatee = self.find_resource_by_email(accepted['from']) - notify = self.check_message_received("Reservation Request for test was ACCEPTED", self.room2['mail'], self.jane['mailbox']) + notify = self.check_message_received(_('Booking for %s has been %s') % (delegatee['cn'], participant_status_label('ACCEPTED')), delegatee['mail'], self.jane['mailbox']) self.assertIsInstance(notify, email.message.Message) + self.assertIn(self.john['mail'], notification_text)
View file
pykolab-0.7.tar.gz/tests/functional/test_wallace/test_007_invitationpolicy.py
Added
@@ -0,0 +1,737 @@ +import time +import pykolab +import smtplib +import email +import datetime +import pytz +import uuid +import kolabformat + +from pykolab.imap import IMAP +from wallace import module_resources + +from pykolab.translate import _ +from pykolab.xml import event_from_message +from pykolab.xml import participant_status_label +from email import message_from_string +from twisted.trial import unittest + +import tests.functional.resource_func as funcs + +conf = pykolab.getConf() + +itip_invitation = """ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:%(uid)s +DTSTAMP:20140213T125414Z +DTSTART;TZID=Europe/Berlin:%(start)s +DTEND;TZID=Europe/Berlin:%(end)s +SUMMARY:%(summary)s +DESCRIPTION:test +ORGANIZER;CN="Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=%(partstat)s;RSVP=TRUE:mailto:%(mailto)s +ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=TENTATIVE;RSVP=FALSE:mailto:somebody@else.com +TRANSP:OPAQUE +SEQUENCE:%(sequence)d +END:VEVENT +END:VCALENDAR +""" + +itip_cancellation = """ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:CANCEL +BEGIN:VEVENT +UID:%(uid)s +DTSTAMP:20140218T125414Z +DTSTART;TZID=Europe/Berlin:20120713T100000 +DTEND;TZID=Europe/Berlin:20120713T110000 +SUMMARY:%(summary)s +DESCRIPTION:test +ORGANIZER;CN="Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE:mailto:%(mailto)s +TRANSP:OPAQUE +SEQUENCE:%(sequence)d +END:VEVENT +END:VCALENDAR +""" + +itip_recurring = """ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//Mac OS X 10.9.2//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:%(uid)s +DTSTAMP:20140213T125414Z +DTSTART;TZID=Europe/Zurich:%(start)s +DTEND;TZID=Europe/Zurich:%(end)s +RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=10 +SUMMARY:%(summary)s +DESCRIPTION:test +ORGANIZER;CN="Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=%(partstat)s;RSVP=TRUE:mailto:%(mailto)s +TRANSP:OPAQUE +SEQUENCE:%(sequence)d +END:VEVENT +END:VCALENDAR +""" + +itip_reply = """ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//pykolab-0.6.9-1//kolab.org// +CALSCALE:GREGORIAN +METHOD:REPLY +BEGIN:VEVENT +SUMMARY:%(summary)s +UID:%(uid)s +DTSTART;TZID=Europe/Berlin;VALUE=DATE-TIME:%(start)s +DTEND;TZID=Europe/Berlin;VALUE=DATE-TIME:%(end)s +DTSTAMP;VALUE=DATE-TIME:20140706T171038Z +ORGANIZER;CN="Doe, John":MAILTO:%(organizer)s +ATTENDEE;CUTYPE=INDIVIDUAL;PARTSTAT=%(partstat)s;ROLE=REQ-PARTICIPANT:mailto:%(mailto)s +PRIORITY:0 +SEQUENCE:%(sequence)d +END:VEVENT +END:VCALENDAR +""" + +mime_message = """MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_c8894dbdb8baeedacae836230e3436fd" +From: "Doe, John" <john.doe@example.org> +Date: Tue, 25 Feb 2014 13:54:14 +0100 +Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org> +To: %s +Subject: "test" + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +*test* + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/calendar; charset=UTF-8; method=%s; name=event.ics +Content-Disposition: attachment; filename=event.ics +Content-Transfer-Encoding: 8bit + +%s +--=_c8894dbdb8baeedacae836230e3436fd-- +""" + +class TestWallaceInvitationpolicy(unittest.TestCase): + + john = None + itip_reply_subject = None + + @classmethod + def setUp(self): + """ Compatibility for twisted.trial.unittest + """ + if not self.john: + self.setup_class() + + @classmethod + def setup_class(self, *args, **kw): + self.itip_reply_subject = _('"%(summary)s" has been %(status)s') + + from tests.functional.purge_users import purge_users + purge_users() + + self.john = { + 'displayname': 'John Doe', + 'mail': 'john.doe@example.org', + 'dn': 'uid=doe,ou=People,dc=example,dc=org', + 'preferredlanguage': 'en_US', + 'mailbox': 'user/john.doe@example.org', + 'kolabtargetfolder': 'user/john.doe/Calendar@example.org', + 'kolabinvitationpolicy': ['ACT_UPDATE_AND_NOTIFY','ACT_MANUAL'] + } + + self.jane = { + 'displayname': 'Jane Manager', + 'mail': 'jane.manager@example.org', + 'dn': 'uid=manager,ou=People,dc=example,dc=org', + 'preferredlanguage': 'en_US', + 'mailbox': 'user/jane.manager@example.org', + 'kolabtargetfolder': 'user/jane.manager/Calendar@example.org', + 'kolabinvitationpolicy': ['ACT_ACCEPT_IF_NO_CONFLICT','ACT_REJECT_IF_CONFLICT','ACT_UPDATE'] + } + + self.jack = { + 'displayname': 'Jack Tentative', + 'mail': 'jack.tentative@example.org', + 'dn': 'uid=tentative,ou=People,dc=example,dc=org', + 'preferredlanguage': 'en_US', + 'mailbox': 'user/jack.tentative@example.org', + 'kolabtargetfolder': 'user/jack.tentative/Calendar@example.org', + 'kolabinvitationpolicy': ['ACT_TENTATIVE_IF_NO_CONFLICT','ACT_SAVE_TO_CALENDAR','ACT_UPDATE'] + } + + self.mark = { + 'displayname': 'Mark German', + 'mail': 'mark.german@example.org', + 'dn': 'uid=german,ou=People,dc=example,dc=org', + 'preferredlanguage': 'de_DE', + 'mailbox': 'user/mark.german@example.org', + 'kolabtargetfolder': 'user/mark.german/Calendar@example.org', + 'kolabinvitationpolicy': ['ACT_ACCEPT','ACT_UPDATE_AND_NOTIFY'] + } + + self.external = { + 'displayname': 'Bob External', + 'mail': 'bob.external@gmail.com' + } + + from tests.functional.user_add import user_add + user_add("John", "Doe", kolabinvitationpolicy=self.john['kolabinvitationpolicy'], preferredlanguage=self.john['preferredlanguage']) + user_add("Jane", "Manager", kolabinvitationpolicy=self.jane['kolabinvitationpolicy'], preferredlanguage=self.jane['preferredlanguage']) + user_add("Jack", "Tentative", kolabinvitationpolicy=self.jack['kolabinvitationpolicy'], preferredlanguage=self.jack['preferredlanguage']) + user_add("Mark", "German", kolabinvitationpolicy=self.mark['kolabinvitationpolicy'], preferredlanguage=self.mark['preferredlanguage']) + + time.sleep(1) + from tests.functional.synchronize import synchronize_once + synchronize_once() + + def send_message(self, itip_payload, to_addr, from_addr=None, method="REQUEST"): + if from_addr is None: + from_addr = self.john['mail'] + + smtp = smtplib.SMTP('localhost', 10026) + smtp.sendmail(from_addr, to_addr, mime_message % (to_addr, method, itip_payload)) + + def send_itip_invitation(self, attendee_email, start=None, allday=False, template=None, summary="test", sequence=0, partstat='NEEDS-ACTION'): + if start is None: + start = datetime.datetime.now() + + uid = str(uuid.uuid4()) + + if allday: + default_template = itip_allday + end = start + datetime.timedelta(days=1) + date_format = '%Y%m%d' + else: + end = start + datetime.timedelta(hours=4) + default_template = itip_invitation + date_format = '%Y%m%dT%H%M%S' + + self.send_message((template if template is not None else default_template) % { + 'uid': uid, + 'start': start.strftime(date_format), + 'end': end.strftime(date_format), + 'mailto': attendee_email, + 'summary': summary, + 'sequence': sequence, + 'partstat': partstat + }, + attendee_email) + + return uid + + def send_itip_update(self, attendee_email, uid, start=None, template=None, summary="test", sequence=1, partstat='ACCEPTED'): + if start is None: + start = datetime.datetime.now() + + end = start + datetime.timedelta(hours=4) + self.send_message((template if template is not None else itip_invitation) % { + 'uid': uid, + 'start': start.strftime('%Y%m%dT%H%M%S'), + 'end': end.strftime('%Y%m%dT%H%M%S'), + 'mailto': attendee_email, + 'summary': summary, + 'sequence': sequence, + 'partstat': partstat + }, + attendee_email) + + return uid + + def send_itip_reply(self, uid, attendee_email, mailto, start=None, template=None, summary="test", sequence=0, partstat='ACCEPTED'): + if start is None: + start = datetime.datetime.now() + + end = start + datetime.timedelta(hours=4) + self.send_message((template if template is not None else itip_reply) % { + 'uid': uid, + 'start': start.strftime('%Y%m%dT%H%M%S'), + 'end': end.strftime('%Y%m%dT%H%M%S'), + 'mailto': attendee_email, + 'organizer': mailto, + 'summary': summary, + 'sequence': sequence, + 'partstat': partstat + }, + mailto, + attendee_email, + method='REPLY') + + return uid + + def send_itip_cancel(self, attendee_email, uid, summary="test", sequence=1): + self.send_message(itip_cancellation % { + 'uid': uid, + 'mailto': attendee_email, + 'summary': summary, + 'sequence': sequence, + }, + attendee_email, + method='CANCEL') + + return uid + + def create_calendar_event(self, start=None, summary="test", sequence=0, user=None, attendees=None): + if start is None: + start = datetime.datetime.now(pytz.timezone("Europe/Berlin")) + if user is None: + user = self.john + if attendees is None: + attendees = [self.jane] + + end = start + datetime.timedelta(hours=4) + + event = pykolab.xml.Event() + event.set_start(start) + event.set_end(end) + event.set_organizer(user['mail'], user['displayname']) + + for attendee in attendees: + event.add_attendee(attendee['mail'], attendee['displayname'], role="REQ-PARTICIPANT", participant_status="NEEDS-ACTION", rsvp=True) + + event.set_summary(summary) + event.set_sequence(sequence) + + # create event with attachment + vattach = event.get_attachments() + attachment = kolabformat.Attachment() + attachment.setLabel('attach.txt') + attachment.setData('This is a text attachment', 'text/plain') + vattach.append(attachment) + event.event.setAttachments(vattach) + + imap = IMAP() + imap.connect() + + mailbox = imap.folder_quote(user['kolabtargetfolder']) + imap.set_acl(mailbox, "cyrus-admin", "lrswipkxtecda") + imap.imap.m.select(mailbox) + + result = imap.imap.m.append( + mailbox, + None, + None, + event.to_message().as_string() + ) + + return event.get_uid() + + def update_calendar_event(self, uid, start=None, summary=None, sequence=0, user=None): + if user is None: + user = self.john + + event = self.check_user_calendar_event(user['kolabtargetfolder'], uid) + if event: + if start is not None: + event.set_start(start) + if summary is not None: + event.set_summary(summary) + if sequence is not None: + event.set_sequence(sequence) + + imap = IMAP() + imap.connect() + + mailbox = imap.folder_quote(user['kolabtargetfolder']) + imap.set_acl(mailbox, "cyrus-admin", "lrswipkxtecda") + imap.imap.m.select(mailbox) + + return imap.imap.m.append( + mailbox, + None, + None, + event.to_message().as_string() + ) + + return False + + def check_message_received(self, subject, from_addr=None, mailbox=None): + if mailbox is None: + mailbox = self.john['mailbox'] + + imap = IMAP() + imap.connect() + + mailbox = imap.folder_quote(mailbox) + imap.set_acl(mailbox, "cyrus-admin", "lrs") + imap.imap.m.select(mailbox) + + found = None + retries = 15 + + while not found and retries > 0: + retries -= 1 + + typ, data = imap.imap.m.search(None, '(UNDELETED HEADER FROM "%s")' % (from_addr) if from_addr else 'UNDELETED') + for num in data[0].split(): + typ, msg = imap.imap.m.fetch(num, '(RFC822)') + message = message_from_string(msg[0][1]) + if message['Subject'] == subject: + found = message + break + + time.sleep(1) + + imap.disconnect() + + return found + + def check_user_calendar_event(self, mailbox, uid=None): + imap = IMAP() + imap.connect() + + mailbox = imap.folder_quote(mailbox) + imap.set_acl(mailbox, "cyrus-admin", "lrs") + imap.imap.m.select(mailbox) + + found = None + retries = 15 + + while not found and retries > 0: + retries -= 1 + + typ, data = imap.imap.m.search(None, '(UNDELETED HEADER SUBJECT "%s")' % (uid) if uid else '(UNDELETED HEADER X-Kolab-Type "application/x-vnd.kolab.event")') + for num in data[0].split(): + typ, data = imap.imap.m.fetch(num, '(RFC822)') + event_message = message_from_string(data[0][1]) + + # return matching UID or first event found + if uid and event_message['subject'] != uid: + continue + + found = event_from_message(event_message) + if found: + break + + time.sleep(1) + + return found + + def purge_mailbox(self, mailbox): + imap = IMAP() + imap.connect() + mailbox = imap.folder_quote(mailbox) + imap.set_acl(mailbox, "cyrus-admin", "lrwcdest") + imap.imap.m.select(mailbox) + + typ, data = imap.imap.m.search(None, 'ALL') + for num in data[0].split(): + imap.imap.m.store(num, '+FLAGS', '\\Deleted') + + imap.imap.m.expunge() + imap.disconnect() + + + def test_001_invite_accept_udate(self): + start = datetime.datetime(2014,8,13, 10,0,0) + uid = self.send_itip_invitation(self.jane['mail'], start) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.jane['mail']) + self.assertIsInstance(response, email.message.Message) + + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "test") + + # send update with the same sequence: no re-scheduling + self.send_itip_update(self.jane['mail'], uid, start, summary="test updated", sequence=0, partstat='ACCEPTED') + + time.sleep(10) + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "test updated") + self.assertEqual(event.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + + + # @depends on test_001_invite_user + def test_002_invite_conflict_reject(self): + uid = self.send_itip_invitation(self.jane['mail'], datetime.datetime(2014,8,13, 11,0,0), summary="test2") + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test2', 'status':participant_status_label('DECLINED') }, self.jane['mail']) + self.assertIsInstance(response, email.message.Message) + + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "test2") + + + def test_003_invite_accept_tentative(self): + self.purge_mailbox(self.john['mailbox']) + + uid = self.send_itip_invitation(self.jack['mail'], datetime.datetime(2014,7,24, 8,0,0)) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('TENTATIVE') }, self.jack['mail']) + self.assertIsInstance(response, email.message.Message) + + + def test_004_copy_to_calendar(self): + self.purge_mailbox(self.john['mailbox']) + + self.send_itip_invitation(self.jack['mail'], datetime.datetime(2014,7,29, 8,0,0)) + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('TENTATIVE') }, self.jack['mail']) + self.assertIsInstance(response, email.message.Message) + + # send conflicting request to jack + uid = self.send_itip_invitation(self.jack['mail'], datetime.datetime(2014,7,29, 10,0,0), summary="test2") + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test2', 'status':participant_status_label('DECLINED') }, self.jack['mail']) + self.assertEqual(response, None, "No reply expected") + + event = self.check_user_calendar_event(self.jack['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "test2") + self.assertEqual(event.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartNeedsAction) + + + def test_005_invite_rescheduling_accept(self): + self.purge_mailbox(self.john['mailbox']) + + start = datetime.datetime(2014,8,14, 9,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.send_itip_invitation(self.jane['mail'], start) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.jane['mail']) + self.assertIsInstance(response, email.message.Message) + + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "test") + + self.purge_mailbox(self.john['mailbox']) + + # send update with new date and incremented sequence + new_start = datetime.datetime(2014,8,15, 15,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + self.send_itip_update(self.jane['mail'], uid, new_start, summary="test", sequence=1) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('ACCEPTED') }, self.jane['mail']) + self.assertIsInstance(response, email.message.Message) + + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_start(), new_start) + self.assertEqual(event.get_sequence(), 1) + + + def test_005_invite_rescheduling_reject(self): + self.purge_mailbox(self.john['mailbox']) + self.purge_mailbox(self.jack['kolabtargetfolder']) + + start = datetime.datetime(2014,8,9, 17,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.send_itip_invitation(self.jack['mail'], start) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('TENTATIVE') }, self.jack['mail']) + self.assertIsInstance(response, email.message.Message) + + # send update with new but conflicting date and incremented sequence + self.create_calendar_event(datetime.datetime(2014,8,10, 10,30,0, tzinfo=pytz.timezone("Europe/Berlin")), user=self.jack) + new_start = datetime.datetime(2014,8,10, 9,30,0, tzinfo=pytz.timezone("Europe/Berlin")) + self.send_itip_update(self.jack['mail'], uid, new_start, summary="test (updated)", sequence=1) + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'test', 'status':participant_status_label('DECLINED') }, self.jack['mail']) + self.assertEqual(response, None) + + # verify re-scheduled copy in jack's calendar with NEEDS-ACTION + event = self.check_user_calendar_event(self.jack['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_start(), new_start) + self.assertEqual(event.get_sequence(), 1) + + attendee = event.get_attendee(self.jack['mail']) + self.assertTrue(attendee.get_rsvp()) + self.assertEqual(attendee.get_participant_status(), kolabformat.PartNeedsAction) + + + def test_006_invitation_reply(self): + self.purge_mailbox(self.john['mailbox']) + + start = datetime.datetime(2014,8,18, 14,30,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.create_calendar_event(start, user=self.john) + + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + + # send a reply from jane to john + self.send_itip_reply(uid, self.jane['mail'], self.john['mail'], start=start) + + # check for the updated event in john's calendar + time.sleep(10) + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + + attendee = event.get_attendee(self.jane['mail']) + self.assertIsInstance(attendee, pykolab.xml.Attendee) + self.assertEqual(attendee.get_participant_status(), kolabformat.PartAccepted) + + # check attachments in update event + attachments = event.get_attachments() + self.assertEqual(len(attachments), 1) + self.assertEqual(event.get_attachment_data(0), 'This is a text attachment') + + + def test_007_invitation_cancel(self): + self.purge_mailbox(self.john['mailbox']) + + uid = self.send_itip_invitation(self.jane['mail'], summary="cancelled") + + response = self.check_message_received(self.itip_reply_subject % { 'summary':'cancelled', 'status':participant_status_label('ACCEPTED') }, self.jane['mail']) + self.assertIsInstance(response, email.message.Message) + + self.send_itip_cancel(self.jane['mail'], uid, summary="cancelled") + + time.sleep(10) + event = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_summary(), "cancelled") + self.assertEqual(event.get_status(), 'CANCELLED') + self.assertTrue(event.get_transparency()) + + + def test_008_inivtation_reply_notify(self): + self.purge_mailbox(self.john['mailbox']) + + start = datetime.datetime(2014,8,12, 16,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.create_calendar_event(start, user=self.john, attendees=[self.jane, self.mark, self.jack]) + + # send a reply from jane to john + self.send_itip_reply(uid, self.jane['mail'], self.john['mail'], start=start) + + # check for notification message + # this notification should be suppressed until mark has replied, too + notification = self.check_message_received(_('"%s" has been updated') % ('test'), self.john['mail']) + self.assertEqual(notification, None) + + # send a reply from mark to john + self.send_itip_reply(uid, self.mark['mail'], self.john['mail'], start=start, partstat='ACCEPTED') + + notification = self.check_message_received(_('"%s" has been updated') % ('test'), self.john['mail']) + self.assertIsInstance(notification, email.message.Message) + + notification_text = str(notification.get_payload()); + self.assertIn(self.jane['mail'], notification_text) + self.assertIn(_("PENDING"), notification_text) + + self.purge_mailbox(self.john['mailbox']) + + # send a reply from mark to john + self.send_itip_reply(uid, self.jack['mail'], self.john['mail'], start=start, partstat='ACCEPTED') + + # this triggers an additional notification + notification = self.check_message_received(_('"%s" has been updated') % ('test'), self.john['mail']) + self.assertIsInstance(notification, email.message.Message) + + notification_text = str(notification.get_payload()); + self.assertNotIn(_("PENDING"), notification_text) + + + def test_008_notify_translated(self): + self.purge_mailbox(self.mark['mailbox']) + + start = datetime.datetime(2014,8,12, 16,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.create_calendar_event(start, user=self.mark, attendees=[self.jane]) + + # send a reply from jane to mark + self.send_itip_reply(uid, self.jane['mail'], self.mark['mail'], start=start) + + # change translations to de_DE + pykolab.translate.setUserLanguage(self.mark['preferredlanguage']) + notification = self.check_message_received(_('"%s" has been updated') % ('test'), self.mark['mail'], self.mark['mailbox']) + self.assertIsInstance(notification, email.message.Message) + + notification_text = str(notification.get_payload()); + self.assertIn(self.jane['mail'], notification_text) + self.assertIn(participant_status_label("ACCEPTED")+":", notification_text) + + # reset localization + pykolab.translate.setUserLanguage(conf.get('kolab','default_locale')) + + + def test_009_outdated_reply(self): + self.purge_mailbox(self.john['mailbox']) + + start = datetime.datetime(2014,9,2, 11,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.create_calendar_event(start, user=self.john, sequence=2) + + # send a reply from jane to john + self.send_itip_reply(uid, self.jane['mail'], self.john['mail'], start=start, sequence=1) + + # verify jane's attendee status was not updated + time.sleep(10) + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + self.assertEqual(event.get_sequence(), 2) + self.assertEqual(event.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartNeedsAction) + + + def test_010_partstat_update_propagation(self): + # ATTENTION: this test requires wallace.invitationpolicy_autoupdate_other_attendees_on_reply to be enabled in config + + start = datetime.datetime(2014,8,21, 13,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + uid = self.create_calendar_event(start, user=self.john, attendees=[self.jane, self.jack, self.external]) + + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + + # send invitations to jack and jane + event_itip = event.as_string_itip() + self.send_itip_invitation(self.jane['mail'], start, template=event_itip) + self.send_itip_invitation(self.jack['mail'], start, template=event_itip) + + # wait for replies from jack and jane to be processed and propagated + time.sleep(10) + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + + # check updated event in organizer's calendar + self.assertEqual(event.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(event.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartTentative) + + # check updated partstats in jane's calendar + janes = self.check_user_calendar_event(self.jane['kolabtargetfolder'], uid) + self.assertEqual(janes.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(janes.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartTentative) + + # check updated partstats in jack's calendar + jacks = self.check_user_calendar_event(self.jack['kolabtargetfolder'], uid) + self.assertEqual(jacks.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(jacks.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartTentative) + + # PART 2: create conflicting event in jack's calendar + new_start = datetime.datetime(2014,8,21, 6,0,0, tzinfo=pytz.timezone("Europe/Berlin")) + self.create_calendar_event(new_start, user=self.jack, attendees=[], summary="blocker") + + # re-schedule initial event to new date + self.update_calendar_event(uid, start=new_start, sequence=1, user=self.john) + self.send_itip_update(self.jane['mail'], uid, new_start, summary="test (updated)", sequence=1) + self.send_itip_update(self.jack['mail'], uid, new_start, summary="test (updated)", sequence=1) + + # wait for replies to be processed and propagated + time.sleep(10) + event = self.check_user_calendar_event(self.john['kolabtargetfolder'], uid) + self.assertIsInstance(event, pykolab.xml.Event) + + # check updated event in organizer's calendar (jack didn't reply yet) + self.assertEqual(event.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(event.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartTentative) + + # check partstats in jack's calendar: jack's status should remain needs-action + jacks = self.check_user_calendar_event(self.jack['kolabtargetfolder'], uid) + self.assertEqual(jacks.get_attendee(self.jane['mail']).get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(jacks.get_attendee(self.jack['mail']).get_participant_status(), kolabformat.PartNeedsAction) + +
View file
pykolab-0.7.tar.gz/tests/functional/user_add.py
Changed
@@ -4,7 +4,7 @@ conf = pykolab.getConf() -def user_add(givenname, sn, preferredlanguage='en_US'): +def user_add(givenname, sn, preferredlanguage='en_US', **kw): if givenname == None: raise Exception @@ -25,6 +25,8 @@ 'userpassword': 'Welcome2KolabSystems' } + user_details.update(kw) + login = conf.get('ldap', 'bind_dn') password = conf.get('ldap', 'bind_pw') domain = conf.get('kolab', 'primary_domain')
View file
pykolab-0.7.tar.gz/tests/unit/test-002-attendee.py
Changed
@@ -1,7 +1,9 @@ import datetime import unittest +import kolabformat from pykolab.xml import Attendee +from pykolab.xml import participant_status_label class TestEventXML(unittest.TestCase): attendee = Attendee("jane@doe.org") @@ -101,5 +103,30 @@ self.assertEqual([k for k,v in self.attendee.cutype_map.iteritems() if v == 2][0], "INDIVIDUAL") self.assertEqual([k for k,v in self.attendee.cutype_map.iteritems() if v == 3][0], "RESOURCE") + def test_018_partstat_label(self): + self.assertEqual(participant_status_label('NEEDS-ACTION'), "Needs Action") + self.assertEqual(participant_status_label(kolabformat.PartTentative), "Tentatively Accepted") + self.assertEqual(participant_status_label('UNKNOWN'), "UNKNOWN") + + def test_020_to_dict(self): + name = "Doe, Jane" + role = 'OPT-PARTICIPANT' + cutype = 'RESOURCE' + partstat = 'ACCEPTED' + self.attendee.set_name(name) + self.attendee.set_rsvp(True) + self.attendee.set_role(role) + self.attendee.set_cutype(cutype) + self.attendee.set_participant_status(partstat) + + data = self.attendee.to_dict() + self.assertIsInstance(data, dict) + self.assertEqual(data['role'], role) + self.assertEqual(data['cutype'], cutype) + self.assertEqual(data['partstat'], partstat) + self.assertEqual(data['name'], name) + self.assertEqual(data['email'], 'jane@doe.org') + self.assertTrue(data['rsvp']) + if __name__ == '__main__': unittest.main()
View file
pykolab-0.7.tar.gz/tests/unit/test-003-event.py
Changed
@@ -1,3 +1,4 @@ +import re import datetime import pytz import sys @@ -11,6 +12,233 @@ from pykolab.xml import InvalidAttendeeParticipantStatusError from pykolab.xml import InvalidEventDateError from pykolab.xml import event_from_ical +from pykolab.xml import event_from_string +from pykolab.xml import event_from_message + +ical_event = """ +BEGIN:VEVENT +UID:7a35527d-f783-4b58-b404-b1389bd2fc57 +DTSTAMP;VALUE=DATE-TIME:20140407T122311Z +CREATED;VALUE=DATE-TIME:20140407T122245Z +LAST-MODIFIED;VALUE=DATE-TIME:20140407T122311Z +DTSTART;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T110000 +DURATION:PT1H30M0S +RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=10 +EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140530T110000 +EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140620T110000 +SUMMARY:Summary +LOCATION:Location +DESCRIPTION:Description\\n2 lines +CATEGORIES:Personal +TRANSP:OPAQUE +PRIORITY:2 +SEQUENCE:2 +CLASS:PUBLIC +ATTENDEE;CN="Manager, Jane";PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;CUTYP + E=INDIVIDUAL;RSVP=TRUE:mailto:jane.manager@example.org +ATTENDEE;CUTYPE=RESOURCE;PARTSTAT=NEEDS-ACTION;ROLE=OPT-PARTICIPANT;RSVP=FA + LSE:MAILTO:max@imum.com +ORGANIZER;CN=Doe\, John:mailto:john.doe@example.org +URL:http://somelink.com/foo +ATTACH;VALUE=BINARY;ENCODING=BASE64;FMTTYPE=image/png;X-LABEL=silhouette.pn + g:iVBORw0KGgoAAAANSUhEUgAAAC4AAAAuCAIAAADY27xgAAAAGXRFWHRTb2Z0d2FyZQBBZG9i + ZSBJbWFnZVJlYWR5ccllPAAAAsRJREFUeNrsmeluKjEMhTswrAWB4P3fECGx79CjsTDmOKRkpF + xxpfoHSmchX7ybFrfb7eszpPH1MfKH8ofyH6KUtd/c7/en0wmfWBdF0Wq1Op1Ou91uNGoer6iX + V1ar1Xa7xUJeB4qsr9frdyVlWWZH2VZyPp+xPXHIAoK70+m02+1m9JXj8bhcLi+Xi3J4xUCazS + bUltdtd7ud7ldUIhC3u+iTwF0sFhlR4Kds4LtRZK1w4te5UM6V6JaqhqC3CQ28OAsKggJfbZ3U + eozCqZ4koHIZCGmD9ivuos9YONFirmxrI0UNZG1kbZeUXdJQNJNa91RlqMn0ekYUMZDup6dXVV + m+1OSZhqLx6bVCELJGSsyFQtFrF15JGYMZgoxubWGDSDVhvTipDKWhoBOIpFobxtlbJ0Gh0/tg + lgXal4woUHi/36fQoBQncDAlupa8DeVwOPRe4lUyGAwQ+dl7W+xBXkJBhEUqR32UoJfYIKrR4d + ZBgcdIRqfEqn+mekl9FNRbSTA249la3ev1/kXHD47ZbEYR5L9kMplkd9vNZqMFyIYxxfN8Pk8q + QGlagT5QDtfrNYUMlWW9LiGNPPSmC/+OgpK2r4RO6dOatZd+4gAAemdIi6Fg9EKLD4vASWkzv3 + ew06NSCiA40CumAIoaIrhrcAwjF7aDo58gUchgNV+0n1BAcDgcoAZrXV9mI4qkhtK6FJFhi9Fo + ZKPsgQI1ACJieH/Kd570t+xFoIzHYzl5Q40CFGrSqGuks3qmYIKJfIl0nPKLxAMFw7Dv1+2QYf + vFSOBQubbOFDSc7ZcfWvHv6DzhOzT6IeOVPuz8Roex0f6EgsE/2IL4qdg7hIXz7/pBie7q1uWr + tp66xrif0l1KwUE4P7Y9Gci/ZgtNRFX+Rw06Q2RigsjuDc3urwKHxuNITaaxyD9mT2WvSDAXn/ + Pvhh8BBgBjyfPSGbSYcwAAAABJRU5ErkJggg== +ATTACH;VALUE=BINARY;ENCODING=BASE64;FMTTYPE=text/plain;X-LABEL=text.txt:VGh + pcyBpcyBhIHRleHQgZmlsZQo= +BEGIN:VALARM +ACTION:DISPLAY +TRIGGER:-PT30M +END:VALARM +END:VEVENT +""" + +xml_event = """ +<icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0"> + <vcalendar> + <properties> + <prodid> + <text>Libkolabxml-1.1</text> + </prodid> + <version> + <text>2.0</text> + </version> + <x-kolab-version> + <text>3.1.0</text> + </x-kolab-version> + </properties> + <components> + <vevent> + <properties> + <uid> + <text>75c740bb-b3c6-442c-8021-ecbaeb0a025e</text> + </uid> + <created> + <date-time>2014-07-07T01:28:23Z</date-time> + </created> + <dtstamp> + <date-time>2014-07-07T01:28:23Z</date-time> + </dtstamp> + <sequence> + <integer>1</integer> + </sequence> + <class> + <text>PUBLIC</text> + </class> + <dtstart> + <parameters> + <tzid> + <text>/kolab.org/Europe/London</text> + </tzid> + </parameters> + <date-time>2014-08-13T10:00:00</date-time> + </dtstart> + <dtend> + <parameters> + <tzid><text>/kolab.org/Europe/London</text></tzid> + </parameters> + <date-time>2014-08-13T14:00:00</date-time> + </dtend> + <rrule> + <recur> + <freq>DAILY</freq> + <until> + <date>2014-07-25</date> + </until> + </recur> + </rrule> + <exdate> + <parameters> + <tzid> + <text>/kolab.org/Europe/Berlin</text> + </tzid> + </parameters> + <date>2014-07-19</date> + <date>2014-07-26</date> + <date>2014-07-12</date> + <date>2014-07-13</date> + <date>2014-07-20</date> + <date>2014-07-27</date> + <date>2014-07-05</date> + <date>2014-07-06</date> + </exdate> + <summary> + <text>test</text> + </summary> + <description> + <text>test</text> + </description> + <priority> + <integer>5</integer> + </priority> + <status> + <text>CANCELLED</text> + </status> + <location> + <text>Room 101</text> + </location> + <organizer> + <parameters> + <cn><text>Doe, John</text></cn> + </parameters> + <cal-address>mailto:%3Cjohn%40example.org%3E</cal-address> + </organizer> + <attendee> + <parameters> + <partstat><text>ACCEPTED</text></partstat> + <role><text>REQ-PARTICIPANT</text></role> + <rsvp><boolean>true</boolean></rsvp> + </parameters> + <cal-address>mailto:%3Cjane%40example.org%3E</cal-address> + </attendee> + <attendee> + <parameters> + <partstat><text>TENTATIVE</text></partstat> + <role><text>OPT-PARTICIPANT</text></role> + </parameters> + <cal-address>mailto:%3Csomebody%40else.com%3E</cal-address> + </attendee> + <attach> + <parameters> + <fmttype> + <text>text/html</text> + </fmttype> + <x-label> + <text>noname.1395223627.5555</text> + </x-label> + </parameters> + <uri>cid:noname.1395223627.5555</uri> + </attach> + <x-custom> + <identifier>X-MOZ-RECEIVED-DTSTAMP</identifier> + <value>20140224T155612Z</value> + </x-custom> + <x-custom> + <identifier>X-GWSHOW-AS</identifier> + <value>BUSY</value> + </x-custom> + </properties> + <components> + <valarm> + <properties> + <action> + <text>DISPLAY</text> + </action> + <description> + <text>alarm 1</text> + </description> + <trigger> + <parameters> + <related> + <text>START</text> + </related> + </parameters> + <duration>-PT2H</duration> + </trigger> + </properties> + </valarm> + <valarm> + <properties> + <action> + <text>EMAIL</text> + </action> + <summary> + <text>test</text> + </summary> + <description> + <text>alarm 2</text> + </description> + <attendee> + <cal-address>mailto:%3Cjohn.die%40example.org%3E</cal-address> + </attendee> + <trigger> + <parameters> + <related> + <text>START</text> + </related> + </parameters> + <duration>-P1D</duration> + </trigger> + </properties> + </valarm> + </components> + </vevent> + </components> + </vcalendar> +</icalendar> +""" class TestEventXML(unittest.TestCase): event = Event() @@ -117,25 +345,23 @@ def test_018_load_from_ical(self): ical_str = """BEGIN:VCALENDAR VERSION:2.0 -PRODID:-//Apple Inc.//Mac OS X 10.9.2//EN +PRODID:-//Roundcube//Roundcube libcalendaring 1.1-git//Sabre//Sabre VObject + 2.1.3//EN CALSCALE:GREGORIAN -BEGIN:VEVENT -DTSTART;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T110000 -DURATION:PT1H30M0S -RRULE:FREQ=WEEKLY;INTERVAL=1;COUNT=10 -EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140530T110000 -EXDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140620T110000 -UID:7a35527d-f783-4b58-b404-b1389bd2fc57 -ATTENDEE;CN="Doe, Jane";CUTYPE=INDIVIDUAL;PARTSTAT=ACCEPTED - ;ROLE=REQ-PARTICIPANT;RSVP=FALSE:MAILTO:jane@doe.org -ATTENDEE;CUTYPE=RESOURCE;PARTSTAT=NEEDS-ACTION - ;ROLE=OPT-PARTICIPANT;RSVP=FALSE:MAILTO:max@imum.com -SEQUENCE:2 -END:VEVENT -END:VCALENDAR -""" +METHOD:REQUEST + """ + ical_event + "END:VCALENDAR" + ical = icalendar.Calendar.from_ical(ical_str) event = event_from_ical(ical.walk('VEVENT')[0].to_ical()) + + self.assertEqual(event.get_location(), "Location") + self.assertEqual(str(event.get_lastmodified()), "2014-04-07 12:23:11+00:00") + self.assertEqual(event.get_description(), "Description\n2 lines") + self.assertEqual(event.get_url(), "http://somelink.com/foo") + self.assertEqual(event.get_transparency(), False) + self.assertEqual(event.get_categories(), ["Personal"]) + self.assertEqual(event.get_priority(), '2') + self.assertEqual(event.get_classification(), kolabformat.ClassPublic) self.assertEqual(event.get_attendee_by_email("max@imum.com").get_cutype(), kolabformat.CutypeResource) self.assertEqual(event.get_sequence(), 2) self.assertTrue(event.is_recurring()) @@ -144,17 +370,60 @@ self.assertEqual(str(event.get_end()), "2014-05-23 12:30:00+01:00") self.assertEqual(len(event.get_exception_dates()), 2) self.assertIsInstance(event.get_exception_dates()[0], datetime.datetime) + self.assertEqual(len(event.get_alarms()), 1) + self.assertEqual(len(event.get_attachments()), 2) + + def test_018_ical_to_message(self): + event = event_from_ical(ical_event) + message = event.to_message() + + self.assertTrue(message.is_multipart()) + self.assertEqual(message['Subject'], event.uid) + self.assertEqual(message['X-Kolab-Type'], 'application/x-vnd.kolab.event') + + parts = [p for p in message.walk()] + attachments = event.get_attachments(); + + self.assertEqual(len(parts), 5) + self.assertEqual(parts[1].get_content_type(), 'text/plain') + self.assertEqual(parts[2].get_content_type(), 'application/calendar+xml') + self.assertEqual(parts[3].get_content_type(), 'image/png') + self.assertEqual(parts[4].get_content_type(), 'text/plain') + self.assertEqual(parts[2]['Content-ID'], None) + self.assertEqual(parts[3]['Content-ID'].strip('<>'), attachments[0].uri()[4:]) + self.assertEqual(parts[4]['Content-ID'].strip('<>'), attachments[1].uri()[4:]) + + def test_018_ical_allday_events(self): + ical = """BEGIN:VEVENT +UID:ffffffff-f783-4b58-b404-b1389bd2ffff +DTSTAMP;VALUE=DATE-TIME:20140407T122311Z +CREATED;VALUE=DATE-TIME:20140407T122245Z +DTSTART;VALUE=DATE:20140823 +DTEND;VALUE=DATE:20140824 +SUMMARY:All day +DESCRIPTION:One single day +TRANSP:OPAQUE +CLASS:PUBLIC +END:VEVENT +""" + event = event_from_ical(ical) + self.assertEqual(str(event.get_start()), "2014-08-23") + self.assertEqual(str(event.get_end()), "2014-08-23") + self.assertEqual(str(event.get_ical_dtend()), "2014-08-24") + self.assertTrue(re.match('.*<dtend>\s*<date>2014-08-23</date>', str(event), re.DOTALL)) def test_019_as_string_itip(self): self.event.set_summary("test") self.event.set_start(datetime.datetime(2014, 05, 23, 11, 00, 00, tzinfo=pytz.timezone("Europe/London"))) self.event.set_end(datetime.datetime(2014, 05, 23, 12, 30, 00, tzinfo=pytz.timezone("Europe/London"))) + self.event.set_sequence(3) ical = icalendar.Calendar.from_ical(self.event.as_string_itip()) event = ical.walk('VEVENT')[0] self.assertEqual(event['uid'], self.event.get_uid()) self.assertEqual(event['summary'], "test") + self.assertEqual(event['sequence'], 3) self.assertIsInstance(event['dtstamp'].dt, datetime.datetime) def test_020_calendaring_recurrence(self): @@ -214,6 +483,94 @@ self.assertEqual(self.event.get_next_occurence(_start), None) self.assertEqual(self.event.get_last_occurrence(), None) + def test_022_load_from_xml(self): + event = event_from_string(xml_event) + self.assertEqual(event.uid, '75c740bb-b3c6-442c-8021-ecbaeb0a025e') + self.assertEqual(event.get_attendee_by_email("jane@example.org").get_participant_status(), kolabformat.PartAccepted) + self.assertEqual(event.get_sequence(), 1) + self.assertIsInstance(event.get_start(), datetime.datetime) + self.assertEqual(str(event.get_start()), "2014-08-13 10:00:00+00:00") + + def test_023_load_from_message(self): + event = event_from_message(event_from_ical(ical_event).to_message()) + event.set_sequence(3) + + message = event.to_message() + self.assertTrue(message.is_multipart()) + + # check attachment MIME parts are kept + parts = [p for p in message.walk()] + attachments = event.get_attachments(); + + self.assertEqual(len(parts), 5) + self.assertEqual(parts[3].get_content_type(), 'image/png') + self.assertEqual(parts[3]['Content-ID'].strip('<>'), attachments[0].uri()[4:]) + self.assertEqual(parts[4].get_content_type(), 'text/plain') + self.assertEqual(parts[4]['Content-ID'].strip('<>'), attachments[1].uri()[4:]) + self.assertEqual(event.get_attachment_data(1), 'This is a text file') + + def test_024_bogus_itip_data(self): + # DTSTAMP contains an invalid date/time value + vevent = """BEGIN:VEVENT +UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 +DTSTAMP:20120713T1254140 +DTSTART;TZID=Europe/London:20120713T100000 +DTEND;TZID=Europe/London:20120713T110000 +SUMMARY:test +DESCRIPTION:test +ORGANIZER;CN="Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailt + o:jane.doe@example.org +ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailt + o:user.external@example.com +SEQUENCE:1 +TRANSP:OPAQUE +END:VEVENT +""" + event = event_from_ical(vevent) + self.assertRaises(EventIntegrityError, event.to_message) + + def test_025_to_dict(self): + data = event_from_string(xml_event).to_dict() + + self.assertIsInstance(data, dict) + self.assertIsInstance(data['start'], datetime.datetime) + self.assertIsInstance(data['end'], datetime.datetime) + self.assertIsInstance(data['created'], datetime.datetime) + self.assertIsInstance(data['lastmodified-date'], datetime.datetime) + self.assertEqual(data['uid'], '75c740bb-b3c6-442c-8021-ecbaeb0a025e') + self.assertEqual(data['summary'], 'test') + self.assertEqual(data['location'], 'Room 101') + self.assertEqual(data['description'], 'test') + self.assertEqual(data['priority'], 5) + self.assertEqual(data['status'], 'CANCELLED') + self.assertEqual(data['sequence'], 1) + self.assertEqual(data['transparency'], False) + self.assertEqual(data['X-GWSHOW-AS'], 'BUSY') + + self.assertIsInstance(data['organizer'], dict) + self.assertEqual(data['organizer']['email'], 'john@example.org') + + self.assertEqual(len(data['attendee']), 2) + self.assertIsInstance(data['attendee'][0], dict) + + self.assertEqual(len(data['attach']), 1) + self.assertIsInstance(data['attach'][0], dict) + self.assertEqual(data['attach'][0]['fmttype'], 'text/html') + + self.assertIsInstance(data['rrule'], dict) + self.assertEqual(data['rrule']['frequency'], 'DAILY') + self.assertEqual(data['rrule']['interval'], 1) + self.assertEqual(data['rrule']['wkst'], 'MO') + self.assertIsInstance(data['rrule']['until'], datetime.date) + + self.assertIsInstance(data['alarm'], list) + self.assertEqual(len(data['alarm']), 2) + self.assertEqual(data['alarm'][0]['action'], 'DISPLAY') + self.assertEqual(data['alarm'][1]['action'], 'EMAIL') + self.assertEqual(data['alarm'][1]['trigger']['value'], '-P1D') + self.assertEqual(len(data['alarm'][1]['attendee']), 1) + if __name__ == '__main__': unittest.main()
View file
pykolab-0.7.tar.gz/tests/unit/test-011-itip.py
Added
@@ -0,0 +1,406 @@ +import pykolab +import datetime +import pytz +import kolabformat + +from pykolab import itip +from pykolab.xml import Event + +from icalendar import Calendar +from email import message +from email import message_from_string +from wallace import module_resources +from twisted.trial import unittest + +# define some iTip MIME messages + +itip_multipart = """MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_c8894dbdb8baeedacae836230e3436fd" +From: "Doe, John" <john.doe@example.org> +Date: Fri, 13 Jul 2012 13:54:14 +0100 +Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org> +User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0 +To: resource-collection-car@example.org +Subject: "test" has been updated + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +*test* + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/calendar; charset=UTF-8; method=REQUEST; + name=event.ics +Content-Disposition: attachment; + filename=event.ics +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 +DTSTAMP:20120713T1254140 +DTSTART;TZID=3DEurope/London:20120713T100000 +DTEND;TZID=3DEurope/London:20120713T110000 +SUMMARY:test +DESCRIPTION:test +ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt= +o:resource-collection-car@example.org +ATTENDEE;ROLE=3DOPT-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailto:anoth= +er-resource@example.org +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--=_c8894dbdb8baeedacae836230e3436fd-- +""" + +itip_non_multipart = """Return-Path: <john.doe@example.org> +Sender: john.doe@example.org +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: quoted-printable +To: resource-collection-car@example.org +From: john.doe@example.org +Date: Mon, 24 Feb 2014 11:27:28 +0100 +Message-ID: <1a3aa8995e83dd24cf9247e538ac913a@example.org> +Subject: test + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 +DTSTAMP:20120713T1254140 +DTSTART;TZID=3DEurope/London:20120713T100000 +DTEND;TZID=3DEurope/London:20120713T110000 +SUMMARY:test +DESCRIPTION:test +ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DACCEPTED;RSVP=3DTRUE:mailt= +o:resource-collection-car@example.org +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR +""" + +itip_google_multipart = """MIME-Version: 1.0 +Message-ID: <001a11c2ad84243e0604f3246bae@google.com> +Date: Mon, 24 Feb 2014 10:27:28 +0000 +Subject: =?ISO-8859-1?Q?Invitation=3A_iTip_from_Apple_=40_Mon_Feb_24=2C_2014_12pm_?= + =?ISO-8859-1?Q?=2D_1pm_=28Tom_=26_T=E4m=29?= +From: "john.doe" <john.doe@gmail.com> +To: <john.sample@example.org> +Content-Type: multipart/mixed; boundary=001a11c2ad84243df004f3246bad + +--001a11c2ad84243df004f3246bad +Content-Type: multipart/alternative; boundary=001a11c2ad84243dec04f3246bab + +--001a11c2ad84243dec04f3246bab +Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes + +<some text content here> + +--001a11c2ad84243dec04f3246bab +Content-Type: text/html; charset=ISO-8859-1 +Content-Transfer-Encoding: quoted-printable + +<div style=3D""><!-- some HTML message content here --></div> +--001a11c2ad84243dec04f3246bab +Content-Type: text/calendar; charset=UTF-8; method=REQUEST +Content-Transfer-Encoding: 7bit + +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +DTSTART:20140224T110000Z +DTEND:20140224T120000Z +DTSTAMP:20140224T102728Z +ORGANIZER:mailto:kepjllr6mcq7d0959u4cdc7000@group.calendar.google.com +UID:0BE2F640-5814-47C9-ABAE-E7E959204E76 +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE + ;X-NUM-GUESTS=0:mailto:kepjllr6mcq7d0959u4cdc7000@group.calendar.google.com +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP= + TRUE;CN=John Sample;X-NUM-GUESTS=0:mailto:john.sample@example.org +CREATED:20140224T102728Z +DESCRIPTION:Testing Multipart structure\\nView your event at http://www.goog + le.com/calendar/event?action=VIEW&eid=XzYxMTRhY2k2Nm9xMzBiOWw3MG9qOGI5azZ0M + WppYmExODkwa2FiYTU2dDJqaWQ5cDY4bzM4aDluNm8gdGhvbWFzQGJyb3RoZXJsaS5jaA&tok=N + TIja2VwamxscjZtY3E3ZDA5NTl1NGNkYzcwMDBAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbTkz + NTcyYTU2YmUwNWMxNjY0Zjc3OTU0MzhmMDcwY2FhN2NjZjIzYWM&ctz=Europe/Zurich&hl=en + . +LAST-MODIFIED:20140224T102728Z +LOCATION: +SEQUENCE:5 +STATUS:CONFIRMED +SUMMARY:iTip from Apple +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--001a11c2ad84243dec04f3246bab-- +--001a11c2ad84243df004f3246bad +Content-Type: application/ics; name="invite.ics" +Content-Disposition: attachment; filename="invite.ics" +Content-Transfer-Encoding: base64 + +QkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vR29vZ2xlIEluYy8vR29vZ2xlIENhbGVuZGFyIDcw +LjkwNTQvL0VODQpWRVJTSU9OOjIuMA0KQ0FMU0NBTEU6R1JFR09SSUFODQpNRVRIT0Q6UkVRVUVT +VA0KQkVHSU46VkVWRU5UDQpEVFNUQVJUOjIwMTQwMjI0VDExMDAwMFoNCkRURU5EOjIwMTQwMjI0 +VDEyMDAwMFoNCkRUU1RBTVA6MjAxNDAyMjRUMTAyNzI4Wg0KT1JHQU5JWkVSOm1haWx0bzprZXBq +bGxyNm1jcTdkMDk1OXU0Y2RjNzAwMEBncm91cC5jYWxlbmRhci5nb29nbGUuY29tDQpVSUQ6MEJF +MkY2NDAtNTgxNC00N0M5LUFCQUUtRTdFOTU5MjA0RTc2DQpBVFRFTkRFRTtDVVRZUEU9SU5ESVZJ +RFVBTDtST0xFPVJFUS1QQVJUSUNJUEFOVDtQQVJUU1RBVD1BQ0NFUFRFRDtSU1ZQPVRSVUUNCiA7 +WC1OVU0tR1VFU1RTPTA6bWFpbHRvOmtlcGpsbHI2bWNxN2QwOTU5dTRjZGM3MDAwQGdyb3VwLmNh +bGVuZGFyLmdvb2dsZS5jb20NCkFUVEVOREVFO0NVVFlQRT1JTkRJVklEVUFMO1JPTEU9UkVRLVBB +UlRJQ0lQQU5UO1BBUlRTVEFUPU5FRURTLUFDVElPTjtSU1ZQPQ0KIFRSVUU7WC1OVU0tR1VFU1RT +PTA6bWFpbHRvOnRob21hc0Bicm90aGVybGkuY2gNCkFUVEVOREVFO0NVVFlQRT1JTkRJVklEVUFM +O1JPTEU9UkVRLVBBUlRJQ0lQQU5UO1BBUlRTVEFUPU5FRURTLUFDVElPTjtSU1ZQPQ0KIFRSVUU7 +Q049VGhvbWFzIEJydWVkZXJsaTtYLU5VTS1HVUVTVFM9MDptYWlsdG86cm91bmRjdWJlQGdtYWls +LmNvbQ0KQ1JFQVRFRDoyMDE0MDIyNFQxMDI3MjhaDQpERVNDUklQVElPTjpUZXN0aW5nIE11bHRp +cGFydCBzdHJ1Y3R1cmVcblZpZXcgeW91ciBldmVudCBhdCBodHRwOi8vd3d3Lmdvb2cNCiBsZS5j +b20vY2FsZW5kYXIvZXZlbnQ/YWN0aW9uPVZJRVcmZWlkPVh6WXhNVFJoWTJrMk5tOXhNekJpT1d3 +M01HOXFPR0k1YXpaME0NCiBXcHBZbUV4T0Rrd2EyRmlZVFUyZERKcWFXUTVjRFk0YnpNNGFEbHVO +bThnZEdodmJXRnpRR0p5YjNSb1pYSnNhUzVqYUEmdG9rPU4NCiBUSWphMlZ3YW14c2NqWnRZM0Uz +WkRBNU5UbDFOR05rWXpjd01EQkFaM0p2ZFhBdVkyRnNaVzVrWVhJdVoyOXZaMnhsTG1OdmJUa3oN +CiBOVGN5WVRVMlltVXdOV014TmpZMFpqYzNPVFUwTXpobU1EY3dZMkZoTjJOalpqSXpZV00mY3R6 +PUV1cm9wZS9adXJpY2gmaGw9ZW4NCiAuDQpMQVNULU1PRElGSUVEOjIwMTQwMjI0VDEwMjcyOFoN +CkxPQ0FUSU9OOg0KU0VRVUVOQ0U6NQ0KU1RBVFVTOkNPTkZJUk1FRA0KU1VNTUFSWTppVGlwIGZy +b20gQXBwbGUNClRSQU5TUDpPUEFRVUUNCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVINCg== +--001a11c2ad84243df004f3246bad-- +""" + +itip_application_ics = """MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_c8894dbdb8baeedacae836230e3436fd" +From: "Doe, John" <john.doe@example.org> +Date: Fri, 13 Jul 2012 13:54:14 +0100 +Message-ID: <240fe7ae7e139129e9eb95213c101622@example.org> +User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0 +To: resource-collection-car@example.org +Subject: "test" has been updated + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Transfer-Encoding: quoted-printable +Content-Type: text/plain; charset=UTF-8; format=flowed + +<some text here> + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: application/ics; charset=UTF-8; method=REQUEST; + name=event.ics +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 +DTSTAMP:20120713T1254140 +DTSTART;TZID=3DEurope/London:20120713T100000 +DTEND;TZID=3DEurope/London:20120713T110000 +SUMMARY:test +DESCRIPTION:test +ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt= +o:resource-collection-car@example.org +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--=_c8894dbdb8baeedacae836230e3436fd-- +""" + +itip_recurring = """Return-Path: <john.doe@example.org> +Sender: john.doe@example.org +Content-Type: text/calendar; method=REQUEST; charset=UTF-8 +Content-Transfer-Encoding: 8bit +From: john.doe@example.org +Date: Mon, 24 Feb 2014 11:27:28 +0100 +Message-ID: <1a3aa8995e83dd24cf9247e538ac913a@example.org> +Subject: Recurring + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Apple Inc.//Mac OS X 10.9.2//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:dbdb8baeedacae836230e3436fd-5e83dd24cf92 +DTSTAMP:20140213T1254140 +DTSTART;TZID=Europe/London:20120709T100000 +DTEND;TZID=Europe/London:20120709T120000 +RRULE:FREQ=DAILY;INTERVAL=1;COUNT=5 +SUMMARY:Recurring +ORGANIZER;CN="Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=REQ-PARTICIPANT;CUTYPE=RESOURCE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:jane@example.com +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR +""" + +itip_empty = """MIME-Version: 1.0 +Date: Fri, 17 Jan 2014 13:51:50 +0100 +From: <john.doe@example.org> +User-Agent: Roundcube Webmail/0.9.5 +To: john.sample@example.org +Subject: "test" has been sent +Message-ID: <52D92766.5040508@somedomain.com> +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit + +Message plain text goes here... +""" + +conf = pykolab.getConf() + +if not hasattr(conf, 'defaults'): + conf.finalize_conf() + +class TestITip(unittest.TestCase): + + def setUp(self): + # intercept calls to smtplib.SMTP.sendmail() + import smtplib + self.patch(smtplib.SMTP, "__init__", self._mock_smtp_init) + self.patch(smtplib.SMTP, "quit", self._mock_nop) + self.patch(smtplib.SMTP, "sendmail", self._mock_smtp_sendmail) + + self.smtplog = []; + + def _mock_nop(self, domain=None): + pass + + def _mock_smtp_init(self, host=None, port=None, local_hostname=None, timeout=0): + pass + + def _mock_smtp_sendmail(self, from_addr, to_addr, message, mail_options=None, rcpt_options=None): + self.smtplog.append((from_addr, to_addr, message)) + + + def test_001_itip_events_from_message(self): + itips1 = itip.events_from_message(message_from_string(itip_multipart)) + self.assertEqual(len(itips1), 1, "Multipart iTip message with text/calendar") + self.assertEqual(itips1[0]['method'], "REQUEST", "iTip request method property") + + itips2 = itip.events_from_message(message_from_string(itip_non_multipart)) + self.assertEqual(len(itips2), 1, "Detect non-multipart iTip messages") + + itips3 = itip.events_from_message(message_from_string(itip_application_ics)) + self.assertEqual(len(itips3), 1, "Multipart iTip message with application/ics attachment") + + itips4 = itip.events_from_message(message_from_string(itip_google_multipart)) + self.assertEqual(len(itips4), 1, "Multipart iTip message from Google") + + itips5 = itip.events_from_message(message_from_string(itip_empty)) + self.assertEqual(len(itips5), 0, "Simple plain text message") + + # invalid itip blocks + self.assertRaises(Exception, itip.events_from_message, message_from_string(itip_multipart.replace("BEGIN:VEVENT", ""))) + + itips6 = itip.events_from_message(message_from_string(itip_multipart.replace("DTSTART;", "X-DTSTART;"))) + self.assertEqual(len(itips6), 0, "Event with not DTSTART") + + itips7 = itip.events_from_message(message_from_string(itip_non_multipart.replace("METHOD:REQUEST", "METHOD:PUBLISH").replace("method=REQUEST", "method=PUBLISH"))) + self.assertEqual(len(itips7), 0, "Invalid METHOD") + + + def test_002_check_date_conflict(self): + astart = datetime.datetime(2014,7,13, 10,0,0) + aend = astart + datetime.timedelta(hours=2) + + bstart = datetime.datetime(2014,7,13, 10,0,0) + bend = astart + datetime.timedelta(hours=1) + self.assertTrue(itip.check_date_conflict(astart, aend, bstart, bend)) + + bstart = datetime.datetime(2014,7,13, 11,0,0) + bend = astart + datetime.timedelta(minutes=30) + self.assertTrue(itip.check_date_conflict(astart, aend, bstart, bend)) + + bend = astart + datetime.timedelta(hours=2) + self.assertTrue(itip.check_date_conflict(astart, aend, bstart, bend)) + + bstart = datetime.datetime(2014,7,13, 12,0,0) + bend = astart + datetime.timedelta(hours=1) + self.assertFalse(itip.check_date_conflict(astart, aend, bstart, bend)) + + bstart = datetime.datetime(2014,6,13, 10,0,0) + bend = datetime.datetime(2014,6,14, 12,0,0) + self.assertFalse(itip.check_date_conflict(astart, aend, bstart, bend)) + + bstart = datetime.datetime(2014,7,10, 12,0,0) + bend = datetime.datetime(2014,7,14, 14,0,0) + self.assertTrue(itip.check_date_conflict(astart, aend, bstart, bend)) + + + def test_002_check_event_conflict(self): + itip_event = itip.events_from_message(message_from_string(itip_non_multipart))[0] + + event = Event() + event.set_start(datetime.datetime(2012,7,13, 9,30,0, tzinfo=itip_event['start'].tzinfo)) + event.set_end(datetime.datetime(2012,7,13, 10,30,0, tzinfo=itip_event['start'].tzinfo)) + + self.assertTrue(itip.check_event_conflict(event, itip_event), "Conflicting dates") + + event.set_uid(itip_event['uid']) + self.assertFalse(itip.check_event_conflict(event, itip_event), "No conflict for same UID") + + allday = Event() + allday.set_start(datetime.date(2012,7,13)) + allday.set_end(datetime.date(2012,7,13)) + + self.assertTrue(itip.check_event_conflict(allday, itip_event), "Conflicting allday event") + + event2 = Event() + event2.set_start(datetime.datetime(2012,7,13, 10,0,0, tzinfo=pytz.timezone("US/Central"))) + event2.set_end(datetime.datetime(2012,7,13, 11,0,0, tzinfo=pytz.timezone("US/Central"))) + + self.assertFalse(itip.check_event_conflict(event, itip_event), "No conflict with timezone shift") + + rrule = kolabformat.RecurrenceRule() + rrule.setFrequency(kolabformat.RecurrenceRule.Weekly) + rrule.setCount(10) + + event3 = Event() + event3.set_recurrence(rrule); + event3.set_start(datetime.datetime(2012,6,29, 9,30,0, tzinfo=pytz.utc)) + event3.set_end(datetime.datetime(2012,6,29, 10,30,0, tzinfo=pytz.utc)) + + self.assertTrue(itip.check_event_conflict(event3, itip_event), "Conflict in (3rd) recurring event instance") + + itip_event = itip.events_from_message(message_from_string(itip_recurring))[0] + self.assertTrue(itip.check_event_conflict(event3, itip_event), "Conflict in two recurring events") + + event4 = Event() + event4.set_recurrence(rrule); + event4.set_start(datetime.datetime(2012,7,1, 9,30,0, tzinfo=pytz.utc)) + event4.set_end(datetime.datetime(2012,7,1, 10,30,0, tzinfo=pytz.utc)) + self.assertFalse(itip.check_event_conflict(event4, itip_event), "No conflict in two recurring events") + + + def test_003_send_reply(self): + itip_events = itip.events_from_message(message_from_string(itip_non_multipart)) + itip.send_reply("resource-collection-car@example.org", itip_events, "SUMMARY=%(summary)s; STATUS=%(status)s; NAME=%(name)s;") + + self.assertEqual(len(self.smtplog), 1) + self.assertEqual(self.smtplog[0][0], 'resource-collection-car@example.org', "From attendee") + self.assertEqual(self.smtplog[0][1], 'john.doe@example.org', "To organizer") + + message = message_from_string(self.smtplog[0][2]) + self.assertEqual(message.get('Subject'), 'Invitation for test was ACCEPTED') + + text = str(message.get_payload(0)); + self.assertIn('SUMMARY=test', text) + self.assertIn('STATUS=ACCEPTED', text)
View file
pykolab-0.7.tar.gz/tests/unit/test-011-wallace_resources.py
Changed
@@ -2,6 +2,7 @@ import logging import datetime +from pykolab import itip from icalendar import Calendar from email import message from email import message_from_string @@ -87,152 +88,6 @@ END:VCALENDAR """ -itip_google_multipart = """MIME-Version: 1.0 -Message-ID: <001a11c2ad84243e0604f3246bae@google.com> -Date: Mon, 24 Feb 2014 10:27:28 +0000 -Subject: =?ISO-8859-1?Q?Invitation=3A_iTip_from_Apple_=40_Mon_Feb_24=2C_2014_12pm_?= - =?ISO-8859-1?Q?=2D_1pm_=28Tom_=26_T=E4m=29?= -From: "john.doe" <john.doe@gmail.com> -To: <john.sample@example.org> -Content-Type: multipart/mixed; boundary=001a11c2ad84243df004f3246bad - ---001a11c2ad84243df004f3246bad -Content-Type: multipart/alternative; boundary=001a11c2ad84243dec04f3246bab - ---001a11c2ad84243dec04f3246bab -Content-Type: text/plain; charset=ISO-8859-1; format=flowed; delsp=yes - -<some text content here> - ---001a11c2ad84243dec04f3246bab -Content-Type: text/html; charset=ISO-8859-1 -Content-Transfer-Encoding: quoted-printable - -<div style=3D""><!-- some HTML message content here --></div> ---001a11c2ad84243dec04f3246bab -Content-Type: text/calendar; charset=UTF-8; method=REQUEST -Content-Transfer-Encoding: 7bit - -BEGIN:VCALENDAR -PRODID:-//Google Inc//Google Calendar 70.9054//EN -VERSION:2.0 -CALSCALE:GREGORIAN -METHOD:REQUEST -BEGIN:VEVENT -DTSTART:20140224T110000Z -DTEND:20140224T120000Z -DTSTAMP:20140224T102728Z -ORGANIZER:mailto:kepjllr6mcq7d0959u4cdc7000@group.calendar.google.com -UID:0BE2F640-5814-47C9-ABAE-E7E959204E76 -ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE - ;X-NUM-GUESTS=0:mailto:kepjllr6mcq7d0959u4cdc7000@group.calendar.google.com -ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP= - TRUE;CN=John Sample;X-NUM-GUESTS=0:mailto:john.sample@example.org -CREATED:20140224T102728Z -DESCRIPTION:Testing Multipart structure\\nView your event at http://www.goog - le.com/calendar/event?action=VIEW&eid=XzYxMTRhY2k2Nm9xMzBiOWw3MG9qOGI5azZ0M - WppYmExODkwa2FiYTU2dDJqaWQ5cDY4bzM4aDluNm8gdGhvbWFzQGJyb3RoZXJsaS5jaA&tok=N - TIja2VwamxscjZtY3E3ZDA5NTl1NGNkYzcwMDBAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbTkz - NTcyYTU2YmUwNWMxNjY0Zjc3OTU0MzhmMDcwY2FhN2NjZjIzYWM&ctz=Europe/Zurich&hl=en - . -LAST-MODIFIED:20140224T102728Z -LOCATION: -SEQUENCE:5 -STATUS:CONFIRMED -SUMMARY:iTip from Apple -TRANSP:OPAQUE -END:VEVENT -END:VCALENDAR - ---001a11c2ad84243dec04f3246bab-- ---001a11c2ad84243df004f3246bad -Content-Type: application/ics; name="invite.ics" -Content-Disposition: attachment; filename="invite.ics" -Content-Transfer-Encoding: base64 - -QkVHSU46VkNBTEVOREFSDQpQUk9ESUQ6LS8vR29vZ2xlIEluYy8vR29vZ2xlIENhbGVuZGFyIDcw -LjkwNTQvL0VODQpWRVJTSU9OOjIuMA0KQ0FMU0NBTEU6R1JFR09SSUFODQpNRVRIT0Q6UkVRVUVT -VA0KQkVHSU46VkVWRU5UDQpEVFNUQVJUOjIwMTQwMjI0VDExMDAwMFoNCkRURU5EOjIwMTQwMjI0 -VDEyMDAwMFoNCkRUU1RBTVA6MjAxNDAyMjRUMTAyNzI4Wg0KT1JHQU5JWkVSOm1haWx0bzprZXBq -bGxyNm1jcTdkMDk1OXU0Y2RjNzAwMEBncm91cC5jYWxlbmRhci5nb29nbGUuY29tDQpVSUQ6MEJF -MkY2NDAtNTgxNC00N0M5LUFCQUUtRTdFOTU5MjA0RTc2DQpBVFRFTkRFRTtDVVRZUEU9SU5ESVZJ -RFVBTDtST0xFPVJFUS1QQVJUSUNJUEFOVDtQQVJUU1RBVD1BQ0NFUFRFRDtSU1ZQPVRSVUUNCiA7 -WC1OVU0tR1VFU1RTPTA6bWFpbHRvOmtlcGpsbHI2bWNxN2QwOTU5dTRjZGM3MDAwQGdyb3VwLmNh -bGVuZGFyLmdvb2dsZS5jb20NCkFUVEVOREVFO0NVVFlQRT1JTkRJVklEVUFMO1JPTEU9UkVRLVBB -UlRJQ0lQQU5UO1BBUlRTVEFUPU5FRURTLUFDVElPTjtSU1ZQPQ0KIFRSVUU7WC1OVU0tR1VFU1RT -PTA6bWFpbHRvOnRob21hc0Bicm90aGVybGkuY2gNCkFUVEVOREVFO0NVVFlQRT1JTkRJVklEVUFM -O1JPTEU9UkVRLVBBUlRJQ0lQQU5UO1BBUlRTVEFUPU5FRURTLUFDVElPTjtSU1ZQPQ0KIFRSVUU7 -Q049VGhvbWFzIEJydWVkZXJsaTtYLU5VTS1HVUVTVFM9MDptYWlsdG86cm91bmRjdWJlQGdtYWls -LmNvbQ0KQ1JFQVRFRDoyMDE0MDIyNFQxMDI3MjhaDQpERVNDUklQVElPTjpUZXN0aW5nIE11bHRp -cGFydCBzdHJ1Y3R1cmVcblZpZXcgeW91ciBldmVudCBhdCBodHRwOi8vd3d3Lmdvb2cNCiBsZS5j -b20vY2FsZW5kYXIvZXZlbnQ/YWN0aW9uPVZJRVcmZWlkPVh6WXhNVFJoWTJrMk5tOXhNekJpT1d3 -M01HOXFPR0k1YXpaME0NCiBXcHBZbUV4T0Rrd2EyRmlZVFUyZERKcWFXUTVjRFk0YnpNNGFEbHVO -bThnZEdodmJXRnpRR0p5YjNSb1pYSnNhUzVqYUEmdG9rPU4NCiBUSWphMlZ3YW14c2NqWnRZM0Uz -WkRBNU5UbDFOR05rWXpjd01EQkFaM0p2ZFhBdVkyRnNaVzVrWVhJdVoyOXZaMnhsTG1OdmJUa3oN -CiBOVGN5WVRVMlltVXdOV014TmpZMFpqYzNPVFUwTXpobU1EY3dZMkZoTjJOalpqSXpZV00mY3R6 -PUV1cm9wZS9adXJpY2gmaGw9ZW4NCiAuDQpMQVNULU1PRElGSUVEOjIwMTQwMjI0VDEwMjcyOFoN -CkxPQ0FUSU9OOg0KU0VRVUVOQ0U6NQ0KU1RBVFVTOkNPTkZJUk1FRA0KU1VNTUFSWTppVGlwIGZy -b20gQXBwbGUNClRSQU5TUDpPUEFRVUUNCkVORDpWRVZFTlQNCkVORDpWQ0FMRU5EQVINCg== ---001a11c2ad84243df004f3246bad-- -""" - -itip_application_ics = """MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="=_c8894dbdb8baeedacae836230e3436fd" -From: "Doe, John" <john.doe@example.org> -Date: Fri, 13 Jul 2012 13:54:14 +0100 -Message-ID: <240fe7ae7e139129e9eb95213c101622@example.org> -User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0 -To: resource-collection-car@example.org -Subject: "test" has been updated - ---=_c8894dbdb8baeedacae836230e3436fd -Content-Transfer-Encoding: quoted-printable -Content-Type: text/plain; charset=UTF-8; format=flowed - -<some text here> - ---=_c8894dbdb8baeedacae836230e3436fd -Content-Type: application/ics; charset=UTF-8; method=REQUEST; - name=event.ics -Content-Transfer-Encoding: quoted-printable - -BEGIN:VCALENDAR -VERSION:2.0 -PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN -CALSCALE:GREGORIAN -METHOD:REQUEST -BEGIN:VEVENT -UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 -DTSTAMP:20120713T1254140 -DTSTART;TZID=3DEurope/London:20120713T100000 -DTEND;TZID=3DEurope/London:20120713T110000 -SUMMARY:test -DESCRIPTION:test -ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org -ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt= -o:resource-collection-car@example.org -TRANSP:OPAQUE -END:VEVENT -END:VCALENDAR - ---=_c8894dbdb8baeedacae836230e3436fd-- -""" - -itip_empty = """MIME-Version: 1.0 -Date: Fri, 17 Jan 2014 13:51:50 +0100 -From: <john.doe@example.org> -User-Agent: Roundcube Webmail/0.9.5 -To: john.sample@example.org -Subject: "test" has been sent -Message-ID: <52D92766.5040508@somedomain.com> -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bit - -Message plain text goes here... -""" - - conf = pykolab.getConf() if not hasattr(conf, 'defaults'): @@ -272,7 +127,7 @@ def _mock_search_entry_by_attribute(self, attr, value, **kw): results = [] if value == "cn=Room 101,ou=Resources,dc=example,dc=org": - results.append({ 'dn': 'cn=Rooms,ou=Resources,dc=example,dc=org', attr: value, 'owner': 'uid=doe,ou=People,dc=example,dc=org' }) + results.append(('cn=Rooms,ou=Resources,dc=example,dc=org', { attr: value, 'owner': 'uid=doe,ou=People,dc=example,dc=org' })) return results def _mock_smtp_init(self, host=None, port=None, local_hostname=None, timeout=0): @@ -301,32 +156,6 @@ return None - def test_001_itip_events_from_message(self): - itips1 = module_resources.itip_events_from_message(message_from_string(itip_multipart)) - self.assertEqual(len(itips1), 1, "Multipart iTip message with text/calendar") - self.assertEqual(itips1[0]['method'], "REQUEST", "iTip request method property") - - itips2 = module_resources.itip_events_from_message(message_from_string(itip_non_multipart)) - self.assertEqual(len(itips2), 1, "Detect non-multipart iTip messages") - - itips3 = module_resources.itip_events_from_message(message_from_string(itip_application_ics)) - self.assertEqual(len(itips3), 1, "Multipart iTip message with application/ics attachment") - - itips4 = module_resources.itip_events_from_message(message_from_string(itip_google_multipart)) - self.assertEqual(len(itips4), 1, "Multipart iTip message from Google") - - itips5 = module_resources.itip_events_from_message(message_from_string(itip_empty)) - self.assertEqual(len(itips5), 0, "Simple plain text message") - - # invalid itip blocks - self.assertRaises(Exception, module_resources.itip_events_from_message, message_from_string(itip_multipart.replace("BEGIN:VEVENT", ""))) - - itips6 = module_resources.itip_events_from_message(message_from_string(itip_multipart.replace("DTSTART;", "X-DTSTART;"))) - self.assertEqual(len(itips6), 0, "Event with not DTSTART") - - itips7 = module_resources.itip_events_from_message(message_from_string(itip_non_multipart.replace("METHOD:REQUEST", "METHOD:PUBLISH").replace("method=REQUEST", "method=PUBLISH"))) - self.assertEqual(len(itips7), 0, "Invalid METHOD") - def test_002_resource_record_from_email_address(self): res = module_resources.resource_record_from_email_address("doe@example.org") @@ -337,7 +166,7 @@ def test_003_resource_records_from_itip_events(self): message = message_from_string(itip_multipart) - itips = module_resources.itip_events_from_message(message) + itips = itip.events_from_message(message) res = module_resources.resource_records_from_itip_events(itips) self.assertEqual(len(res), 2, "Return all attendee resources"); @@ -365,7 +194,7 @@ def test_005_send_response_accept(self): - itip_event = module_resources.itip_events_from_message(message_from_string(itip_non_multipart)) + itip_event = itip.events_from_message(message_from_string(itip_non_multipart)) module_resources.send_response("resource-collection-car@example.org", itip_event) self.assertEqual(len(self.smtplog), 1); @@ -384,7 +213,7 @@ def test_006_send_response_delegate(self): # delegate resource-collection-car@example.org => resource-car-audi-a4@example.org - itip_event = module_resources.itip_events_from_message(message_from_string(itip_non_multipart))[0] + itip_event = itip.events_from_message(message_from_string(itip_non_multipart))[0] itip_event['xml'].delegate('resource-collection-car@example.org', 'resource-car-audi-a4@example.org') itip_event['xml'].set_attendee_participant_status(itip_event['xml'].get_attendee('resource-car-audi-a4@example.org'), "ACCEPTED") @@ -408,30 +237,3 @@ self.assertEqual(ical2['attendee'].params['PARTSTAT'], "DELEGATED") - def test_007_check_date_conflict(self): - astart = datetime.datetime(2014,7,13, 10,0,0) - aend = astart + datetime.timedelta(hours=2) - - bstart = datetime.datetime(2014,7,13, 10,0,0) - bend = astart + datetime.timedelta(hours=1) - self.assertTrue(module_resources.check_date_conflict(astart, aend, bstart, bend)) - - bstart = datetime.datetime(2014,7,13, 11,0,0) - bend = astart + datetime.timedelta(minutes=30) - self.assertTrue(module_resources.check_date_conflict(astart, aend, bstart, bend)) - - bend = astart + datetime.timedelta(hours=2) - self.assertTrue(module_resources.check_date_conflict(astart, aend, bstart, bend)) - - bstart = datetime.datetime(2014,7,13, 12,0,0) - bend = astart + datetime.timedelta(hours=1) - self.assertFalse(module_resources.check_date_conflict(astart, aend, bstart, bend)) - - bstart = datetime.datetime(2014,6,13, 10,0,0) - bend = datetime.datetime(2014,6,14, 12,0,0) - self.assertFalse(module_resources.check_date_conflict(astart, aend, bstart, bend)) - - bstart = datetime.datetime(2014,7,10, 12,0,0) - bend = datetime.datetime(2014,7,14, 14,0,0) - self.assertTrue(module_resources.check_date_conflict(astart, aend, bstart, bend)) -
View file
pykolab-0.7.tar.gz/tests/unit/test-012-wallace_invitationpolicy.py
Added
@@ -0,0 +1,161 @@ +import os +import pykolab +import logging +import time + +from icalendar import Calendar +from email import message +from email import message_from_string +from wallace import module_invitationpolicy as MIP +from twisted.trial import unittest + +from pykolab.auth.ldap import LDAP +from pykolab.constants import * + + +# define some iTip MIME messages + +itip_multipart = """MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=_c8894dbdb8baeedacae836230e3436fd" +From: "Doe, John" <john.doe@example.org> +Date: Fri, 13 Jul 2012 13:54:14 +0100 +Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org> +User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0 +To: jane.doe@example.org +Subject: "test" has been updated + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: quoted-printable + +*test* + +--=_c8894dbdb8baeedacae836230e3436fd +Content-Type: text/calendar; charset=UTF-8; method=REQUEST; + name=event.ics +Content-Disposition: attachment; + filename=event.ics +Content-Transfer-Encoding: quoted-printable + +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Roundcube Webmail 1.0.1//NONSGML Calendar//EN +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VEVENT +UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271 +DTSTAMP:20120713T125414Z +DTSTART;TZID=3DEurope/London:20120713T100000 +DTEND;TZID=3DEurope/London:20120713T110000 +SUMMARY:test +DESCRIPTION:test +ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org +ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt= +o:jane.doe@example.org +ATTENDEE;ROLE=3DOPT-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt= +user.external@example.com +SEQUENCE:1 +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + +--=_c8894dbdb8baeedacae836230e3436fd-- +""" + +conf = pykolab.getConf() + +if not hasattr(conf, 'defaults'): + conf.finalize_conf() + +class TestWallaceInvitationpolicy(unittest.TestCase): + + def setUp(self): + # monkey-patch the pykolab.auth module to check API calls + # without actually connecting to LDAP + self.patch(pykolab.auth.Auth, "connect", self._mock_nop) + self.patch(pykolab.auth.Auth, "disconnect", self._mock_nop) + self.patch(pykolab.auth.Auth, "find_user_dn", self._mock_find_user_dn) + self.patch(pykolab.auth.Auth, "get_entry_attributes", self._mock_get_entry_attributes) + + # intercept calls to smtplib.SMTP.sendmail() + import smtplib + self.patch(smtplib.SMTP, "__init__", self._mock_smtp_init) + self.patch(smtplib.SMTP, "quit", self._mock_nop) + self.patch(smtplib.SMTP, "sendmail", self._mock_smtp_sendmail) + + self.smtplog = []; + + def _mock_find_user_dn(self, value, kolabuser=False): + (prefix, domain) = value.split('@') + return "uid=" + prefix + ",ou=People,dc=" + ",dc=".join(domain.split('.')) + + def _mock_get_entry_attributes(self, domain, entry, attributes): + (_, uid) = entry.split(',')[0].split('=') + return { 'cn': uid, 'mail': uid + "@example.org", '_attrib': attributes } + + def _mock_nop(self, domain=None): + pass + + def _mock_smtp_init(self, host=None, port=None, local_hostname=None, timeout=0): + pass + + def _mock_smtp_sendmail(self, from_addr, to_addr, message, mail_options=None, rcpt_options=None): + self.smtplog.append((from_addr, to_addr, message)) + + def test_001_itip_events_from_message(self): + itips = pykolab.itip.events_from_message(message_from_string(itip_multipart)) + self.assertEqual(len(itips), 1, "Multipart iTip message with text/calendar") + self.assertEqual(itips[0]['method'], "REQUEST", "iTip request method property") + self.assertEqual(len(itips[0]['attendees']), 2, "List attendees from iTip") + self.assertEqual(itips[0]['attendees'][0], "mailto:jane.doe@example.org", "First attendee from iTip") + + def test_002_user_dn_from_email_address(self): + res = MIP.user_dn_from_email_address("doe@example.org") + # assert call to (patched) pykolab.auth.Auth.find_resource() + self.assertEqual("uid=doe,ou=People,dc=example,dc=org", res); + + def test_003_get_matching_invitation_policy(self): + user = { 'kolabinvitationpolicy': [ + 'ACT_ACCEPT:example.org', + 'ACT_REJECT:gmail.com', + 'ACT_MANUAL:*' + ] } + self.assertEqual(MIP.get_matching_invitation_policies(user, 'fastmail.net'), [MIP.ACT_MANUAL]) + self.assertEqual(MIP.get_matching_invitation_policies(user, 'example.org'), [MIP.ACT_ACCEPT,MIP.ACT_MANUAL]) + self.assertEqual(MIP.get_matching_invitation_policies(user, 'gmail.com'), [MIP.ACT_REJECT,MIP.ACT_MANUAL]) + + user = { 'kolabinvitationpolicy': ['ACT_ACCEPT:example.org', 'ACT_MANUAL:others'] } + self.assertEqual(MIP.get_matching_invitation_policies(user, 'somedomain.net'), [MIP.ACT_MANUAL]) + + def test_004_write_locks(self): + user = { 'cn': 'John Doe', 'mail': "doe@example.org" } + + lock_key = MIP.get_lock_key(user, '1234567890-abcdef') + lock_file = os.path.join(MIP.mybasepath, 'locks', lock_key + '.lock') + MIP.set_write_lock(lock_key) + + time.sleep(1) + self.assertTrue(os.path.isfile(lock_file)) + self.assertFalse(MIP.set_write_lock(lock_key, False)) + + MIP.remove_write_lock(lock_key) + self.assertFalse(os.path.isfile(lock_file)) + + def test_005_is_auto_reply(self): + all_manual = [ 'ACT_MANUAL' ] + accept_none = [ 'ACT_REJECT' ] + accept_all = [ 'ACT_ACCEPT', 'ACT_UPDATE' ] + accept_cond = [ 'ACT_ACCEPT_IF_NO_CONFLICT', 'ACT_REJECT_IF_CONFLICT' ] + accept_some = [ 'ACT_ACCEPT_IF_NO_CONFLICT', 'ACT_SAVE_TO_CALENDAR:example.org', 'ACT_REJECT_IF_CONFLICT' ] + accept_avail = [ 'ACT_ACCEPT_IF_NO_CONFLICT', 'ACT_REJECT_IF_CONFLICT:example.org' ] + + self.assertFalse( MIP.is_auto_reply({ 'kolabinvitationpolicy':all_manual }, 'domain.org')) + self.assertTrue( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_none }, 'domain.org')) + self.assertTrue( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_all }, 'domain.com')) + self.assertTrue( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_cond }, 'domain.com')) + self.assertTrue( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_some }, 'domain.com')) + self.assertFalse( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_some }, 'example.org')) + self.assertFalse( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_avail }, 'domain.com')) + self.assertTrue( MIP.is_auto_reply({ 'kolabinvitationpolicy':accept_avail }, 'example.org')) + \ No newline at end of file
View file
pykolab-0.7.tar.gz/tests/unit/test-015-platform.py
Added
@@ -0,0 +1,25 @@ +import unittest + +from pykolab.setup.facts import platform, config_service, control_service + +class TestPlatform(unittest.TestCase): + def assertIsInstance(self, _value, _type): + if hasattr(unittest.TestCase, 'assertIsInstance'): + return unittest.TestCase.assertIsInstance(self, _value, _type) + else: + if (type(_value)) == _type: + return True + else: + raise AssertionError, "%s != %s" % (type(_value), _type) + + def test_001_platform(self): + self.assertIsInstance(platform, str) + + def test_002_config_service(self): + self.assertEqual(config_service('enable', 'httpd'), "stomet") + + def test_003_control_service(self): + self.assertEqual(control_service('start', 'httpd'), "stomet") + +if __name__ == '__main__': + unittest.main()
View file
pykolab-0.7.tar.gz/tests/unit/test-015-translate.py
Added
@@ -0,0 +1,23 @@ +import unittest +import gettext +from pykolab import translate + +class TestTranslate(unittest.TestCase): + + def test_001_default_langs(self): + self.assertTrue(len(translate.getDefaultLangs()) > 0) + + def test_002_translate(self): + from pykolab.translate import _ + self.assertEqual(_("Folder name"), "Folder name") + + def test_003_set_lang(self): + from pykolab.translate import _ + self.assertEqual(_("Folder name"), "Folder name") + translate.setUserLanguage('de_DE') + self.assertEqual(_("Folder name"), "Ordnername", "German Translation found") + translate.setUserLanguage('foo_bar') + self.assertEqual(_("Folder name"), "Folder name", "Unkonwn language falls back to NullTranslations") + +if __name__ == '__main__': + unittest.main()
View file
pykolab-0.7.tar.gz/ucs/listener.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # # workaround for PEP 366
View file
pykolab-0.7.tar.gz/wallace.py
Changed
@@ -4,18 +4,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import sys
View file
pykolab-0.7.tar.gz/wallace/__init__.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import asyncore
View file
pykolab-0.7.tar.gz/wallace/module_footer.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
View file
pykolab-0.7.tar.gz/wallace/module_invitationpolicy.py
Added
@@ -0,0 +1,1015 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 Kolab Systems AG (http://www.kolabsys.com) +# +# Thomas Bruederli (Kolab Systems) <bruederli@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 datetime +import os +import tempfile +import time +from urlparse import urlparse +import urllib +import hashlib + +from email import message_from_string +from email.parser import Parser +from email.utils import formataddr +from email.utils import getaddresses + +import modules + +import pykolab +import kolabformat + +from pykolab import utils +from pykolab.auth import Auth +from pykolab.conf import Conf +from pykolab.imap import IMAP +from pykolab.xml import to_dt +from pykolab.xml import event_from_message +from pykolab.xml import participant_status_label +from pykolab.itip import events_from_message +from pykolab.itip import check_event_conflict +from pykolab.itip import send_reply +from pykolab.translate import _ + +# define some contstants used in the code below +COND_IF_AVAILABLE = 32 +COND_IF_CONFLICT = 64 +COND_TENTATIVE = 128 +COND_NOTIFY = 256 +ACT_MANUAL = 1 +ACT_ACCEPT = 2 +ACT_DELEGATE = 4 +ACT_REJECT = 8 +ACT_UPDATE = 16 +ACT_TENTATIVE = ACT_ACCEPT + COND_TENTATIVE +ACT_ACCEPT_IF_NO_CONFLICT = ACT_ACCEPT + COND_IF_AVAILABLE +ACT_TENTATIVE_IF_NO_CONFLICT = ACT_ACCEPT + COND_TENTATIVE + COND_IF_AVAILABLE +ACT_DELEGATE_IF_CONFLICT = ACT_DELEGATE + COND_IF_CONFLICT +ACT_REJECT_IF_CONFLICT = ACT_REJECT + COND_IF_CONFLICT +ACT_UPDATE_AND_NOTIFY = ACT_UPDATE + COND_NOTIFY +ACT_SAVE_TO_CALENDAR = 512 + +FOLDER_TYPE_ANNOTATION = '/vendor/kolab/folder-type' + +MESSAGE_PROCESSED = 1 +MESSAGE_FORWARD = 2 + +policy_name_map = { + 'ACT_MANUAL': ACT_MANUAL, + 'ACT_ACCEPT': ACT_ACCEPT, + 'ACT_ACCEPT_IF_NO_CONFLICT': ACT_ACCEPT_IF_NO_CONFLICT, + 'ACT_TENTATIVE': ACT_TENTATIVE, + 'ACT_TENTATIVE_IF_NO_CONFLICT': ACT_TENTATIVE_IF_NO_CONFLICT, + 'ACT_DELEGATE': ACT_DELEGATE, + 'ACT_DELEGATE_IF_CONFLICT': ACT_DELEGATE_IF_CONFLICT, + 'ACT_REJECT': ACT_REJECT, + 'ACT_REJECT_IF_CONFLICT': ACT_REJECT_IF_CONFLICT, + 'ACT_UPDATE': ACT_UPDATE, + 'ACT_UPDATE_AND_NOTIFY': ACT_UPDATE_AND_NOTIFY, + 'ACT_SAVE_TO_CALENDAR': ACT_SAVE_TO_CALENDAR +} + +policy_value_map = dict([(v, k) for (k, v) in policy_name_map.iteritems()]) + +log = pykolab.getLogger('pykolab.wallace') +conf = pykolab.getConf() + +mybasepath = '/var/spool/pykolab/wallace/invitationpolicy/' + +auth = None +imap = None +write_locks = [] + +def __init__(): + modules.register('invitationpolicy', execute, description=description()) + +def accept(filepath): + new_filepath = os.path.join( + mybasepath, + 'ACCEPT', + os.path.basename(filepath) + ) + + cleanup() + os.rename(filepath, new_filepath) + filepath = new_filepath + exec('modules.cb_action_ACCEPT(%r, %r)' % ('invitationpolicy',filepath)) + +def reject(filepath): + new_filepath = os.path.join( + mybasepath, + 'REJECT', + os.path.basename(filepath) + ) + + os.rename(filepath, new_filepath) + filepath = new_filepath + exec('modules.cb_action_REJECT(%r, %r)' % ('invitationpolicy',filepath)) + +def description(): + return """Invitation policy execution module.""" + +def cleanup(): + global auth, imap, write_locks + + log.debug("cleanup(): %r, %r" % (auth, imap), level=9) + + auth.disconnect() + del auth + + # Disconnect IMAP or we lock the mailbox almost constantly + imap.disconnect() + del imap + + # remove remaining write locks + for key in write_locks: + remove_write_lock(key, False) + +def execute(*args, **kw): + global auth, imap + + # (re)set language to default + pykolab.translate.setUserLanguage(conf.get('kolab','default_locale')) + + if not os.path.isdir(mybasepath): + os.makedirs(mybasepath) + + for stage in ['incoming', 'ACCEPT', 'REJECT', 'HOLD', 'DEFER', 'locks']: + if not os.path.isdir(os.path.join(mybasepath, stage)): + os.makedirs(os.path.join(mybasepath, stage)) + + log.debug(_("Invitation policy called for %r, %r") % (args, kw), level=9) + + auth = Auth() + imap = IMAP() + + filepath = args[0] + + # ignore calls on lock files + if '/locks/' in filepath or kw.has_key('stage') and kw['stage'] == 'locks': + return False + + log.debug("Invitation policy executing for %r, %r" % (filepath, '/locks/' in filepath), level=8) + + if kw.has_key('stage'): + 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'], + 'invitationpolicy', + filepath + ) + ) + + return filepath + else: + # Move to incoming + new_filepath = os.path.join( + mybasepath, + 'incoming', + os.path.basename(filepath) + ) + + if not filepath == new_filepath: + log.debug("Renaming %r to %r" % (filepath, new_filepath)) + os.rename(filepath, new_filepath) + filepath = new_filepath + + # parse full message + message = Parser().parse(open(filepath, 'r')) + + recipients = [address for displayname,address in getaddresses(message.get_all('X-Kolab-To'))] + sender_email = [address for displayname,address in getaddresses(message.get_all('X-Kolab-From'))][0] + + any_itips = False + recipient_email = None + recipient_user_dn = None + + # An iTip message may contain multiple events. Later on, test if the message + # is an iTip message by checking the length of this list. + try: + itip_events = events_from_message(message, ['REQUEST', 'REPLY', 'CANCEL']) + except Exception, e: + log.error(_("Failed to parse iTip events from message: %r" % (e))) + itip_events = [] + + if not len(itip_events) > 0: + log.info(_("Message is not an iTip message or does not contain any (valid) iTip events.")) + + else: + any_itips = True + log.debug(_("iTip events attached to this message contain the following information: %r") % (itip_events), level=9) + + # See if any iTip actually allocates a user. + if any_itips and len([x['uid'] for x in itip_events if x.has_key('attendees') or x.has_key('organizer')]) > 0: + auth.connect() + + for recipient in recipients: + recipient_user_dn = user_dn_from_email_address(recipient) + if recipient_user_dn is not None: + recipient_email = recipient + break + + if not any_itips: + log.debug(_("No itips, no users, pass along %r") % (filepath), level=5) + return filepath + elif recipient_email is None: + log.debug(_("iTips, but no users, pass along %r") % (filepath), level=5) + return filepath + + # we're looking at the first itip event object + itip_event = itip_events[0] + + # for replies, the organizer is the recipient + if itip_event['method'] == 'REPLY': + user_attendees = [itip_event['organizer']] if str(itip_event['organizer']).split(':')[-1] == recipient_email else [] + + else: + # Limit the attendees to the one that is actually invited with the current message. + attendees = [str(a).split(':')[-1] for a in (itip_event['attendees'] if itip_event.has_key('attendees') else [])] + user_attendees = [a for a in attendees if a == recipient_email] + + if itip_event.has_key('organizer'): + sender_email = itip_event['xml'].get_organizer().email() + + # abort if no attendee matches the envelope recipient + if len(user_attendees) == 0: + log.info(_("No user attendee matching envelope recipient %s, skip message") % (recipient_email)) + return filepath + + receiving_user = auth.get_entry_attributes(None, recipient_user_dn, ['*']) + log.debug(_("Receiving user: %r") % (receiving_user), level=8) + + # change gettext language to the preferredlanguage setting of the receiving user + if receiving_user.has_key('preferredlanguage'): + pykolab.translate.setUserLanguage(receiving_user['preferredlanguage']) + + # find user's kolabInvitationPolicy settings and the matching policy values + sender_domain = str(sender_email).split('@')[-1] + policies = get_matching_invitation_policies(receiving_user, sender_domain) + + # select a processing function according to the iTip request method + method_processing_map = { + 'REQUEST': process_itip_request, + 'REPLY': process_itip_reply, + 'CANCEL': process_itip_cancel + } + + done = None + if method_processing_map.has_key(itip_event['method']): + processor_func = method_processing_map[itip_event['method']] + + # connect as cyrus-admin + imap.connect() + + for policy in policies: + log.debug(_("Apply invitation policy %r for domain %r") % (policy_value_map[policy], sender_domain), level=8) + done = processor_func(itip_event, policy, recipient_email, sender_email, receiving_user) + + # matching policy found + if done is not None: + break + + # remove possible write lock from this iteration + remove_write_lock(get_lock_key(receiving_user, itip_event['uid'])) + + else: + log.debug(_("Ignoring '%s' iTip method") % (itip_event['method']), level=8) + + # message has been processed by the module, remove it + if done == MESSAGE_PROCESSED: + log.debug(_("iTip message %r consumed by the invitationpolicy module") % (message.get('Message-ID')), level=5) + os.unlink(filepath) + cleanup() + return None + + # accept message into the destination inbox + accept(filepath) + + +def process_itip_request(itip_event, policy, recipient_email, sender_email, receiving_user): + """ + Process an iTip REQUEST message according to the given policy + """ + + # if invitation policy is set to MANUAL, pass message along + if policy & ACT_MANUAL: + log.info(_("Pass invitation for manual processing")) + return MESSAGE_FORWARD + + try: + receiving_attendee = itip_event['xml'].get_attendee_by_email(recipient_email) + log.debug(_("Receiving Attendee: %r") % (receiving_attendee), level=9) + except Exception, e: + log.error("Could not find envelope attendee: %r" % (e)) + return MESSAGE_FORWARD + + # process request to participating attendees with RSVP=TRUE or PARTSTAT=NEEDS-ACTION + nonpart = receiving_attendee.get_role() == kolabformat.NonParticipant + partstat = receiving_attendee.get_participant_status() + save_event = not nonpart or not partstat == kolabformat.PartNeedsAction + rsvp = receiving_attendee.get_rsvp() + scheduling_required = rsvp or partstat == kolabformat.PartNeedsAction + respond_with = receiving_attendee.get_participant_status(True) + condition_fulfilled = True + + # find existing event in user's calendar + existing = find_existing_event(itip_event['uid'], receiving_user, True) + + # compare sequence number to determine a (re-)scheduling request + if existing is not None: + log.debug(_("Existing event: %r") % (existing), level=9) + scheduling_required = itip_event['sequence'] > 0 and itip_event['sequence'] > existing.get_sequence() + save_event = True + + # if scheduling: check availability + if scheduling_required: + if policy & (COND_IF_AVAILABLE | COND_IF_CONFLICT): + condition_fulfilled = check_availability(itip_event, receiving_user) + if policy & COND_IF_CONFLICT: + condition_fulfilled = not condition_fulfilled + + log.debug(_("Precondition for event %r fulfilled: %r") % (itip_event['uid'], condition_fulfilled), level=5) + + respond_with = None + if policy & ACT_ACCEPT and condition_fulfilled: + respond_with = 'TENTATIVE' if policy & COND_TENTATIVE else 'ACCEPTED' + + elif policy & ACT_REJECT and condition_fulfilled: + respond_with = 'DECLINED' + # TODO: only save declined invitation when a certain config option is set? + + elif policy & ACT_DELEGATE and condition_fulfilled: + # TODO: delegate (but to whom?) + return None + + # if RSVP, send an iTip REPLY + if rsvp or scheduling_required: + # set attendee's CN from LDAP record if yet missing + if not receiving_attendee.get_name() and receiving_user.has_key('cn'): + receiving_attendee.set_name(receiving_user['cn']) + + # send iTip reply + if respond_with is not None: + receiving_attendee.set_participant_status(respond_with) + send_reply(recipient_email, itip_event, invitation_response_text(), + subject=_('"%(summary)s" has been %(status)s')) + + elif policy & ACT_SAVE_TO_CALENDAR: + # copy the invitation into the user's calendar with PARTSTAT=NEEDS-ACTION + itip_event['xml'].set_attendee_participant_status(receiving_attendee, 'NEEDS-ACTION') + save_event = True + + else: + # policy doesn't match, pass on to next one + return None + + else: + log.debug(_("No RSVP for recipient %r requested") % (receiving_user['mail']), level=8) + # TODO: only update if policy & ACT_UPDATE ? + + if save_event: + targetfolder = None + + if existing: + # delete old version from IMAP + targetfolder = existing._imap_folder + delete_event(existing) + + if not nonpart or existing: + # save new copy from iTip + if store_event(itip_event['xml'], receiving_user, targetfolder): + return MESSAGE_PROCESSED + + return None + + +def process_itip_reply(itip_event, policy, recipient_email, sender_email, receiving_user): + """ + Process an iTip REPLY message according to the given policy + """ + + # if invitation policy is set to MANUAL, pass message along + if policy & ACT_MANUAL: + log.info(_("Pass reply for manual processing")) + return MESSAGE_FORWARD + + # auto-update is enabled for this user + if policy & ACT_UPDATE: + try: + sender_attendee = itip_event['xml'].get_attendee_by_email(sender_email) + log.debug(_("Sender Attendee: %r") % (sender_attendee), level=9) + except Exception, e: + log.error("Could not find envelope sender attendee: %r" % (e)) + return MESSAGE_FORWARD + + # find existing event in user's calendar + # TODO: set/check lock to avoid concurrent wallace processes trying to update the same event simultaneously + existing = find_existing_event(itip_event['uid'], receiving_user, True) + + if existing: + # compare sequence number to avoid outdated replies? + if not itip_event['sequence'] == existing.get_sequence(): + log.info(_("The iTip reply sequence (%r) doesn't match the referred event version (%r). Forwarding to Inbox.") % ( + itip_event['sequence'], existing.get_sequence() + )) + remove_write_lock(existing._lock_key) + return MESSAGE_FORWARD + + log.debug(_("Auto-updating event %r on iTip REPLY") % (existing.uid), level=8) + try: + existing.set_attendee_participant_status(sender_email, sender_attendee.get_participant_status(), rsvp=False) + except Exception, e: + log.error("Could not find corresponding attende in organizer's event: %r" % (e)) + + # TODO: accept new participant if ACT_ACCEPT ? + remove_write_lock(existing._lock_key) + return MESSAGE_FORWARD + + # update the organizer's copy of the event + if update_event(existing, receiving_user): + if policy & COND_NOTIFY: + send_reply_notification(existing, receiving_user) + + # update all other attendee's copies + if conf.get('wallace','invitationpolicy_autoupdate_other_attendees_on_reply'): + propagate_changes_to_attendees_calendars(existing) + + return MESSAGE_PROCESSED + + else: + log.error(_("The event referred by this reply was not found in the user's calendars. Forwarding to Inbox.")) + return MESSAGE_FORWARD + + return None + + +def process_itip_cancel(itip_event, policy, recipient_email, sender_email, receiving_user): + """ + Process an iTip CANCEL message according to the given policy + """ + + # if invitation policy is set to MANUAL, pass message along + if policy & ACT_MANUAL: + log.info(_("Pass cancellation for manual processing")) + return MESSAGE_FORWARD + + # auto-update the local copy with STATUS=CANCELLED + if policy & ACT_UPDATE: + # find existing event in user's calendar + existing = find_existing_event(itip_event['uid'], receiving_user, True) + + if existing: + existing.set_status('CANCELLED') + existing.set_transparency(True) + if update_event(existing, receiving_user): + # TODO: send cancellation notification if policy & ACT_UPDATE_AND_NOTIFY: ? + return MESSAGE_PROCESSED + + else: + log.error(_("The event referred by this reply was not found in the user's calendars. Forwarding to Inbox.")) + return MESSAGE_FORWARD + + return None + + +def user_dn_from_email_address(email_address): + """ + Resolves the given email address to a Kolab user entity + """ + global auth + + if not auth: + auth = Auth() + auth.connect() + + # return cached value + if user_dn_from_email_address.cache.has_key(email_address): + return user_dn_from_email_address.cache[email_address] + + local_domains = auth.list_domains() + + if not local_domains == None: + local_domains = list(set(local_domains.keys())) + + if not email_address.split('@')[1] in local_domains: + user_dn_from_email_address.cache[email_address] = None + return None + + log.debug(_("Checking if email address %r belongs to a local user") % (email_address), level=8) + + user_dn = auth.find_user_dn(email_address, True) + + if isinstance(user_dn, basestring): + log.debug(_("User DN: %r") % (user_dn), level=8) + else: + log.debug(_("No user record(s) found for %r") % (email_address), level=9) + + # remember this lookup + user_dn_from_email_address.cache[email_address] = user_dn + + return user_dn + +user_dn_from_email_address.cache = {} + + +def get_matching_invitation_policies(receiving_user, sender_domain): + # get user's kolabInvitationPolicy settings + policies = receiving_user['kolabinvitationpolicy'] if receiving_user.has_key('kolabinvitationpolicy') else [] + if policies and not isinstance(policies, list): + policies = [policies] + + if len(policies) == 0: + policies = conf.get_list('wallace', 'kolab_invitation_policy') + + # match policies agains the given sender_domain + matches = [] + for p in policies: + if ':' in p: + (value, domain) = p.split(':') + else: + value = p + domain = '' + + if domain == '' or domain == '*' or sender_domain.endswith(domain): + value = value.upper() + if policy_name_map.has_key(value): + matches.append(policy_name_map[value]) + + # add manual as default action + if len(matches) == 0: + matches.append(ACT_MANUAL) + + return matches + + +def imap_proxy_auth(user_rec): + """ + + """ + global imap + + mail_attribute = conf.get('cyrus-sasl', 'result_attribute') + if mail_attribute == None: + mail_attribute = 'mail' + + mail_attribute = mail_attribute.lower() + + if not user_rec.has_key(mail_attribute): + log.error(_("User record doesn't have the mailbox attribute %r set" % (mail_attribute))) + return False + + # do IMAP prox auth with the given user + backend = conf.get('kolab', 'imap_backend') + admin_login = conf.get(backend, 'admin_login') + admin_password = conf.get(backend, 'admin_password') + + try: + imap.disconnect() + imap.connect(login=False) + imap.login_plain(admin_login, admin_password, user_rec[mail_attribute]) + except Exception, errmsg: + log.error(_("IMAP proxy authentication failed: %r") % (errmsg)) + return False + + return True + + +def list_user_calendars(user_rec): + """ + Get a list of the given user's private calendar folders + """ + global imap + + # return cached list + if user_rec.has_key('_calendar_folders'): + return user_rec['_calendar_folders']; + + calendars = [] + + if not imap_proxy_auth(user_rec): + return calendars + + folders = imap.list_folders('*') + log.debug(_("List calendar folders for user %r: %r") % (user_rec['mail'], folders), level=8) + + (ns_personal, ns_other, ns_shared) = imap.namespaces() + + if isinstance(ns_shared, list): + ns_shared = ns_shared[0] + if isinstance(ns_other, list): + ns_other = ns_other[0] + + for folder in folders: + # exclude shared and other user's namespace + # TODO: list shared folders the user has write privileges ? + if folder.startswith(ns_other) or folder.startswith(ns_shared): + 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('event') \ + or metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].startswith('event')): + calendars.append(folder) + + # store default calendar folder in user record + if metadata[folder].has_key('/private' + FOLDER_TYPE_ANNOTATION) and metadata[folder]['/private' + FOLDER_TYPE_ANNOTATION].endswith('.default'): + user_rec['_default_calendar'] = folder + + # cache with user record + user_rec['_calendar_folders'] = calendars + + return calendars + + +def find_existing_event(uid, user_rec, lock=False): + """ + Search user's calendar folders for the given event (by UID) + """ + global imap + + lock_key = None + + if lock: + lock_key = get_lock_key(user_rec, uid) + set_write_lock(lock_key) + + event = None + for folder in list_user_calendars(user_rec): + log.debug(_("Searching folder %r for event %r") % (folder, uid), level=8) + imap.imap.m.select(imap.folder_utf7(folder)) + + typ, data = imap.imap.m.search(None, '(UNDELETED HEADER SUBJECT "%s")' % (uid)) + for num in reversed(data[0].split()): + typ, data = imap.imap.m.fetch(num, '(RFC822)') + + try: + event = event_from_message(message_from_string(data[0][1])) + setattr(event, '_imap_folder', folder) + setattr(event, '_lock_key', lock_key) + except Exception, e: + log.error(_("Failed to parse event from message %s/%s: %r") % (folder, num, e)) + continue + + if event and event.uid == uid: + return event + + if lock_key is not None: + remove_write_lock(lock_key) + + return event + + +def check_availability(itip_event, receiving_user): + """ + For the receiving user, determine if the event in question is in conflict. + """ + + start = time.time() + num_messages = 0 + conflict = False + + # return previously detected conflict + if itip_event.has_key('_conflicts'): + return not itip_event['_conflicts'] + + for folder in list_user_calendars(receiving_user): + log.debug(_("Listing events from folder %r") % (folder), level=8) + imap.imap.m.select(imap.folder_utf7(folder)) + + typ, data = imap.imap.m.search(None, '(UNDELETED HEADER X-Kolab-Type "application/x-vnd.kolab.event")') + num_messages += len(data[0].split()) + + for num in reversed(data[0].split()): + event = None + typ, data = imap.imap.m.fetch(num, '(RFC822)') + + try: + event = event_from_message(message_from_string(data[0][1])) + except Exception, e: + log.error(_("Failed to parse event from message %s/%s: %r") % (folder, num, e)) + continue + + if event and event.uid: + conflict = check_event_conflict(event, itip_event) + if conflict: + log.info(_("Existing event %r conflicts with invitation %r") % (event.uid, itip_event['uid'])) + break + + if conflict: + break + + end = time.time() + log.debug(_("start: %r, end: %r, total: %r, messages: %d") % (start, end, (end-start), num_messages), level=9) + + # remember the result of this check for further iterations + itip_event['_conflicts'] = conflict + + return not conflict + + +def set_write_lock(key, wait=True): + """ + Set a write-lock for the given key and wait if such a lock already exists + """ + if not os.path.isdir(mybasepath): + os.makedirs(mybasepath) + if not os.path.isdir(os.path.join(mybasepath, 'locks')): + os.makedirs(os.path.join(mybasepath, 'locks')) + + file = os.path.join(mybasepath, 'locks', key + '.lock') + locked = os.path.getmtime(file) if os.path.isfile(file) else 0 + expired = time.time() - 300 + + # wait if file lock is in place + while locked and locked > expired: + if not wait: + return False + + log.debug(_("%r is locked, waiting...") % (key), level=9) + time.sleep(0.5) + locked = os.path.getmtime(file) if os.path.isfile(file) else 0 + + # touch the file + if os.path.isfile(file): + os.utime(file, None) + else: + open(file, 'w').close() + + # register active lock + write_locks.append(key) + + return True + + +def remove_write_lock(key, update=True): + """ + Remove the lock file for the given key + """ + global write_locks + + if key is not None: + file = os.path.join(mybasepath, 'locks', key + '.lock') + if os.path.isfile(file): + os.remove(file) + if update: + write_locks = [k for k in write_locks if not k == key] + + +def get_lock_key(user, uid): + return hashlib.md5("%s/%s" % (user['mail'], uid)).hexdigest() + + +def update_event(event, user_rec): + """ + Update the given event in IMAP (i.e. delete + append) + """ + success = False + + if hasattr(event, '_imap_folder'): + delete_event(event) + success = store_event(event, user_rec, event._imap_folder) + + # remove write lock for this event + if hasattr(event, '_lock_key') and event._lock_key is not None: + remove_write_lock(event._lock_key) + + return success + + +def store_event(event, user_rec, targetfolder=None): + """ + Append the given event object to the user's default calendar + """ + + # find default calendar folder to save event to + if targetfolder is None: + targetfolder = list_user_calendars(user_rec)[0] + if user_rec.has_key('_default_calendar'): + targetfolder = user_rec['_default_calendar'] + + if not targetfolder: + log.error(_("Failed to save event: no calendar folder found for user %r") % (user_rec['mail'])) + return Fasle + + log.debug(_("Save event %r to user calendar %r") % (event.uid, targetfolder), level=8) + + try: + imap.imap.m.select(imap.folder_utf7(targetfolder)) + result = imap.imap.m.append( + imap.folder_utf7(targetfolder), + None, + None, + event.to_message().as_string() + ) + return result + + except Exception, e: + log.error(_("Failed to save event to user calendar at %r: %r") % ( + targetfolder, e + )) + + return False + + +def delete_event(existing): + """ + Removes the IMAP object with the given UID from a user's calendar folder + """ + targetfolder = existing._imap_folder + imap.imap.m.select(imap.folder_utf7(targetfolder)) + + typ, data = imap.imap.m.search(None, '(HEADER SUBJECT "%s")' % existing.uid) + + log.debug(_("Delete event %r in %r: %r") % ( + existing.uid, targetfolder, data + ), level=8) + + for num in data[0].split(): + imap.imap.m.store(num, '+FLAGS', '\\Deleted') + + imap.imap.m.expunge() + + +def send_reply_notification(event, receiving_user): + """ + Send a (consolidated) notification about the current participant status to organizer + """ + global auth + + import smtplib + from email.MIMEText import MIMEText + from email.Utils import formatdate + + log.debug(_("Compose participation status summary for event %r to user %r") % ( + event.uid, receiving_user['mail'] + ), level=8) + + organizer = event.get_organizer() + orgemail = organizer.email() + orgname = organizer.name() + sender_domain = orgemail.split('@')[-1] + + auto_replies_expected = 0 + auto_replies_received = 0 + partstats = { 'ACCEPTED':[], 'TENTATIVE':[], 'DECLINED':[], 'DELEGATED':[], 'PENDING':[] } + for attendee in event.get_attendees(): + parstat = attendee.get_participant_status(True) + if partstats.has_key(parstat): + partstats[parstat].append(attendee.get_displayname()) + else: + partstats['PENDING'].append(attendee.get_displayname()) + + # look-up kolabinvitationpolicy for this attendee + if attendee.get_cutype() == kolabformat.CutypeResource: + resource_dns = auth.find_resource(attendee.get_email()) + if isinstance(resource_dns, list): + attendee_dn = resource_dns[0] if len(resource_dns) > 0 else None + else: + attendee_dn = resource_dns + else: + attendee_dn = user_dn_from_email_address(attendee.get_email()) + + if attendee_dn: + attendee_rec = auth.get_entry_attributes(None, attendee_dn, ['kolabinvitationpolicy']) + if is_auto_reply(attendee_rec, sender_domain): + auto_replies_expected += 1 + if not parstat == 'NEEDS-ACTION': + auto_replies_received += 1 + + # skip notification until we got replies from all automatically responding attendees + if auto_replies_received < auto_replies_expected: + log.debug(_("Waiting for more automated replies (got %d of %d); skipping notification") % ( + auto_replies_received, auto_replies_expected + ), level=8) + return + + roundup = '' + for status,attendees in partstats.iteritems(): + if len(attendees) > 0: + roundup += "\n" + participant_status_label(status) + ":\n" + "\n".join(attendees) + "\n" + + message_text = """ + The event '%(summary)s' at %(start)s has been updated in your calendar. + %(roundup)s + """ % { + 'summary': event.get_summary(), + 'start': event.get_start().strftime('%Y-%m-%d %H:%M %Z'), + 'roundup': roundup + } + + # compose mime message + msg = MIMEText(utils.stripped_message(message_text)) + + msg['To'] = receiving_user['mail'] + msg['Date'] = formatdate(localtime=True) + msg['Subject'] = _('"%s" has been updated') % (event.get_summary()) + msg['From'] = '"%s" <%s>' % (orgname, orgemail) if orgname else orgemail + + smtp = smtplib.SMTP("localhost", 10027) + + if conf.debuglevel > 8: + smtp.set_debuglevel(True) + + try: + smtp.sendmail(orgemail, receiving_user['mail'], msg.as_string()) + except Exception, e: + log.error(_("SMTP sendmail error: %r") % (e)) + + smtp.quit() + + +def is_auto_reply(user, sender_domain): + accept_available = False + accept_conflicts = False + for policy in get_matching_invitation_policies(user, sender_domain): + if policy & (ACT_ACCEPT | ACT_REJECT | ACT_DELEGATE): + if check_policy_condition(policy, True): + accept_available = True + if check_policy_condition(policy, False): + accept_conflicts = True + + # we have both cases covered by a policy + if accept_available and accept_conflicts: + return True + + # manual action reached + if policy & (ACT_MANUAL | ACT_SAVE_TO_CALENDAR): + return False + + return False + + +def check_policy_condition(policy, available): + condition_fulfilled = True + if policy & (COND_IF_AVAILABLE | COND_IF_CONFLICT): + condition_fulfilled = available + if policy & COND_IF_CONFLICT: + condition_fulfilled = not condition_fulfilled + return condition_fulfilled + + +def propagate_changes_to_attendees_calendars(event): + """ + Find and update copies of this event in all attendee's calendars + """ + for attendee in event.get_attendees(): + attendee_user_dn = user_dn_from_email_address(attendee.get_email()) + if attendee_user_dn: + attendee_user = auth.get_entry_attributes(None, attendee_user_dn, ['*']) + attendee_event = find_existing_event(event.uid, attendee_user, True) # does IMAP authenticate + if attendee_event: + try: + attendee_entry = attendee_event.get_attendee_by_email(attendee_user['mail']) + except: + attendee_entry = None + + # copy all attendees from master event (covers additions and removals) + new_attendees = kolabformat.vectorattendee(); + for a in event.get_attendees(): + # keep my own entry intact + if attendee_entry is not None and attendee_entry.get_email() == a.get_email(): + new_attendees.append(attendee_entry) + else: + new_attendees.append(a) + + attendee_event.event.setAttendees(new_attendees) + + success = update_event(attendee_event, attendee_user) + log.debug(_("Updated %s's copy of %r: %r") % (attendee_user['mail'], event.uid, success), level=8) + + else: + log.debug(_("Attendee %s's copy of %r not found") % (attendee_user['mail'], event.uid), level=8) + + else: + log.debug(_("Attendee %r not found in LDAP") % (attendee.get_email()), level=8) + + +def invitation_response_text(): + return _(""" + %(name)s has %(status)s your invitation for %(summary)s. + + *** This is an automated response sent by the Kolab Invitation system *** + """)
View file
pykolab-0.7.tar.gz/wallace/module_optout.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import json
View file
pykolab-0.7.tar.gz/wallace/module_resources.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import datetime @@ -40,11 +40,25 @@ from pykolab.auth import Auth from pykolab.conf import Conf from pykolab.imap import IMAP -from pykolab.xml import event_from_ical -from pykolab.xml import event_from_string from pykolab.xml import to_dt +from pykolab.xml import event_from_message +from pykolab.xml import participant_status_label +from pykolab.itip import events_from_message +from pykolab.itip import check_event_conflict from pykolab.translate import _ +# define some contstants used in the code below +COND_NOTIFY = 256 +ACT_MANUAL = 1 +ACT_ACCEPT = 2 +ACT_ACCEPT_AND_NOTIFY = ACT_ACCEPT + COND_NOTIFY + +policy_name_map = { + 'ACT_MANUAL': ACT_MANUAL, + 'ACT_ACCEPT': ACT_ACCEPT, + 'ACT_ACCEPT_AND_NOTIFY': ACT_ACCEPT_AND_NOTIFY +} + log = pykolab.getLogger('pykolab.wallace') conf = pykolab.getConf() @@ -86,6 +100,9 @@ def execute(*args, **kw): global auth, imap + # (re)set language to default + pykolab.translate.setUserLanguage(conf.get('kolab','default_locale')) + if not os.path.isdir(mybasepath): os.makedirs(mybasepath) @@ -150,7 +167,7 @@ # An iTip message may contain multiple events. Later on, test if the message # is an iTip message by checking the length of this list. try: - itip_events = itip_events_from_message(message) + itip_events = events_from_message(message, ['REQUEST', 'CANCEL']) except Exception, e: log.error(_("Failed to parse iTip events from message: %r" % (e))) itip_events = [] @@ -466,76 +483,32 @@ event_message = message_from_string(data[0][1]) - if event_message.is_multipart(): - for part in event_message.walk(): - if part.get_content_type() == "application/calendar+xml": - payload = part.get_payload(decode=True) - event = pykolab.xml.event_from_string(payload) - - for itip in itip_events: - _es = to_dt(event.get_start()) - _ee = to_dt(event.get_end()) - - conflict = False - - # naive loops to check for collisions in (recurring) events - # TODO: compare recurrence rules directly (e.g. matching time slot or weekday or monthday) - while not conflict and _es is not None: - _is = to_dt(itip['start']) - _ie = to_dt(itip['end']) - - while not conflict and _is is not None: - log.debug("* Comparing event dates at %s/%s with %s/%s" % (_es, _ee, _is, _ie), level=9) - conflict = check_date_conflict(_es, _ee, _is, _ie) - _is = to_dt(itip['xml'].get_next_occurence(_is)) if event.is_recurring() else None - _ie = to_dt(itip['xml'].get_occurence_end_date(_is)) - - _es = to_dt(event.get_next_occurence(_es)) if event.is_recurring() else None - _ee = to_dt(event.get_occurence_end_date(_es)) + try: + event = event_from_message(message_from_string(data[0][1])) + except Exception, e: + log.error(_("Failed to parse event from message %s/%s: %r") % (mailbox, num, e)) + continue - if event.get_uid() == itip['uid']: - resource_rec['existing_events'].append(itip['uid']) + if event: + for itip in itip_events: + conflict = check_event_conflict(event, itip) - # don't register conflict for updates - if itip['sequence'] > 0 and itip['sequence'] >= event.get_sequence(): - conflict = False + if event.get_uid() == itip['uid']: + resource_rec['existing_events'].append(itip['uid']) - if conflict: - log.info( - _("Event %r conflicts with event %r") % ( - itip['xml'].get_uid(), - event.get_uid() - ) - ) + if conflict: + log.info( + _("Event %r conflicts with event %r") % ( + itip['xml'].get_uid(), + event.get_uid() + ) + ) - resource_rec['conflicting_events'].append(event.get_uid()) - resource_rec['conflict'] = True + resource_rec['conflicting_events'].append(event.get_uid()) + resource_rec['conflict'] = True return num_messages -def check_date_conflict(_es, _ee, _is, _ie): - conflict = False - - # TODO: add margin for all-day dates (+13h; -12h) - - if _es < _is: - if _es <= _ie: - if _ee <= _is: - conflict = False - else: - conflict = True - else: - conflict = True - elif _es == _is: - conflict = True - else: # _es > _is - if _es <= _ie: - conflict = True - else: - conflict = False - - return conflict - def accept_reservation_request(itip_event, resource, delegator=None): """ @@ -556,7 +529,13 @@ level=8 ) - send_response(delegator['mail'] if delegator else resource['mail'], itip_event, get_resource_owner(resource)) + owner = get_resource_owner(resource) + + if saved: + send_response(delegator['mail'] if delegator else resource['mail'], itip_event, owner) + + if owner: + send_owner_notification(resource, owner, itip_event, saved) def decline_reservation_request(itip_event, resource): @@ -570,8 +549,12 @@ "DECLINED" ) + owner = get_resource_owner(resource) send_response(resource['mail'], itip_event, get_resource_owner(resource)) + if owner: + send_owner_notification(resource, owner, itip_event, True) + def save_resource_event(itip_event, resource): """ @@ -617,118 +600,6 @@ imap.imap.m.expunge() -def itip_events_from_message(message): - """ - Obtain the iTip payload from email.message <message> - """ - # Placeholder for any itip_events found in the message. - itip_events = [] - seen_uids = [] - - # iTip methods we are actually interested in. Other methods will be ignored. - itip_methods = [ "REQUEST", "CANCEL" ] - - # Are all iTip messages multipart? No! RFC 6047, section 2.4 states "A - # MIME body part containing content information that conforms to this - # document MUST have (...)" but does not state whether an iTip message must - # therefore also be multipart. - - # Check each part - for part in message.walk(): - - # The iTip part MUST be Content-Type: text/calendar (RFC 6047, section 2.4) - # But in real word, other mime-types are used as well - if part.get_content_type() in [ "text/calendar", "text/x-vcalendar", "application/ics" ]: - if not str(part.get_param('method')).upper() in itip_methods: - log.error(_("Method %r not really interesting for us.") % (part.get_param('method'))) - continue - - # Get the itip_payload - itip_payload = part.get_payload(decode=True) - - log.debug(_("Raw iTip payload: %s") % (itip_payload), level=9) - - # Python iCalendar prior to 3.0 uses "from_string". - if hasattr(icalendar.Calendar, 'from_ical'): - cal = icalendar.Calendar.from_ical(itip_payload) - elif hasattr(icalendar.Calendar, 'from_string'): - cal = icalendar.Calendar.from_string(itip_payload) - - # If we can't read it, we're out - else: - log.error(_("Could not read iTip from message.")) - return [] - - for c in cal.walk(): - if c.name == "VEVENT": - itip = {} - - if c['uid'] in seen_uids: - log.debug(_("Duplicate iTip event: %s") % (c['uid']), level=9) - continue - - # From the event, take the following properties: - # - # - method - # - uid - # - sequence - # - start - # - end (if any) - # - duration (if any) - # - organizer - # - attendees (if any) - # - resources (if any) - # - - itip['uid'] = str(c['uid']) - itip['method'] = str(cal['method']).upper() - itip['sequence'] = int(c['sequence']) if c.has_key('sequence') else 0 - - if c.has_key('dtstart'): - itip['start'] = c['dtstart'].dt - else: - log.error(_("iTip event without a start")) - continue - - if c.has_key('dtend'): - itip['end'] = c['dtend'].dt - - if c.has_key('duration'): - itip['duration'] = c['duration'].dt - itip['end'] = itip['start'] + c['duration'].dt - - itip['organizer'] = c['organizer'] - - itip['attendees'] = c['attendee'] - - if c.has_key('resources'): - itip['resources'] = c['resources'] - - itip['raw'] = itip_payload - - try: - itip['xml'] = event_from_ical(c.to_ical()) - except Exception, e: - log.error("event_from_ical() exception: %r" % (e)) - continue - - itip_events.append(itip) - - seen_uids.append(c['uid']) - - # end if c.name == "VEVENT" - - # end for c in cal.walk() - - # end if part.get_content_type() == "text/calendar" - - # end for part in message.walk() - - if not len(itip_events) and not message.is_multipart(): - log.debug(_("Message is not an iTip message (non-multipart message)"), level=5) - - return itip_events - def reject(filepath): new_filepath = os.path.join( mybasepath, @@ -904,21 +775,25 @@ # If it is not, ... resource_attrs = auth.get_entry_attributes(None, resource_dn, ['*']) resource_attrs['dn'] = resource_dn + parse_kolabinvitationpolicy(resource_attrs) + if not 'kolabsharedfolder' in [x.lower() for x in resource_attrs['objectclass']]: if resource_attrs.has_key('uniquemember'): resources[resource_dn] = resource_attrs for uniquemember in resource_attrs['uniquemember']: - resource_attrs = auth.get_entry_attributes( + member_attrs = auth.get_entry_attributes( None, uniquemember, ['*'] ) - if 'kolabsharedfolder' in [x.lower() for x in resource_attrs['objectclass']]: - resource_attrs['dn'] = uniquemember - resources[uniquemember] = resource_attrs + if 'kolabsharedfolder' in [x.lower() for x in member_attrs['objectclass']]: + member_attrs['dn'] = uniquemember + parse_kolabinvitationpolicy(member_attrs, resource_attrs) + + resources[uniquemember] = member_attrs resources[uniquemember]['memberof'] = resource_dn - if not resource_attrs.has_key('owner') and resources[resource_dn].has_key('owner'): + if not member_attrs.has_key('owner') and resources[resource_dn].has_key('owner'): resources[uniquemember]['owner'] = resources[resource_dn]['owner'] resource_dns.append(uniquemember) else: @@ -927,6 +802,16 @@ return resources +def parse_kolabinvitationpolicy(attrs, parent=None): + if attrs.has_key('kolabinvitationpolicy'): + if not isinstance(attrs['kolabinvitationpolicy'], list): + attrs['kolabinvitationpolicy'] = [attrs['kolabinvitationpolicy']] + attrs['kolabinvitationpolicy'] = [policy_name_map[p] for p in attrs['kolabinvitationpolicy'] if policy_name_map.has_key(p)] + + elif isinstance(parent, dict) and parent.has_key('kolabinvitationpolicy'): + attrs['kolabinvitationpolicy'] = parent['kolabinvitationpolicy'] + + def get_resource_collection(email_address): """ @@ -986,12 +871,6 @@ resource, this will send an additional DELEGATED response message. """ - import smtplib - smtp = smtplib.SMTP("localhost", 10027) - - if conf.debuglevel > 8: - smtp.set_debuglevel(True) - if isinstance(itip_events, dict): itip_events = [ itip_events ] @@ -999,7 +878,10 @@ attendee = itip_event['xml'].get_attendee_by_email(from_address) participant_status = itip_event['xml'].get_ical_attendee_participant_status(attendee) + # TODO: look-up event organizer in LDAP and change localization to its preferredlanguage + message_text = reservation_response_text(participant_status, owner) + subject_template = _("Reservation Request for %(summary)s was %(status)s") if participant_status == "DELEGATED": # Extra actions to take @@ -1007,32 +889,21 @@ delegatee = [a for a in itip_event['xml'].get_attendees() if from_address in [b.email() for b in a.get_delegated_from()]][0] delegatee_status = itip_event['xml'].get_ical_attendee_participant_status(delegatee) - message = itip_event['xml'].to_message_itip(delegatee.get_email(), - method="REPLY", - participant_status=delegatee_status, - message_text=reservation_response_text(delegatee_status, owner) - ) - smtp.sendmail(message['From'], message['To'], message.as_string()) + pykolab.itip.send_reply(delegatee.get_email(), itip_event, reservation_response_text(delegatee_status, owner), + subject=subject_template) # restore list of attendees after to_message_itip() itip_event['xml']._attendees = [ delegator, delegatee ] itip_event['xml'].event.setAttendees(itip_event['xml']._attendees) - participant_status = "DELEGATED" message_text = _(""" *** This is an automated response, please do not reply! *** Your reservation was delegated to "%s" which is available for the requested time. """) % (delegatee.get_name()) - message = itip_event['xml'].to_message_itip(from_address, - method="REPLY", - participant_status=participant_status, - message_text=message_text - ) - smtp.sendmail(message['From'], message['To'], message.as_string()) - - smtp.quit() + pykolab.itip.send_reply(from_address, itip_event, message_text, + subject=subject_template) def reservation_response_text(status, owner): @@ -1040,7 +911,7 @@ *** This is an automated response, please do not reply! *** We hereby inform you that your reservation was %s. - """) % (_(status)) + """) % (participant_status_label(status)) if owner: message_text += _(""" @@ -1049,3 +920,83 @@ """) % (owner['cn'], owner['mail'], owner['telephoneNumber'] if owner.has_key('telephoneNumber') else '') return message_text + + +def send_owner_notification(resource, owner, itip_event, success=True): + """ + Send a reservation notification to the resource owner + """ + import smtplib + from pykolab import utils + from email.MIMEText import MIMEText + from email.Utils import formatdate + + notify = False + status = itip_event['xml'].get_attendee_by_email(resource['mail']).get_participant_status(True) + + if resource.has_key('kolabinvitationpolicy'): + for policy in resource['kolabinvitationpolicy']: + # TODO: distingish ACCEPTED / DECLINED status notifications? + if policy & COND_NOTIFY and owner['mail']: + notify = True + break + + if notify or not success: + log.debug( + _("Sending booking notification for event %r to %r from %r") % ( + itip_event['uid'], owner['mail'], resource['cn'] + ), + level=8 + ) + + # change gettext language to the preferredlanguage setting of the resource owner + if owner.has_key('preferredlanguage'): + pykolab.translate.setUserLanguage(owner['preferredlanguage']) + + message_text = owner_notification_text(resource, owner, itip_event['xml'], success) + + msg = MIMEText(utils.stripped_message(message_text)) + + msg['To'] = owner['mail'] + msg['From'] = resource['mail'] + msg['Date'] = formatdate(localtime=True) + msg['Subject'] = _('Booking for %s has been %s') % (resource['cn'], participant_status_label(status) if success else _('failed')) + + smtp = smtplib.SMTP("localhost", 10027) + + if conf.debuglevel > 8: + smtp.set_debuglevel(True) + + try: + smtp.sendmail(resource['mail'], owner['mail'], msg.as_string()) + except Exception, e: + log.error(_("SMTP sendmail error: %r") % (e)) + + smtp.quit() + +def owner_notification_text(resource, owner, event, success): + organizer = event.get_organizer() + status = event.get_attendee_by_email(resource['mail']).get_participant_status(True) + + if success: + message_text = _(""" + The resource booking for %(resource)s by %(orgname)s <%(orgemail)s> has been %(status)s for %(date)s. + + *** This is an automated message, sent to you as the resource owner. *** + """) + else: + message_text = _(""" + A reservation request for %(resource)s could not be processed automatically. + Please contact %(orgname)s <%(orgemail)s> who requested this resource for %(date)s. Subject: %(summary)s. + + *** This is an automated message, sent to you as the resource owner. *** + """) + + return message_text % { + 'resource': resource['cn'], + 'summary': event.get_summary(), + 'date': event.get_date_text(), + 'status': participant_status_label(status), + 'orgname': organizer.name(), + 'orgemail': organizer.email() + }
View file
pykolab-0.7.tar.gz/wallace/modules.py
Changed
@@ -3,18 +3,18 @@ # # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> # -# This program is free software; you can redistribute it and/or modify +# 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 -# +# 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 Library General Public License for more details. -# +# 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, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # import os
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
.