diff --git a/doc/conf.py b/doc/conf.py index 13b3fddff..39fa7e833 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -41,16 +41,16 @@ master_doc = 'index' # General information about the project. project = u'Modoboa' -copyright = u'2013, Antoine Nguyen' +copyright = u'2014, Antoine Nguyen' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '1.0' +version = '1.1' # The full version, including alpha/beta/rc tags. -release = '1.0.1' +release = '1.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/getting_started/configuration.rst b/doc/getting_started/configuration.rst index efcf39658..c56271a05 100644 --- a/doc/getting_started/configuration.rst +++ b/doc/getting_started/configuration.rst @@ -242,6 +242,17 @@ Modoboa should connect to your LDAP server. They are described just below: | |server is an Active | | | |Directory one | | +--------------------+---------------------------------+--------------------+ +|Administrator groups|Members of those LDAP Posix | | +| |groups will be created ad domain | | +| |administrators. Use ';' | | +| |characters to separate groups. | | ++--------------------+---------------------------------+--------------------+ +|Groups search base |The distinguished name of the | | +| |search base used to find groups | | +| | | | +| | | | ++--------------------+---------------------------------+--------------------+ + If you need additional parameters, you will find a detailled documentation `here `_. @@ -250,12 +261,14 @@ Once the authentication is properly configured, the users defined in your LDAP directory will be able to connect to Modoboa, the associated domain and mailboxes will be automatically created if needed. -.. note:: +The first time a user connects to Modoboa, a local account is created +if the LDAP username is a valid email address. By default, this +account belongs to the *SimpleUsers* group and it has a mailbox. - Users created automatically from an LDAP directory belongs to the - *SimpleUsers* group and have a mailbox. To do so, usernames have to - be valid email addresses. If not, LDAP users won't be able to - access Modoboa. +To automatically create domain administrators, you can use the +**Administrator groups** setting. If a LDAP user belongs to one the +listed groups, its local account will belong to the *DomainAdmins* +group. In this case, the username is not necessarily an email address. Users will also be able to update their LDAP password directly from Modoboa. diff --git a/doc/getting_started/plugins.rst b/doc/getting_started/plugins.rst index 2b47858e7..0cfd93378 100644 --- a/doc/getting_started/plugins.rst +++ b/doc/getting_started/plugins.rst @@ -46,7 +46,7 @@ listing page: *relay domain* and *relay domain alias*. The extension is compatible with the *amavis* and *limits* ones. Resellers will be able to create both new objects. -To tell Postfix this feature exists, you must generate two new map +Replace by the name of the database you use.To tell Postfix this feature exists, you must generate two new map files and then update your configuration. To generate the map files, run the following command:: @@ -55,7 +55,23 @@ To generate the map files, run the following command:: Replace values between ``<>`` by yours. -Edit the :file:`/etc/postfix/main.cf` file. +Edit the :file:`/etc/postfix/main.cf` file and copy the following +lines inside:: + + relay_domains = :/etc/postfix/maps/sql-relaydomains.cf + transport_maps = + :/etc/postfix/maps/sql-relaydomains-transport.cf + :/etc/postfix/maps/sql-relaydomain-aliases-transport.cf + + smtpd_recipient_restrictions = + permit_mynetworks + reject_unauth_destination + check_recipient_access + :/etc/postfix/maps/sql-relay-recipient-verification.cf + +Replace ```` by the name of the database you use. + +Reload postfix. .. _amavis_frontend: @@ -311,12 +327,11 @@ configuration files as follows: ``/etc/postfix/main.cf``:: - transport_maps = mysql:/etc/postfix/maps/sql-transport.cf - virtual_alias_maps = mysql:/etc/postfix/maps/sql-aliases.cf - mysql:/etc/postfix/mapfiles/sql-domain-aliases-mailboxes.cf, - mysql:/etc/postfix/mapfiles/sql-email2email.cf, - mysql:/etc/postfix/maps/sql-autoreplies.cf, - mysql:/etc/postfix/mapfiles/sql-catchall-aliases.cf + transport_maps = mysql:/etc/postfix/maps/sql-autoreplies-transport.cf + virtual_alias_maps = :/etc/postfix/maps/sql-aliases.cf + :/etc/postfix/mapfiles/sql-domain-aliases-mailboxes.cf, + :/etc/postfix/maps/sql-autoreplies.cf, + :/etc/postfix/mapfiles/sql-catchall-aliases.cf .. note:: @@ -327,7 +342,8 @@ configuration files as follows: autoreply unix - n n - - pipe flags= user=vmail: argv=/manage.py autoreply $sender $mailbox -```` is the path of your Modoboa instance. +Replace ```` by the name of the database you +use. ```` is the path of your Modoboa instance. Then, create the requested map files:: diff --git a/doc/getting_started/upgrade.rst b/doc/getting_started/upgrade.rst index 013e9fb56..9aa488ed9 100644 --- a/doc/getting_started/upgrade.rst +++ b/doc/getting_started/upgrade.rst @@ -50,8 +50,8 @@ Finally, follow the common procedure:: .. _1.1.0: -1.1.0: FIXME -============ +1.1.0: relay domains and better passwords encryption +==================================================== Due to code refactoring, some modifications need to be done into :file:`settings.py`: @@ -72,7 +72,9 @@ Due to code refactoring, some modifications need to be done into 'modoboa.extensions.sievefilters', ) -#. Add ``'modoboa.extensions.postfix_relay_domains'`` to ``MODOBOA_APPS`` +#. Add ``'modoboa.extensions.postfix_relay_domains'`` to + ``MODOBOA_APPS``, just before + ``'modoboa.extensions.limits'`` #. ``AUTH_USER_MODEL`` must be set to ``core.User`` @@ -81,6 +83,7 @@ Due to code refactoring, some modifications need to be done into Then, run the following commands to migrate your installation:: + $ python manage.py syncdb $ python manage.py migrate core 0001 --fake $ python manage.py migrate $ python manage.py collectstatic diff --git a/doc/integration/imap_and_smtp.rst b/doc/integration/imap_and_smtp.rst index 5c66009fa..ded944f66 100644 --- a/doc/integration/imap_and_smtp.rst +++ b/doc/integration/imap_and_smtp.rst @@ -44,14 +44,26 @@ Then, edit the ``inbox`` namespace and add the following lines:: special_use = \Trash } -It ensures all the special mailboxes will be automaticaly created for -new accounts. +With dovecot 2.1+, it ensures all the special mailboxes will be +automaticaly created for new accounts. + +For dovecot 2.0 and older, use the `autocreate +`_ plugin. .. _fs_operations: Operations on the file system ----------------------------- +.. warning:: + + Modoboa needs to access the ``dovecot`` binary to check its + version. To find the binary path, we use the ``which`` command + first and then try known locations (:file:`/usr/sbin/dovecot` and + :file:`/usr/local/sbin/dovecot`). If you installed dovecot in a + custom location, please tell us where the binary is by using the + ``DOVECOT_LOOKUP_PATH`` setting (see :file:`settings.py`). + Three operation types are considered: #. Mailbox creation @@ -443,15 +455,9 @@ Use the following configuration in the :file:`/etc/postfix/main.cf` file virtual_transport = dovecot dovecot_destination_recipient_limit = 1 - virtual_minimum_uid = - virtual_gid_maps = static: - virtual_uid_maps = static: - virtual_mailbox_base = /var/vmail - relay_domains = virtual_mailbox_domains = :/etc/postfix/sql-domains.cf virtual_alias_domains = :/etc/postfix/sql-domain-aliases.cf - virtual_mailbox_maps = :/etc/postfix/sql-mailboxes.cf virtual_alias_maps = :/etc/postfix/sql-aliases.cf, :/etc/postfix/sql-domain-aliases-mailboxes.cf, :/etc/postfix/sql-catchall-aliases.cf diff --git a/modoboa/core/commands/postfix_maps.py b/modoboa/core/commands/postfix_maps.py index d37fb1dbb..5ac75ce8a 100644 --- a/modoboa/core/commands/postfix_maps.py +++ b/modoboa/core/commands/postfix_maps.py @@ -104,13 +104,6 @@ class DomainsAliasesMap(MapFile): sqlite = "SELECT dom.name FROM admin_domain dom INNER JOIN admin_domainalias domal ON dom.id=domal.target_id WHERE domal.name='%s' AND domal.enabled=1 AND dom.enabled=1" -class MailboxesMap(MapFile): - filename = 'sql-mailboxes.cf' - mysql = "SELECT 1 FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN core_user user ON mb.user_id=user.id WHERE dom.enabled=1 AND dom.name='%d' AND user.is_active=1 AND mb.address='%u'" - postgres = "SELECT 1 FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN core_user u ON mb.user_id=u.id WHERE dom.enabled AND dom.name='%d' AND u.is_active AND mb.address='%u'" - sqlite = "SELECT 1 FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id INNER JOIN core_user user ON mb.user_id=user.id WHERE dom.enabled=1 AND dom.name='%d' AND user.is_active=1 AND mb.address='%u'" - - class AliasesMap(MapFile): filename = 'sql-aliases.cf' mysql = "(SELECT concat(mb.address, '@', dom.name) FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.id IN (SELECT al_mb.mailbox_id FROM admin_alias_mboxes al_mb INNER JOIN admin_alias al ON al_mb.alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT concat(al.address, '@', dom.name) FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE al.id IN (SELECT al_al.to_alias_id FROM admin_alias_aliases al_al INNER JOIN admin_alias al ON al_al.from_alias_id=al.id INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1)) UNION (SELECT al.extmboxes FROM admin_alias al INNER JOIN admin_domain dom ON al.domain_id=dom.id WHERE dom.name='%d' AND dom.enabled=1 AND al.address='%u' AND al.enabled=1 AND al.extmboxes<>'')" @@ -141,7 +134,7 @@ class MaintainMap(MapFile): class TransportMap(MapFile): category = "autoreply" - filename = 'sql-transport.cf' + filename = 'sql-autoreplies-transport.cf' mysql = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'" postgres = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'" sqlite = "SELECT method FROM postfix_autoreply_transport WHERE domain='%s'" @@ -155,20 +148,36 @@ class AutoRepliesMap(MapFile): sqlite = "SELECT full_address, autoreply_address FROM postfix_autoreply_alias WHERE full_address='%s'" +class RelayDomainsMap(MapFile): + category = "relaydomains" + filename = "sql-relaydomains.cf" + mysql = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled=1" + postgres = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled" + sqlite = "SELECT name FROM postfix_relay_domains_relaydomain WHERE name='%s' AND enabled=1" + + class RelayDomainsTransportMap(MapFile): category = "relaydomains" filename = "sql-relaydomains-transport.cf" - mysql = "SELECT CONCAT(srv.name, ':') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'" - postgres = "SELECT srv.name || ':' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled AND rdom.name='%s'" - sqlite = "SELECT srv.name || ':' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'" + mysql = "SELECT CONCAT(srv.name, ':[', rdom.target_host, ']') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'" + postgres = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled AND rdom.name='%s'" + sqlite = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id WHERE rdom.enabled=1 AND rdom.name='%s'" class RelayDomainAliasesTransportMap(MapFile): category = "relaydomains" filename = "sql-relaydomain-aliases-transport.cf" - mysql = "SELECT CONCAT(srv.name, ':') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'" - postgres = "SELECT srv.name || ':' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled AND rdomalias.enabled AND rdomalias.name='%s'" - sqlite = "SELECT srv.name || ':' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'" + mysql = "SELECT CONCAT(srv.name, ':[', rdom.target_host, ']') FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'" + postgres = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled AND rdomalias.enabled AND rdomalias.name='%s'" + sqlite = "SELECT srv.name || ':[' || rdom.target_host || ']' FROM postfix_relay_domains_service AS srv INNER JOIN postfix_relay_domains_relaydomain AS rdom ON rdom.service_id=srv.id INNER JOIN postfix_relay_domains_relaydomainalias AS rdomalias ON rdom.id=rdomalias.target_id WHERE rdom.enabled=1 AND rdomalias.enabled=1 AND rdomalias.name='%s'" + + +class RelayRecipientVerification(MapFile): + category = "relaydomains" + filename = "sql-relay-recipient-verification.cf" + mysql = "SELECT 'reject_unverified_recipient' FROM postfix_relay_domains_relaydomain WHERE verify_recipients=1 AND name='%d'" + postgres = "SELECT 'reject_unverified_recipient' FROM postfix_relay_domains_relaydomain WHERE verify_recipients AND name='%d'" + sqlite = "SELECT 'reject_unverified_recipient' FROM postfix_relay_domains_relaydomain WHERE verify_recipients=1 AND name='%d'" class PostfixMapsCommand(Command): diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index b7f36115f..87b8caa88 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -172,6 +172,8 @@ SOUTH_TESTS_MIGRATE = False #MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") +#DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) + AUTHENTICATION_BACKENDS = ( 'modoboa.lib.authbackends.SimpleBackend', ) diff --git a/modoboa/core/management/commands/cleanlogs.py b/modoboa/core/management/commands/cleanlogs.py index 3da28798f..0cf1c8aac 100644 --- a/modoboa/core/management/commands/cleanlogs.py +++ b/modoboa/core/management/commands/cleanlogs.py @@ -4,7 +4,7 @@ import datetime from optparse import make_option from django.core.management.base import BaseCommand from django.utils import timezone -from modoboa.core import load_settings +from modoboa.core import load_core_settings from modoboa.core.models import Log from modoboa.lib import parameters @@ -37,7 +37,7 @@ class Command(BaseCommand): l.addHandler(logging.StreamHandler()) self.verbose = options["verbose"] - load_settings() + load_core_settings() log_maximum_age = int(parameters.get_admin("LOG_MAXIMUM_AGE")) self.__vprint("Deleting logs older than %d days..." % log_maximum_age) limit = timezone.now() - datetime.timedelta(log_maximum_age) diff --git a/modoboa/core/models.py b/modoboa/core/models.py index cfb194e39..db3d05f22 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -17,7 +17,7 @@ from django.contrib.auth.models import ( from django.contrib.auth.hashers import make_password, is_password_usable from modoboa.lib import events, parameters from modoboa.lib.exceptions import ( - PermDeniedException, InternalError, BadRequest + PermDeniedException, InternalError, BadRequest, Conflict ) from modoboa.lib.sysutils import exec_cmd from modoboa.core.extensions import exts_pool @@ -325,6 +325,12 @@ class User(PermissionsMixin): _("You can't import an account with a role greater than yours") ) self.username = row[1].strip() + try: + User.objects.get(username=self.username) + except User.DoesNotExist: + pass + else: + raise Conflict if role == "SimpleUsers": if (len(row) < 8 or not row[7].strip()): raise BadRequest( diff --git a/modoboa/core/password_hashers/__init__.py b/modoboa/core/password_hashers/__init__.py index c26f9d3fd..66e4d6a64 100644 --- a/modoboa/core/password_hashers/__init__.py +++ b/modoboa/core/password_hashers/__init__.py @@ -20,7 +20,7 @@ def get_password_hasher(scheme): """ try: scheme = scheme.replace('-', '') - hasher = globals()['%sHasher' % scheme] - except AttributeError: + hasher = globals()['%sHasher' % scheme.upper()] + except KeyError: hasher = PLAINHasher return hasher diff --git a/modoboa/demo/views.py b/modoboa/demo/views.py index 18e2a8427..89a88f9f6 100755 --- a/modoboa/demo/views.py +++ b/modoboa/demo/views.py @@ -5,7 +5,7 @@ from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from modoboa.lib.webutils import render_to_json_response from modoboa.lib.emailutils import sendmail_simple, sendmail_fromfile -from modoboa.lib.decorators import needs_mailbox +from modoboa.extensions.admin.lib import needs_mailbox @login_required diff --git a/modoboa/extensions/admin/app_settings.py b/modoboa/extensions/admin/app_settings.py index 377ce5ebb..8daebb4ef 100644 --- a/modoboa/extensions/admin/app_settings.py +++ b/modoboa/extensions/admin/app_settings.py @@ -1,8 +1,10 @@ from django import forms +from django.conf import settings from django.utils.translation import ugettext_lazy from modoboa.lib.formutils import YesNoField, SeparatorField from modoboa.lib.sysutils import exec_cmd from modoboa.lib import parameters +import os class AdminParametersForm(parameters.AdminParametersForm): @@ -46,9 +48,19 @@ class AdminParametersForm(parameters.AdminParametersForm): def __init__(self, *args, **kwargs): super(AdminParametersForm, self).__init__(*args, **kwargs) hide_fields = False + dpath = None code, output = exec_cmd("which dovecot") if not code: dpath = output.strip() + else: + known_paths = getattr( + settings, "DOVECOT_LOOKUP_PATH", + ("/usr/sbin/dovecot", "/usr/local/sbin/dovecot") + ) + for fpath in known_paths: + if os.path.isfile(fpath) and os.access(fpath, os.X_OK): + dpath = fpath + if dpath: try: code, version = exec_cmd("%s --version" % dpath) except OSError: diff --git a/modoboa/extensions/admin/fixtures/demo.json b/modoboa/extensions/admin/fixtures/demo.json index 206e3d53c..f1971a053 100644 --- a/modoboa/extensions/admin/fixtures/demo.json +++ b/modoboa/extensions/admin/fixtures/demo.json @@ -1 +1 @@ -[{"pk": 1, "model": "admin.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "last_login": "2012-05-03 16:58:51", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26 15:19:25"}}, {"pk": 2, "model": "admin.user", "fields": {"username": "admin@demo.local", "first_name": "Demo", "last_name": "Administrator", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-05-24 05:00:12", "groups": [1], "user_permissions": [], "password": "{CRYPT}SJ2bQWwabfH/6", "email": "admin@demo.local", "date_joined": "2012-05-03 16:50:15"}}, {"pk": 4, "model": "admin.user", "fields": {"username": "user@demo.local", "first_name": "Demo", "last_name": "User", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-05-03 16:56:50", "groups": [2], "user_permissions": [], "password": "{CRYPT}2iAFXtxUA6.7Y", "email": "user@demo.local", "date_joined": "2012-05-03 16:56:50"}}, {"pk": 2, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "domain"], "object_id": 1}}, {"pk": 3, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "user"], "object_id": 2}}, {"pk": 4, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "mailbox"], "object_id": 1}}, {"pk": 5, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "alias"], "object_id": 1}}, {"pk": 6, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "domain"], "object_id": 1}}, {"pk": 7, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "mailbox"], "object_id": 1}}, {"pk": 8, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "user"], "object_id": 2}}, {"pk": 9, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "alias"], "object_id": 1}}, {"pk": 13, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "user"], "object_id": 4}}, {"pk": 14, "model": "admin.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "mailbox"], "object_id": 3}}, {"pk": 15, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "mailbox"], "object_id": 3}}, {"pk": 16, "model": "admin.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "user"], "object_id": 4}}, {"pk": 1, "model": "admin.objectdates", "fields": {"creation": "2012-05-03 16:49:40", "last_modification": "2012-05-03 16:49:40"}}, {"pk": 2, "model": "admin.objectdates", "fields": {"creation": "2012-05-03 16:50:15", "last_modification": "2012-05-03 16:50:36"}}, {"pk": 3, "model": "admin.objectdates", "fields": {"creation": "2012-05-03 16:50:15", "last_modification": "2012-05-03 16:50:15"}}, {"pk": 4, "model": "admin.objectdates", "fields": {"creation": "2012-05-03 16:51:04", "last_modification": "2012-05-03 16:51:04"}}, {"pk": 5, "model": "admin.objectdates", "fields": {"creation": "2012-05-03 16:56:50", "last_modification": "2012-05-03 16:56:50"}}, {"pk": 1, "model": "admin.domain", "fields": {"dates": 1, "enabled": true, "name": "demo.local", "quota": 10}}, {"pk": 1, "model": "admin.mailbox", "fields": {"dates": 2, "quota": 10, "user": 2, "domain": 1, "address": "admin"}}, {"pk": 3, "model": "admin.mailbox", "fields": {"dates": 5, "quota": 10, "user": 4, "domain": 1, "address": "user"}}, {"pk": 1, "model": "admin.alias", "fields": {"dates": 3, "enabled": true, "domain": 1, "mboxes": [1], "address": "postmaster", "extmboxes": ""}}, {"pk": 1, "model": "admin.extension", "fields": {"enabled": true, "name": "limits"}}, {"pk": 2, "model": "admin.extension", "fields": {"enabled": true, "name": "postfix_autoreply"}}, {"pk": 3, "model": "admin.extension", "fields": {"enabled": true, "name": "stats"}}, {"pk": 4, "model": "admin.extension", "fields": {"enabled": true, "name": "amavis"}}, {"pk": 5, "model": "admin.extension", "fields": {"enabled": true, "name": "webmail"}}, {"pk": 6, "model": "admin.extension", "fields": {"enabled": true, "name": "sievefilters"}}, {"pk": "admin@demo.local", "model": "admin.Quota", "fields": {"mbox": 1, "username": "admin@demo.local", "bytes": 0, "messages": 0}}, {"pk": "user@demo.local", "model": "admin.Quota", "fields": {"mbox": 3, "username": "user@demo.local", "bytes": 0, "messages": 0}}] +[{"pk": 1, "model": "core.user", "fields": {"username": "admin", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": false, "last_login": "2012-05-03T16:58:51+01:00", "groups": [], "user_permissions": [], "password": "{CRYPT}dTTsGDkA5ZHKg", "email": "", "date_joined": "2012-01-26T15:19:25+01:00"}}, {"pk": 2, "model": "core.user", "fields": {"username": "admin@demo.local", "first_name": "Demo", "last_name": "Administrator", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-05-24T05:00:12+01:00", "groups": [1], "user_permissions": [], "password": "{CRYPT}SJ2bQWwabfH/6", "email": "admin@demo.local", "date_joined": "2012-05-03T16:50:15+01:00"}}, {"pk": 4, "model": "core.user", "fields": {"username": "user@demo.local", "first_name": "Demo", "last_name": "User", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2012-05-03T16:56:50+01:00", "groups": [2], "user_permissions": [], "password": "{CRYPT}2iAFXtxUA6.7Y", "email": "user@demo.local", "date_joined": "2012-05-03T16:56:50+01:00"}}, {"pk": 2, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "domain"], "object_id": 1}}, {"pk": 3, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["core", "user"], "object_id": 2}}, {"pk": 4, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "mailbox"], "object_id": 1}}, {"pk": 5, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "alias"], "object_id": 1}}, {"pk": 6, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "domain"], "object_id": 1}}, {"pk": 7, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "mailbox"], "object_id": 1}}, {"pk": 8, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["core", "user"], "object_id": 2}}, {"pk": 9, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "alias"], "object_id": 1}}, {"pk": 13, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["core", "user"], "object_id": 4}}, {"pk": 14, "model": "core.objectaccess", "fields": {"is_owner": true, "user": 1, "content_type": ["admin", "mailbox"], "object_id": 3}}, {"pk": 15, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["admin", "mailbox"], "object_id": 3}}, {"pk": 16, "model": "core.objectaccess", "fields": {"is_owner": false, "user": 2, "content_type": ["core", "user"], "object_id": 4}}, {"pk": 1, "model": "admin.objectdates", "fields": {"creation": "2012-05-03T16:49:40+01:00", "last_modification": "2012-05-03T16:49:40+01:00"}}, {"pk": 2, "model": "admin.objectdates", "fields": {"creation": "2012-05-03T16:50:15+01:00", "last_modification": "2012-05-03T16:50:36+01:00"}}, {"pk": 3, "model": "admin.objectdates", "fields": {"creation": "2012-05-03T16:50:15+01:00", "last_modification": "2012-05-03T16:50:15+01:00"}}, {"pk": 4, "model": "admin.objectdates", "fields": {"creation": "2012-05-03T16:51:04+01:00", "last_modification": "2012-05-03T16:51:04+01:00"}}, {"pk": 5, "model": "admin.objectdates", "fields": {"creation": "2012-05-03T16:56:50+01:00", "last_modification": "2012-05-03T16:56:50+01:00"}}, {"pk": 1, "model": "admin.domain", "fields": {"dates": 1, "enabled": true, "name": "demo.local", "quota": 10}}, {"pk": 1, "model": "admin.mailbox", "fields": {"dates": 2, "quota": 10, "user": 2, "domain": 1, "address": "admin"}}, {"pk": 3, "model": "admin.mailbox", "fields": {"dates": 5, "quota": 10, "user": 4, "domain": 1, "address": "user"}}, {"pk": 1, "model": "admin.alias", "fields": {"dates": 3, "enabled": true, "domain": 1, "mboxes": [1], "address": "postmaster", "extmboxes": ""}}, {"pk": 1, "model": "core.extension", "fields": {"enabled": true, "name": "limits"}}, {"pk": 2, "model": "core.extension", "fields": {"enabled": true, "name": "postfix_autoreply"}}, {"pk": 3, "model": "core.extension", "fields": {"enabled": true, "name": "stats"}}, {"pk": 4, "model": "core.extension", "fields": {"enabled": true, "name": "amavis"}}, {"pk": 5, "model": "core.extension", "fields": {"enabled": true, "name": "webmail"}}, {"pk": 6, "model": "core.extension", "fields": {"enabled": true, "name": "sievefilters"}}, {"pk": 7, "model": "core.extension", "fields": {"enabled": true, "name": "postfix_relay_domains"}}, {"pk": "admin@demo.local", "model": "admin.quota", "fields": {"mbox": 1, "username": "admin@demo.local", "bytes": 0, "messages": 0}}, {"pk": "user@demo.local", "model": "admin.quota", "fields": {"mbox": 3, "username": "user@demo.local", "bytes": 0, "messages": 0}}] diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index 327e4bf0c..62c0d6f5b 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -2,7 +2,9 @@ import reversion from django.db import models from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.emailutils import split_mailbox -from modoboa.lib.exceptions import PermDeniedException, BadRequest +from modoboa.lib.exceptions import ( + PermDeniedException, BadRequest, Conflict +) from .base import AdminObject from .domain import Domain from .mailbox import Mailbox @@ -155,6 +157,12 @@ class Alias(AdminObject): raise BadRequest(_("Domain '%s' does not exist" % domname)) if not user.can_access(domain): raise PermDeniedException + try: + Alias.objects.get(address=localpart, domain__name=domain) + except Alias.DoesNotExist: + pass + else: + raise Conflict self.address = localpart self.domain = domain self.enabled = (row[2].strip() == 'True') diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py index 7c19710dd..c0a13d459 100644 --- a/modoboa/extensions/admin/models/domain.py +++ b/modoboa/extensions/admin/models/domain.py @@ -4,7 +4,7 @@ from django.db.models.manager import Manager from django.utils.translation import ugettext as _, ugettext_lazy from django.contrib.contenttypes import generic from modoboa.lib import events, parameters -from modoboa.lib.exceptions import BadRequest +from modoboa.lib.exceptions import BadRequest, Conflict from modoboa.core.models import User, ObjectAccess from .base import AdminObject @@ -131,9 +131,24 @@ class Domain(AdminObject): return self.name def from_csv(self, user, row): + """Create a new domain from a CSV entry. + + The expected fields order is the following:: + + "domain", name, quota, enabled + + :param ``core.User`` user: user creating the domain + :param str row: a list containing domain's definition + """ if len(row) < 4: raise BadRequest(_("Invalid line")) self.name = row[1].strip() + try: + Domain.objects.get(name=self.name) + except Domain.DoesNotExist: + pass + else: + raise Conflict try: self.quota = int(row[2].strip()) except ValueError: diff --git a/modoboa/extensions/admin/models/domain_alias.py b/modoboa/extensions/admin/models/domain_alias.py index a24549b96..29fe93037 100644 --- a/modoboa/extensions/admin/models/domain_alias.py +++ b/modoboa/extensions/admin/models/domain_alias.py @@ -38,12 +38,13 @@ class DomainAlias(AdminObject): if len(row) < 4: raise BadRequest(_("Invalid line")) self.name = row[1].strip() - try: - Domain.objects.get(name=self.name) - except Domain.DoesNotExist: - pass - else: - raise Conflict(_("A domain %s already exists" % self.name)) + for model in [DomainAlias, Domain]: + try: + model.objects.get(name=self.name) + except model.DoesNotExist: + pass + else: + raise Conflict domname = row[2].strip() try: self.target = Domain.objects.get(name=domname) diff --git a/modoboa/extensions/admin/tests/account.py b/modoboa/extensions/admin/tests/account.py index 8a79674bf..5ad4d556f 100644 --- a/modoboa/extensions/admin/tests/account.py +++ b/modoboa/extensions/admin/tests/account.py @@ -187,11 +187,6 @@ class PermissionsTestCase(ModoTestCase): account = User.objects.get(username="superadmin2@test.com") self.clt.logout() self.clt.login(username="admin@test.com", password="toto") - self.ajax_get( - reverse("modoboa.extensions.admin.views.identity.delaccount", - args=[account.id]), - {}, 403 - ) self.ajax_post( reverse("modoboa.extensions.admin.views.identity.delaccount", args=[account.id]), {}, 403 diff --git a/modoboa/extensions/admin/tests/export.py b/modoboa/extensions/admin/tests/export.py index c0e727e04..37b49c005 100644 --- a/modoboa/extensions/admin/tests/export.py +++ b/modoboa/extensions/admin/tests/export.py @@ -20,17 +20,27 @@ class ExportTestCase(ModoTestCase): {"filename": "test.csv"} ) + def assertListEqual(self, list1, list2): + list2 = list2.split('\r\n') + for entry in list1.split('\r\n'): + if not entry: + continue + self.assertIn(entry, list2) + def test_export_identities(self): response = self.__export_identities() - self.assertEqual(response.content, "account;admin;{CRYPT}dTTsGDkA5ZHKg;;;True;SuperAdmins;;\r\naccount;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nforward;forward@test.com;True;user@external.com\r\ndlist;postmaster@test.com;True;toto@titi.com;test@truc.fr\r\n") + self.assertListEqual( + "account;admin;{CRYPT}dTTsGDkA5ZHKg;;;True;SuperAdmins;;\r\naccount;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nforward;forward@test.com;True;user@external.com\r\ndlist;postmaster@test.com;True;toto@titi.com;test@truc.fr\r\n", + response.content.strip() + ) def test_export_simpleusers(self): response = self.__export_identities( idtfilter="account", grpfilter="SimpleUsers" ) - self.assertEqual( - response.content.strip(), - "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10" + self.assertListEqual( + "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10", + response.content.strip() ) def test_export_superadmins(self): @@ -46,9 +56,9 @@ class ExportTestCase(ModoTestCase): response = self.__export_identities( idtfilter="account", grpfilter="DomainAdmins" ) - self.assertEqual( - response.content.strip(), - "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com" + self.assertListEqual( + "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com", + response.content.strip() ) def test_export_aliases(self): diff --git a/modoboa/extensions/admin/tests/import_.py b/modoboa/extensions/admin/tests/import_.py index aeeba148e..8f02fed99 100644 --- a/modoboa/extensions/admin/tests/import_.py +++ b/modoboa/extensions/admin/tests/import_.py @@ -49,7 +49,7 @@ domainalias;test.alias;test.com;True "sourcefile": f } ) - self.assertIn('A domain test.alias already exists', resp.content) + self.assertIn('Object already exists: domainalias', resp.content) def test_identities_import(self): f = ContentFile(b""" diff --git a/modoboa/extensions/admin/views/import.py b/modoboa/extensions/admin/views/import.py index 5ea28efa4..be306e048 100644 --- a/modoboa/extensions/admin/views/import.py +++ b/modoboa/extensions/admin/views/import.py @@ -122,7 +122,7 @@ def importdata(request, formclass=ImportDataForm): fct = fct[0] try: fct(request.user, row, form.cleaned_data) - except IntegrityError, e: + except Conflict: if form.cleaned_data["continue_if_exists"]: continue raise Conflict( diff --git a/modoboa/extensions/amavis/lib.py b/modoboa/extensions/amavis/lib.py index e098f7513..9a9ed39bd 100644 --- a/modoboa/extensions/amavis/lib.py +++ b/modoboa/extensions/amavis/lib.py @@ -12,7 +12,6 @@ from modoboa.lib.webutils import NavigationParameters from modoboa.extensions.amavis.models import Users, Policy - def selfservice(ssfunc=None): """Decorator used to expose views to the 'self-service' feature @@ -121,7 +120,7 @@ def create_user_and_policy(name): :param str name: name """ - policy = Policy.objects.create(policy_name=name) + policy = Policy.objects.create(policy_name=name[:32]) Users.objects.create( email="@%s" % name, fullname=name, priority=7, policy=policy @@ -134,7 +133,7 @@ def create_user_and_use_policy(name, policy_name): :param str name: user record name :param str policy_name: policy name """ - policy = Policy.objects.get(policy_name=policy_name) + policy = Policy.objects.get(policy_name=policy_name[:32]) Users.objects.create( email="@%s" % name, fullname=name, priority=7, policy=policy @@ -152,7 +151,7 @@ def update_user_and_policy(oldname, newname): u = Users.objects.get(email="@%s" % oldname) u.email = "@%s" % newname u.fullname = newname - u.policy.policy_name = newname + u.policy.policy_name = newname[:32] u.policy.save() u.save() diff --git a/modoboa/extensions/amavis/models.py b/modoboa/extensions/amavis/models.py index b15a63c93..50f29305b 100644 --- a/modoboa/extensions/amavis/models.py +++ b/modoboa/extensions/amavis/models.py @@ -83,7 +83,7 @@ class Msgrcpt(models.Model): class Policy(models.Model): - policy_name = models.CharField(max_length=96, blank=True) + policy_name = models.CharField(max_length=32, blank=True) virus_lover = models.CharField(max_length=3, blank=True, null=True) spam_lover = models.CharField(max_length=3, blank=True, null=True) unchecked_lover = models.CharField(max_length=3, blank=True, null=True) diff --git a/modoboa/extensions/limits/fixtures/demo.json b/modoboa/extensions/limits/fixtures/demo.json index 306fdc48d..52a9bc1a1 100644 --- a/modoboa/extensions/limits/fixtures/demo.json +++ b/modoboa/extensions/limits/fixtures/demo.json @@ -1 +1 @@ -[{"pk": 1, "model": "limits.limitspool", "fields": {"user": 2}}, {"pk": 1, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_admins_limit", "pool": 1, "maxvalue": -2}}, {"pk": 2, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domains_limit", "pool": 1, "maxvalue": -2}}, {"pk": 3, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_aliases_limit", "pool": 1, "maxvalue": -2}}, {"pk": 4, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailboxes_limit", "pool": 1, "maxvalue": 5}}, {"pk": 5, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailbox_aliases_limit", "pool": 1, "maxvalue": 5}},{"pk": 3, "model": "auth.group", "fields": {"name": "Resellers", "permissions": [["add_user", "admin", "user"], ["change_user", "admin", "user"], ["delete_user", "admin", "user"], ["view_domains", "admin", "domain"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"],["view_permissions", "auth", "permission"], ["view_domains", "admin", "domain"], ["add_domain", "admin", "domain"], ["change_domain", "admin", "domain"], ["delete_domain", "admin", "domain"]]}}] \ No newline at end of file +[{"pk": 1, "model": "limits.limitspool", "fields": {"user": 2}}, {"pk": 1, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_admins_limit", "pool": 1, "maxvalue": -2}}, {"pk": 2, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domains_limit", "pool": 1, "maxvalue": -2}}, {"pk": 3, "model": "limits.limit", "fields": {"curvalue": 0, "name": "domain_aliases_limit", "pool": 1, "maxvalue": -2}}, {"pk": 4, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailboxes_limit", "pool": 1, "maxvalue": 5}}, {"pk": 5, "model": "limits.limit", "fields": {"curvalue": 0, "name": "mailbox_aliases_limit", "pool": 1, "maxvalue": 5}},{"pk": 3, "model": "auth.group", "fields": {"name": "Resellers", "permissions": [["add_user", "core", "user"], ["change_user", "core", "user"], ["delete_user", "core", "user"], ["view_domains", "admin", "domain"], ["add_mailbox", "admin", "mailbox"], ["change_mailbox", "admin", "mailbox"], ["delete_mailbox", "admin", "mailbox"], ["add_alias", "admin", "alias"], ["change_alias", "admin", "alias"], ["delete_alias", "admin", "alias"], ["view_mailboxes", "admin", "mailbox"], ["view_aliases", "admin", "alias"], ["view_domaliases", "admin", "domainalias"], ["add_domainalias", "admin", "domainalias"], ["change_domainalias", "admin", "domainalias"], ["delete_domainalias", "admin", "domainalias"], ["view_domains", "admin", "domain"], ["add_domain", "admin", "domain"], ["change_domain", "admin", "domain"], ["delete_domain", "admin", "domain"]]}}] \ No newline at end of file diff --git a/modoboa/extensions/postfix_autoreply/__init__.py b/modoboa/extensions/postfix_autoreply/__init__.py index c28dd67e0..fce457e71 100644 --- a/modoboa/extensions/postfix_autoreply/__init__.py +++ b/modoboa/extensions/postfix_autoreply/__init__.py @@ -27,6 +27,8 @@ class PostfixAutoreply(ModoExtension): def init(self): from modoboa.extensions.admin.models import Domain + from modoboa.extensions.postfix_autoreply.general_callbacks \ + import onDomainCreated, onMailboxCreated for dom in Domain.objects.all(): try: diff --git a/modoboa/extensions/postfix_autoreply/forms.py b/modoboa/extensions/postfix_autoreply/forms.py index 211186eb1..cf9cd5ad4 100644 --- a/modoboa/extensions/postfix_autoreply/forms.py +++ b/modoboa/extensions/postfix_autoreply/forms.py @@ -30,9 +30,12 @@ class ARmessageForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(ARmessageForm, self).__init__(*args, **kwargs) - self.fields.keyOrder = ['subject', 'content', 'fromdate', 'untildate', 'enabled'] + self.fields.keyOrder = [ + 'subject', 'content', 'fromdate', 'untildate', 'enabled' + ] if 'instance' in kwargs and kwargs['instance'] is not None: - self.fields['fromdate'].initial = kwargs['instance'].fromdate + self.fields['fromdate'].initial = \ + kwargs['instance'].fromdate.replace(second=0, microsecond=0) self.fields['untildate'].initial = kwargs['instance'].untildate def clean(self): @@ -46,7 +49,7 @@ class ARmessageForm(forms.ModelForm): raise forms.ValidationError(self._errors) if self.cleaned_data["fromdate"] is not None: if self.cleaned_data["fromdate"] < timezone.now(): - self._errrors["fromdate"] = self.error_class([_("This date is over")]) + self._errors["fromdate"] = self.error_class([_("This date is over")]) del self.cleaned_data['fromdate'] else: self.cleaned_data['fromdate'] = timezone.now() @@ -54,7 +57,8 @@ class ARmessageForm(forms.ModelForm): if self.cleaned_data["untildate"] < timezone.now(): self._errors["untildate"] = self.error_class([_("This date is over")]) del self.cleaned_data['untildate'] - elif self.cleaned_data['untildate'] < self.cleaned_data['fromdate']: + elif 'fromdate' in self.cleaned_data and \ + self.cleaned_data['untildate'] < self.cleaned_data['fromdate']: self._errors["untildate"] = \ self.error_class([_("Must be greater than start date")]) del self.cleaned_data['untildate'] diff --git a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py index 450fee4fe..63fb9b655 100644 --- a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py +++ b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py @@ -12,7 +12,7 @@ from modoboa.extensions.postfix_autoreply.models import ARmessage, ARhistoric def send_autoreply(sender, mailbox, armessage): - if armessage.fromdate < timezone.now(): + if armessage.fromdate > timezone.now(): return if armessage.untildate is not None \ and armessage.untildate < timezone.now(): diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py index 0f75eb3f8..cbcfcb03e 100644 --- a/modoboa/extensions/stats/management/commands/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -39,18 +39,20 @@ variables = ["sent", "recv", "bounced", "reject", "spam", "virus", class LogParser(object): + def __init__(self, options, workdir, year=None): + """Constructor + """ self.logfile = options["logfile"] + self.debug = options["debug"] + self.verbose = options["verbose"] try: self.f = open(self.logfile) - except IOError, errno: - if options["debug"]: - print "%s" % errno + except IOError as errno: + self._dprint("%s" % errno) sys.exit(1) self.workdir = workdir self.__year = year - self.debug = options["debug"] - self.verbose = options["verbose"] self.cfs = ['AVERAGE', 'MAX'] curtime = time.localtime() @@ -59,16 +61,74 @@ class LogParser(object): self.curmonth = curtime.tm_mon self.data = {} - domains = Domain.objects.all() self.domains = [] - for dom in domains: + for dom in Domain.objects.all(): self.domains += [str(dom.name)] self.data[str(dom.name)] = {} self.data["global"] = {} self.workdict = {} self.lupdates = {} - self.line_expr = re.compile("(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+([-\w]+)\s+(\w+)/?\w*[[](\d+)[]]:\s+(.*)") + self._s_date_expr = \ + re.compile(r"(?P\w+)\s+(?P\d+)\s+(?P\d+):(?P\d+):(?P\d+)(?P.*)") + self._hp_date_expr = \ + re.compile(r"(?P\d+)-(?P\d+)-(?P\d+)T(?P\d+):(?P\d+):(?P\d+)\.\d+\+\d+:\d+(?P.*)") + self.date_expr = None + self.line_expr = \ + re.compile(r"\s+([-\w]+)\s+(\w+)/?\w*[[](\d+)[]]:\s+(.*)") + self._id_expr = re.compile(r"(\w+): (.*)") + self._prev_se = -1 + self._prev_mi = -1 + self._prev_ho = -1 + self.cur_t = 0 + + def _dprint(self, msg): + """Print a debug message if required. + + :param str msg: debug message + """ + if not self.debug: + return + print msg + + def _parse_date(self, line): + """Try to match a date inside :kw:`line` and to convert it to + a timestamp. + + We try different date format until we find valid one. We then + store it for future use. + + :param str line: a log entry + :return: the remaining part of the line or None + """ + match = None + if self.date_expr is None: + for expr in [self._s_date_expr, self._hp_date_expr]: + match = expr.match(line) + if match is not None: + self.date_expr = expr + break + else: + match = self.date_expr.match(line) + if match is None: + return None + ho = match.group("hour") + mi = match.group("min") + se = match.group("sec") + se = int(int(se) / rrdstep) # rrd step is one-minute => se = 0 + if self._prev_se != se or self._prev_mi != mi or self._prev_ho != ho: + mo = match.group("month") + da = match.group("day") + try: + ye = match.group("year") + except IndexError: + ye = self.year(mo) + self.cur_t = str2Time(ye, mo, da, ho, mi, se) + self.cur_t = self.cur_t - self.cur_t % rrdstep + self._prev_mi = mi + self._prev_ho = ho + self._prev_se = se + return match.group('eol') def init_rrd(self, fname, m): """init_rrd @@ -119,8 +179,7 @@ class LogParser(object): m = t - (t % rrdstep) if not os.path.exists(fname): self.lupdates[fname] = self.init_rrd(fname, m) - if self.debug: - print "[rrd] create new RRD file %s" % fname + self._dprint("[rrd] create new RRD file %s" % fname) else: if not fname in self.lupdates: self.lupdates[fname] = rrdtool.last(str(fname)) @@ -164,21 +223,21 @@ class LogParser(object): self.lupdates[fname] = m return True - def initcounters(self, dom, cur_t): + def initcounters(self, dom): init = {} for v in variables: init[v] = 0 - self.data[dom][cur_t] = init + self.data[dom][self.cur_t] = init - def inc_counter(self, dom, cur_t, counter, val=1): + def inc_counter(self, dom, counter, val=1): if dom is not None and dom in self.domains: - if not cur_t in self.data[dom]: - self.initcounters(dom, cur_t) - self.data[dom][cur_t][counter] += val + if not self.cur_t in self.data[dom]: + self.initcounters(dom) + self.data[dom][self.cur_t][counter] += val - if not cur_t in self.data["global"]: - self.initcounters("global", cur_t) - self.data["global"][cur_t][counter] += val + if not self.cur_t in self.data["global"]: + self.initcounters("global") + self.data["global"][self.cur_t][counter] += val def year(self, month): """Return the appropriate year @@ -203,82 +262,76 @@ class LogParser(object): return self.__year - 1 return self.__year - def process(self): - id_expr = re.compile("([0-9A-F]+): (.*)") - prev_se = -1 - prev_mi = -1 - prev_ho = -1 - for line in self.f.readlines(): - m = self.line_expr.match(line) - if not m: - continue - (mo, da, ho, mi, se, host, prog, pid, log) = m.groups() - se = int(int(se) / rrdstep) # rrd step is one-minute => se = 0 + def _parse_line(self, line): + """Parse a single log line. - if prev_se != se or prev_mi != mi or prev_ho != ho: - cur_t = str2Time(self.year(mo), mo, da, ho, mi, se) - cur_t = cur_t - cur_t % rrdstep - prev_mi = mi - prev_ho = ho - prev_se = se - m = id_expr.match(log) - if m: - (line_id, line_log) = m.groups() + :param str line: log line + """ + line = self._parse_date(line) + if line is None: + return + m = self.line_expr.match(line) + if not m: + return + host, prog, pid, log = m.groups() + m = self._id_expr.match(log) + if m is None: + self._dprint("Unknown line format: %s" % log) + return + (line_id, line_log) = m.groups() + if line_id == "NOQUEUE": + addrto = re.match("reject: .*from=<.*> to=<[^@]+@([^>]+)>", line_log) + if addrto and addrto.group(1) in self.domains: + self.inc_counter(addrto.group(1), 'reject') + return + m = re.search("message-id=<([^>]*)>", line_log) + if m is not None: + self.workdict[line_id] = {'from': m.group(1), 'size': 0} + return + m = re.search("from=<([^>]*)>, size=(\d+)", line_log) + if m is not None: + self.workdict[line_id] = { + 'from': m.group(1), 'size': string.atoi(m.group(2)) + } + return - m = re.search("message-id=<([^>]*)>", line_log) - if m: - self.workdict[line_id] = {'from': m.group(1), 'size': 0} - continue - - m = re.search("from=<([^>]*)>, size=(\d+)", line_log) - if m: - self.workdict[line_id] = {'from': m.group(1), - 'size': string.atoi(m.group(2))} - continue - - m = re.search("to=<([^>]*)>.*status=(\S+)", line_log) - if m: - if not line_id in self.workdict: - if self.debug: - print "Inconsistent mail (%s: %s), skipping" % (line_id, m.group(1)) - continue - if not m.group(2) in variables: - if self.debug: - print "Unsupported status %s, skipping" % m.group(2) - continue - - addrfrom = re.match("([^@]+)@(.+)", self.workdict[line_id]['from']) - if addrfrom is not None and addrfrom.group(2) in self.domains: - self.inc_counter(addrfrom.group(2), cur_t, 'sent') - self.inc_counter(addrfrom.group(2), cur_t, 'size_sent', - self.workdict[line_id]['size']) - addrto = re.match("([^@]+)@(.+)", m.group(1)) - domname = addrto.group(2) if addrto is not None else None - if m.group(2) == "sent": - self.inc_counter(addrto.group(2), cur_t, 'recv') - self.inc_counter(addrto.group(2), cur_t, 'size_recv', - self.workdict[line_id]['size']) - else: - self.inc_counter(domname, cur_t, m.group(2)) - continue - - if self.debug: - print "Unknown line format: %s" % line_log + m = re.search("to=<([^>]*)>.*status=(\S+)", line_log) + if m is not None: + if not line_id in self.workdict: + self._dprint("Inconsistent mail (%s: %s), skipping" \ + % (line_id, m.group(1))) + return + if not m.group(2) in variables: + self._dprint("Unsupported status %s, skipping" % m.group(2)) + return + addrfrom = re.match("([^@]+)@(.+)", self.workdict[line_id]['from']) + if addrfrom is not None and addrfrom.group(2) in self.domains: + self.inc_counter(addrfrom.group(2), 'sent') + self.inc_counter(addrfrom.group(2), 'size_sent', + self.workdict[line_id]['size']) + addrto = re.match("([^@]+)@(.+)", m.group(1)) + domname = addrto.group(2) if addrto is not None else None + if m.group(2) == "sent": + self.inc_counter(addrto.group(2), 'recv') + self.inc_counter(addrto.group(2), 'size_recv', + self.workdict[line_id]['size']) else: - m = re.match("NOQUEUE: reject: .*from=<(.*)> to=<([^>]*)>", log) - if m: - addrto = re.match("([^@]+)@(.+)", m.group(2)) - if addrto and addrto.group(2) in self.domains: - self.inc_counter(addrto.group(2), cur_t, 'reject') - continue - if self.debug: - print "Unknown line format: %s" % log + self.inc_counter(domname, m.group(2)) + return + self._dprint("Unknown line format: %s" % line_log) + + def process(self): + """Process the log file. + + We parse it and then generate standard graphics (day, week, + month). + """ + for line in self.f.readlines(): + self._parse_line(line) - # Sort everything by time G = Grapher() for dom, data in self.data.iteritems(): - if self.debug: - print "[rrd] dealing with domain %s" % dom + self._dprint("[rrd] dealing with domain %s" % dom) for t in sorted(data.keys()): self.update_rrd(dom, t) diff --git a/modoboa/extensions/webmail/lib.py b/modoboa/extensions/webmail/lib.py index 3eb63628b..0b099f8ef 100644 --- a/modoboa/extensions/webmail/lib.py +++ b/modoboa/extensions/webmail/lib.py @@ -582,8 +582,8 @@ def save_attachment(f): def clean_attachments(attlist): """Remove all attachments from the filesystem - :param attlist: a list of 2-uple. Each element must contain the following information : - (random name, real name). + :param attlist: a list of 2-uple. Each element must contain the + following information : (random name, real name). """ for att in attlist: fullpath = os.path.join(settings.MEDIA_ROOT, "webmail", att["tmpname"]) diff --git a/modoboa/lib/fixtures/demo.json b/modoboa/lib/fixtures/demo.json index 046dd26f0..cdd99ecb9 100644 --- a/modoboa/lib/fixtures/demo.json +++ b/modoboa/lib/fixtures/demo.json @@ -3,7 +3,7 @@ "pk": 2, "model": "lib.parameter", "fields": { - "name": "admin.PASSWORD_SCHEME", + "name": "core.PASSWORD_SCHEME", "value": "crypt" } }, @@ -11,7 +11,7 @@ "pk": 3, "model": "lib.parameter", "fields": { - "name": "admin.ITEMS_PER_PAGE", + "name": "core.ITEMS_PER_PAGE", "value": "30" } }, @@ -19,23 +19,15 @@ "pk": 4, "model": "lib.parameter", "fields": { - "name": "general.DEFAULT_TOP_REDIRECTION", + "name": "core.DEFAULT_TOP_REDIRECTION", "value": "user" } }, - { - "pk": 6, - "model": "lib.parameter", - "fields": { - "name": "general.SECRET_KEY", - "value": "abcdefghijklmnop" - } - }, { "pk": 8, "model": "lib.parameter", "fields": { - "name": "admin.AUTHENTICATION_TYPE", + "name": "core.AUTHENTICATION_TYPE", "value": "local" } }, diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py index 5cf677aaf..8834a5cfe 100644 --- a/modoboa/lib/permissions.py +++ b/modoboa/lib/permissions.py @@ -56,21 +56,18 @@ def grant_access_to_object(user, obj, is_owner=False): else: return - try: - ObjectAccess.objects.create(user=user, content_type=ct, - object_id=obj.id, is_owner=is_owner) - if is_owner: - from modoboa.core.models import User - for su in User.objects.filter(is_superuser=True): - if su == user: - continue - try: - ObjectAccess.objects.create(user=su, content_type=ct, object_id=obj.id) - except IntegrityError: - pass - - except IntegrityError, e: - raise ModoboaException(_("Failed to grant access (%s)" % str(e))) + ObjectAccess.objects.create( + user=user, content_type=ct, object_id=obj.id, is_owner=is_owner + ) + if not is_owner: + return + from modoboa.core.models import User + for su in User.objects.filter(is_superuser=True): + if su == user: + continue + ObjectAccess.objects.get_or_create( + user=su, content_type=ct, object_id=obj.id + ) def grant_access_to_objects(user, objects, ct): diff --git a/modoboa/locale/de/LC_MESSAGES/django.po b/modoboa/locale/de/LC_MESSAGES/django.po index 3fe643142..bd96b891d 100644 --- a/modoboa/locale/de/LC_MESSAGES/django.po +++ b/modoboa/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: Modoboa-0.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-12-15 10:21+0100\n" -"PO-Revision-Date: 2013-12-08 23:33+0100\n" +"PO-Revision-Date: 2013-12-23 14:26+0100\n" "Last-Translator: Patrick Ben Koetter \n" "Language-Team: DE \n" "Language: de\n" @@ -20,13 +20,17 @@ msgstr "" "X-Poedit-Country: GERMANY\n" "X-Poedit-SourceCharset: utf-8\n" -#: core/__init__.py:52 core/__init__.py:53 -#: extensions/admin/forms/account.py:326 extensions/admin/forms/domain.py:251 -#: extensions/admin/views/domain.py:95 extensions/admin/views/identity.py:127 +#: core/__init__.py:52 +#: core/__init__.py:53 +#: extensions/admin/forms/account.py:326 +#: extensions/admin/forms/domain.py:251 +#: extensions/admin/views/domain.py:95 +#: extensions/admin/views/identity.py:127 #: extensions/postfix_autoreply/app_settings.py:11 #: extensions/postfix_relay_domains/forms.py:138 #: extensions/sievefilters/app_settings.py:50 -#: extensions/stats/app_settings.py:11 extensions/webmail/app_settings.py:11 +#: extensions/stats/app_settings.py:11 +#: extensions/webmail/app_settings.py:11 msgid "General" msgstr "Grundsätzlich" @@ -79,12 +83,8 @@ msgid "Rounds" msgstr "Runden" #: core/app_settings.py:64 -msgid "" -"Number of rounds to use (only used by sha256crypt and sha512crypt). Must be " -"between 1000 and 999999999, inclusive." -msgstr "" -"Anzahl zu verwendender Runden (nur für sha256crypt und sha512crypt). Zahl " -"muss zwischen 1000 und 999999999 liegen." +msgid "Number of rounds to use (only used by sha256crypt and sha512crypt). Must be between 1000 and 999999999, inclusive." +msgstr "Anzahl zu verwendender Runden (nur für sha256crypt und sha512crypt). Zahl muss zwischen 1000 und 999999999 liegen." #: core/app_settings.py:70 msgid "Secret key" @@ -98,8 +98,10 @@ msgstr "Verwendeter Schlüssel, um Passworte zu ver-/entschlüsseln" msgid "LDAP settings" msgstr "LDAP-Einstellungen" -#: core/app_settings.py:79 extensions/sievefilters/app_settings.py:22 -#: extensions/webmail/app_settings.py:22 extensions/webmail/app_settings.py:42 +#: core/app_settings.py:79 +#: extensions/sievefilters/app_settings.py:22 +#: extensions/webmail/app_settings.py:22 +#: extensions/webmail/app_settings.py:42 msgid "Server address" msgstr "Server-Adresse" @@ -107,8 +109,10 @@ msgstr "Server-Adresse" msgid "The IP address of the DNS name of the LDAP server" msgstr "Die IP-Adresse des LDAP-Server Hostnamens" -#: core/app_settings.py:85 extensions/sievefilters/app_settings.py:28 -#: extensions/webmail/app_settings.py:34 extensions/webmail/app_settings.py:58 +#: core/app_settings.py:85 +#: extensions/sievefilters/app_settings.py:28 +#: extensions/webmail/app_settings.py:34 +#: extensions/webmail/app_settings.py:58 msgid "Server port" msgstr "Server-Port" @@ -116,7 +120,8 @@ msgstr "Server-Port" msgid "The TCP port number used by the LDAP server" msgstr "Der TCP Port des LDAP-Servers" -#: core/app_settings.py:91 extensions/webmail/app_settings.py:28 +#: core/app_settings.py:91 +#: extensions/webmail/app_settings.py:28 msgid "Use a secured connection" msgstr "Gesicherte Verbindung verwenden" @@ -145,11 +150,8 @@ msgid "Bind DN" msgstr "Bind DN" #: core/app_settings.py:108 -msgid "" -"The distinguished name to use when binding to the LDAP server. Leave empty " -"for an anonymous bind" -msgstr "" -"Der DN für einen Bind an den LDAP-Server. Nichts eingeben für anonymen Bind." +msgid "The distinguished name to use when binding to the LDAP server. Leave empty for an anonymous bind" +msgstr "Der DN für einen Bind an den LDAP-Server. Nichts eingeben für anonymen Bind." #: core/app_settings.py:113 msgid "Bind password" @@ -172,12 +174,8 @@ msgid "Search filter" msgstr "Suchfilter" #: core/app_settings.py:130 -msgid "" -"An optional filter string (e.g. '(objectClass=person)'). In order to be " -"valid, it must be enclosed in parentheses." -msgstr "" -"Ein optionaler Filter z.B. (objectClass=person). Das Filter muss " -"entsprechend der LDAP-Konvention in Klammern gesetzt werden." +msgid "An optional filter string (e.g. '(objectClass=person)'). In order to be valid, it must be enclosed in parentheses." +msgstr "Ein optionaler Filter z.B. (objectClass=person). Das Filter muss entsprechend der LDAP-Konvention in Klammern gesetzt werden." #: core/app_settings.py:135 msgid "User DN template" @@ -185,12 +183,8 @@ msgstr "Vorlage für User DN" #: core/app_settings.py:137 #, python-format -msgid "" -"The template used to construct a user's DN. It should contain one " -"placeholder (ie. %(user)s)" -msgstr "" -"Die Vorlage für einen User DN. Sie sollte einen Platzhalter z.B. %(user)s " -"enthalten." +msgid "The template used to construct a user's DN. It should contain one placeholder (ie. %(user)s)" +msgstr "Die Vorlage für einen User DN. Sie sollte einen Platzhalter z.B. %(user)s enthalten." #: core/app_settings.py:142 msgid "Password attribute" @@ -213,12 +207,8 @@ msgid "Administrator groups" msgstr "Administrator-Gruppen" #: core/app_settings.py:157 -msgid "" -"Members of those LDAP Posix groups will be created as domain administrators. " -"Use ';' characters to separate groups." -msgstr "" -"Mitglieder dieser LDAP Posix-Gruppe werden als Domain-Administratoren " -"angelegt werden. Nutzen sie ';', um Gruppen zu separieren." +msgid "Members of those LDAP Posix groups will be created as domain administrators. Use ';' characters to separate groups." +msgstr "Mitglieder dieser LDAP Posix-Gruppe werden als Domain-Administratoren angelegt werden. Nutzen sie ';', um Gruppen zu separieren." #: core/app_settings.py:164 msgid "Groups search base" @@ -261,7 +251,8 @@ msgstr "Die Standardumleitung wenn kein Programm angegeben wurde" msgid "Key must be either 16, 24, or 32 bytes long" msgstr "Schlüssel muss 16, 24 oder 32 Byte lang sein" -#: core/app_settings.py:227 extensions/postfix_autoreply/app_settings.py:53 +#: core/app_settings.py:227 +#: extensions/postfix_autoreply/app_settings.py:53 msgid "Invalid syntax" msgstr "Ungültige Syntax" @@ -273,7 +264,8 @@ msgstr "Ungültige Zahl für Runden" msgid "This field is required" msgstr "Dieses Feld ist erforderlich" -#: core/app_settings.py:317 extensions/amavis/app_settings.py:87 +#: core/app_settings.py:317 +#: extensions/amavis/app_settings.py:87 #: extensions/amavis/templates/amavis/main_action_bar.html:29 #: extensions/webmail/app_settings.py:73 msgid "Display" @@ -287,12 +279,14 @@ msgstr "Bevorzugte Sprache" msgid "Prefered language to display pages" msgstr "Bevorzugte Sprache für Seitendarstellung" -#: core/forms.py:10 extensions/admin/forms/account.py:19 +#: core/forms.py:10 +#: extensions/admin/forms/account.py:19 #: extensions/admin/templates/admin/editdomainform.html:13 msgid "Username" msgstr "Benutzername" -#: core/forms.py:14 extensions/admin/forms/account.py:31 +#: core/forms.py:14 +#: extensions/admin/forms/account.py:31 msgid "Password" msgstr "Passwort" @@ -304,7 +298,8 @@ msgstr "Altes Passwort" msgid "New password" msgstr "Neues Passwort" -#: core/forms.py:33 extensions/admin/forms/account.py:34 +#: core/forms.py:33 +#: extensions/admin/forms/account.py:34 msgid "Confirmation" msgstr "Bestätigung" @@ -336,7 +331,8 @@ msgstr "Konnte Kennwort nicht aktualisieren: LDAP-Modul nicht installiert" msgid "account" msgstr "Konto" -#: core/models.py:321 extensions/admin/models/domain.py:135 +#: core/models.py:321 +#: extensions/admin/models/domain.py:135 #: extensions/admin/models/domain_alias.py:39 #: extensions/postfix_relay_domains/models.py:134 #: extensions/postfix_relay_domains/models.py:190 @@ -355,11 +351,10 @@ msgstr "Der normale Benutzer '%s' muss eine gültige E-Mail-Adresse besitzen" #: core/models.py:335 #, python-format msgid "username and email fields must not differ for '%s'" -msgstr "" -"Die Felder für Benutzername und E-Mail für '%s' dürfen sich nicht " -"unterscheiden" +msgstr "Die Felder für Benutzername und E-Mail für '%s' dürfen sich nicht unterscheiden" -#: core/models.py:404 extensions/admin/models/alias.py:33 +#: core/models.py:404 +#: extensions/admin/models/alias.py:33 #: extensions/admin/models/domain.py:32 #: extensions/admin/models/domain_alias.py:17 #: extensions/postfix_autoreply/models.py:28 @@ -380,7 +375,8 @@ msgstr "hinzugefügt" msgid "modified" msgstr "verändert" -#: core/models.py:480 core/models.py:504 +#: core/models.py:480 +#: core/models.py:504 #, python-format msgid "%(object)s '%(name)s' %(action)s by user %(user)s" msgstr "%(object)s '%(name)s' %(action)s der Identität %(user)s" @@ -389,8 +385,10 @@ msgstr "%(object)s '%(name)s' %(action)s der Identität %(user)s" msgid "deleted" msgstr "entfernt" -#: core/tables.py:8 core/templates/core/information.html:8 -#: extensions/admin/tables.py:9 extensions/admin/forms/domain.py:182 +#: core/tables.py:8 +#: core/templates/core/information.html:8 +#: extensions/admin/tables.py:9 +#: extensions/admin/forms/domain.py:182 #: extensions/admin/templates/admin/domains_table.html:5 #: extensions/admin/templates/admin/editdomainform.html:13 #: extensions/admin/templates/admin/identities_table.html:5 @@ -399,15 +397,18 @@ msgstr "entfernt" msgid "Name" msgstr "Name" -#: core/tables.py:10 extensions/admin/tables.py:11 +#: core/tables.py:10 +#: extensions/admin/tables.py:11 msgid "Version" msgstr "Version" -#: core/tables.py:12 extensions/admin/tables.py:13 +#: core/tables.py:12 +#: extensions/admin/tables.py:13 msgid "Description" msgstr "Beschreibung" -#: core/templates/core/extensions.html:2 core/templatetags/core_tags.py:48 +#: core/templates/core/extensions.html:2 +#: core/templatetags/core_tags.py:48 msgid "Extensions" msgstr "Erweiterungen" @@ -415,12 +416,14 @@ msgstr "Erweiterungen" msgid "Choose the extension(s) to use" msgstr "Extension auswählen" -#: core/templates/core/extensions.html:6 core/templates/core/parameters.html:7 +#: core/templates/core/extensions.html:6 +#: core/templates/core/parameters.html:7 #: core/templates/core/user_preferences.html:8 msgid "Save" msgstr "Speichern" -#: core/templates/core/information.html:2 core/templatetags/core_tags.py:53 +#: core/templates/core/information.html:2 +#: core/templatetags/core_tags.py:53 msgid "Information" msgstr "Information" @@ -444,7 +447,8 @@ msgstr "Gruppenname" msgid "Last login" msgstr "Letzte Anmeldung" -#: core/templates/core/logs.html:2 core/templatetags/core_tags.py:57 +#: core/templates/core/logs.html:2 +#: core/templatetags/core_tags.py:57 msgid "Logs" msgstr "Logs" @@ -452,8 +456,10 @@ msgstr "Logs" msgid "Previously on Modoboa..." msgstr "Vorher auf Modoboa…" -#: core/templates/core/logs.html:6 extensions/amavis/sql_listing.py:46 -#: extensions/webmail/lib.py:48 extensions/webmail/lib.py:425 +#: core/templates/core/logs.html:6 +#: extensions/amavis/sql_listing.py:46 +#: extensions/webmail/lib.py:48 +#: extensions/webmail/lib.py:425 msgid "Date" msgstr "Datum" @@ -469,7 +475,8 @@ msgstr "Logger" msgid "Message" msgstr "Nachricht" -#: core/templates/core/parameters.html:2 core/templatetags/core_tags.py:62 +#: core/templates/core/parameters.html:2 +#: core/templatetags/core_tags.py:62 msgid "Parameters" msgstr "Parameter" @@ -481,7 +488,8 @@ msgstr "Modoboa konfigurieren" msgid "Modoboa settings" msgstr "Modoboa-Einstellungen" -#: core/templates/core/user_index.html:2 core/templatetags/core_tags.py:81 +#: core/templates/core/user_index.html:2 +#: core/templatetags/core_tags.py:81 msgid "Settings" msgstr "Einstellungen" @@ -494,7 +502,8 @@ msgstr "Einstellungen" msgid "Customize Modoboa" msgstr "Modoboa anpassen" -#: core/templates/core/user_profile.html:2 core/templatetags/core_tags.py:104 +#: core/templates/core/user_profile.html:2 +#: core/templatetags/core_tags.py:104 msgid "Profile" msgstr "Profil" @@ -504,11 +513,13 @@ msgstr "Aktualisieren sie ihre persönlichen Daten" #: core/templates/core/user_profile.html:8 #: extensions/admin/templates/admin/forward.html:8 -#: extensions/admin/views/alias.py:107 extensions/admin/views/domain.py:165 +#: extensions/admin/views/alias.py:107 +#: extensions/admin/views/domain.py:165 #: extensions/admin/views/identity.py:197 #: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9 #: extensions/postfix_relay_domains/views.py:63 -#: extensions/sievefilters/views.py:163 extensions/webmail/views.py:170 +#: extensions/sievefilters/views.py:163 +#: extensions/webmail/views.py:170 #: extensions/webmail/views.py:205 msgid "Update" msgstr "Aktualisieren" @@ -536,9 +547,7 @@ msgstr "Identität '%s' hat sich erfolgreich angemeldet" #: core/views/auth.py:43 msgid "Your username and password didn't match. Please try again." -msgstr "" -"Ihr Benutzername und Passwort stimmen nicht überein. Bitte versuchen Sie es " -"noch einmal." +msgstr "Ihr Benutzername und Passwort stimmen nicht überein. Bitte versuchen Sie es noch einmal." #: core/views/auth.py:66 #, python-format @@ -565,7 +574,8 @@ msgstr "Virus senden" msgid "Send spam" msgstr "Spam senden" -#: demo/views.py:18 demo/views.py:43 +#: demo/views.py:18 +#: demo/views.py:43 msgid "Message sent" msgstr "Nachricht gesendet" @@ -574,31 +584,26 @@ msgid "" "\n" "

Welcome to the online demo!

\n" "

Warning: the demo's concent is resetted every two hours.

\n" -"

To try the demo, the following users are available (username/password):

\n" +"

To try the demo, the following users are available (username/password):

\n" "
    \n" "
  • A super administrator : admin/password
  • \n" "
  • A domain administrator : admin@demo.local/admin
  • \n" "
  • A simple user : user@demo.local/user
  • \n" "
\n" "

Please report any issue or give any suggestion to \n" -" the " -"mailing list.

\n" +" the mailing list.

\n" msgstr "" "\n" "

Willkommen zur Online Demo!

\n" -"

Warnung: die Inhalte dieser Demo werden alle zwei Stunden gelöscht." -"

\n" -"

Folgende User (Benutzername/Kennwort) stehen zum Testen zur " -"Verfügung:

\n" +"

Warnung: die Inhalte dieser Demo werden alle zwei Stunden gelöscht.

\n" +"

Folgende User (Benutzername/Kennwort) stehen zum Testen zur Verfügung:

\n" "
    \n" "
  • Super-Administrator : admin/password
  • \n" "
  • Domänen-Administrator : admin@demo.local/admin
  • \n" "
  • Normaler Benutzer: user@demo.local/user
  • \n" "
\n" "

Probleme und Anregungen bitte an die\n" -" Mailingliste berichten.

\n" +" Mailingliste berichten.

\n" #: extensions/admin/__init__.py:48 msgid "Administration console" @@ -614,7 +619,8 @@ msgstr "Administration" #: extensions/admin/__init__.py:79 #: extensions/admin/templates/admin/domains.html:2 -#: extensions/limits/app_settings.py:19 extensions/limits/models.py:17 +#: extensions/limits/app_settings.py:19 +#: extensions/limits/models.py:17 msgid "Domains" msgstr "Domänen" @@ -636,7 +642,8 @@ msgstr "Kann Konto nicht importieren (%s): Die Domain existiert nicht" #: extensions/admin/app_settings.py:11 #: extensions/admin/templates/admin/editdomainform.html:25 -#: extensions/limits/app_settings.py:31 extensions/limits/models.py:23 +#: extensions/limits/app_settings.py:31 +#: extensions/limits/models.py:23 #: extensions/webmail/app_settings.py:107 #: extensions/webmail/templates/webmail/folders.html:4 msgid "Mailboxes" @@ -647,12 +654,8 @@ msgid "Handle mailboxes on filesystem" msgstr "Mailbox im Dateisystem verwalten" #: extensions/admin/app_settings.py:16 -msgid "" -"Rename or remove mailboxes on the filesystem when they get renamed or " -"removed within Modoboa" -msgstr "" -"Mailboxen auch in Dateisystem umbenennen oder entfernen wenn sie in Modoboa " -"umbenannt oder entfernt werden" +msgid "Rename or remove mailboxes on the filesystem when they get renamed or removed within Modoboa" +msgstr "Mailboxen auch in Dateisystem umbenennen oder entfernen wenn sie in Modoboa umbenannt oder entfernt werden" #: extensions/admin/app_settings.py:20 msgid "Mailboxes ower" @@ -660,21 +663,15 @@ msgstr "Mailbox-Besitzer" #: extensions/admin/app_settings.py:22 msgid "The UNIX account who owns mailboxes on the filesystem" -msgstr "" -"UID des virtuellen Benutzers, der Besitzer der Domains, Mailboxen und " -"Nachrichten im Dateisystem ist." +msgstr "UID des virtuellen Benutzers, der Besitzer der Domains, Mailboxen und Nachrichten im Dateisystem ist." #: extensions/admin/app_settings.py:26 msgid "Default domain quota" msgstr "Standard Domainquota" #: extensions/admin/app_settings.py:29 -msgid "" -"Default quota (in MB) applied to freshly created domains with no value " -"specified. A value of 0 means no quota." -msgstr "" -"Standardquota (in MB) für neu erstelle Domains ohne explizite Wertangabe. " -"Der Wert 0 bedeutet „Kein Quota“" +msgid "Default quota (in MB) applied to freshly created domains with no value specified. A value of 0 means no quota." +msgstr "Standardquota (in MB) für neu erstelle Domains ohne explizite Wertangabe. Der Wert 0 bedeutet „Kein Quota“" #: extensions/admin/app_settings.py:36 msgid "Automatic account removal" @@ -684,7 +681,8 @@ msgstr "Automatische Konto-Entfernung" msgid "When a mailbox is removed, also remove the associated account" msgstr "Beim Löschen der Mailbox auch das Konto entfernen." -#: extensions/admin/app_settings.py:69 extensions/admin/forms/account.py:178 +#: extensions/admin/app_settings.py:69 +#: extensions/admin/forms/account.py:178 #: extensions/admin/forms/domain.py:56 msgid "Must be a positive integer" msgstr "Muss eine positive Integer sein" @@ -694,18 +692,15 @@ msgid "A mailbox is required" msgstr "Ein Mailbox ist erforderlich" #: extensions/admin/forms/account.py:21 -#, fuzzy -msgid "" -"The user's name. Must be a valid e-mail address for simple users or " -"administrators with a mailbox." -msgstr "" -"Der Anwendername. Muss eine gültige E-Mail-Adresse für 'simple users' sein." +msgid "The user's name. Must be a valid e-mail address for simple users or administrators with a mailbox." +msgstr "Der Anwendername. Muss eine gültige E-Mail-Adresse für 'simple users' oder Administratoren mit einer Mailbox sein." #: extensions/admin/forms/account.py:26 msgid "Role" msgstr "Rolle" -#: extensions/admin/forms/account.py:27 extensions/admin/forms/account.py:55 +#: extensions/admin/forms/account.py:27 +#: extensions/admin/forms/account.py:55 msgid "Choose" msgstr "Auswählen" @@ -733,37 +728,28 @@ msgstr "Sie können Ihr eigenes Konto nicht deaktivieren" msgid "E-mail" msgstr "E-Mail" -#: extensions/admin/forms/account.py:113 extensions/admin/forms/domain.py:17 +#: extensions/admin/forms/account.py:113 +#: extensions/admin/forms/domain.py:17 msgid "Quota" msgstr "Quota" #: extensions/admin/forms/account.py:115 -msgid "" -"Quota in MB for this mailbox. Define a custom value or use domain's default " -"one. Leave empty to define an unlimited value (not allowed for domain " -"administrators)." -msgstr "" -"Quota in MB für diese Mailbox. Geben Sie einen eigenen Wert an oder nutzen " -"Sie den Standardwert der Domain. Lassen Sie das Feld leer für unbegrenztes " -"Quota - Domänen-Administratoren ist dies nicht gestattet." +msgid "Quota in MB for this mailbox. Define a custom value or use domain's default one. Leave empty to define an unlimited value (not allowed for domain administrators)." +msgstr "Quota in MB für diese Mailbox. Geben Sie einen eigenen Wert an oder nutzen Sie den Standardwert der Domain. Lassen Sie das Feld leer für unbegrenztes Quota - Domänen-Administratoren ist dies nicht gestattet." -#: extensions/admin/forms/account.py:123 extensions/admin/forms/domain.py:26 +#: extensions/admin/forms/account.py:123 +#: extensions/admin/forms/domain.py:26 #: extensions/admin/templates/admin/domains_table.html:6 #: extensions/postfix_relay_domains/forms.py:12 msgid "Alias(es)" msgstr "Aliase" #: extensions/admin/forms/account.py:126 -msgid "" -"Alias(es) of this mailbox. Indicate only one address per input, press ENTER " -"to add a new input. Use the '*' character to create a 'catchall' alias (ex: " -"*@domain.tld)." -msgstr "" -"Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro Eingabe " -"an. Bestätigen Sie mit ENTER um die Eingabe zu bestätigen. Geben Sie '*' an, " -"um einen 'catchall'-Alias (Bsp: *@example.com) zu erstellen." +msgid "Alias(es) of this mailbox. Indicate only one address per input, press ENTER to add a new input. Use the '*' character to create a 'catchall' alias (ex: *@domain.tld)." +msgstr "Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro Eingabe an. Bestätigen Sie mit ENTER um die Eingabe zu bestätigen. Geben Sie '*' an, um einen 'catchall'-Alias (Bsp: *@example.com) zu erstellen." -#: extensions/admin/forms/account.py:187 extensions/admin/forms/account.py:217 +#: extensions/admin/forms/account.py:187 +#: extensions/admin/forms/account.py:217 #: extensions/admin/forms/alias.py:65 msgid "Domain does not exist" msgstr "Domain existiert nicht" @@ -795,24 +781,16 @@ msgid "Email address" msgstr "E-Mail Adresse" #: extensions/admin/forms/alias.py:18 -msgid "" -"The distribution list address. Use the '*' character to create a 'catchall' " -"address (ex: *@domain.tld)." -msgstr "" -"Adresse einer Verteilerliste. Geben Sie '*' an, um einen 'catchall'-Alias " -"(Bsp: *@example.com) zu erstellen." +msgid "The distribution list address. Use the '*' character to create a 'catchall' address (ex: *@domain.tld)." +msgstr "Adresse einer Verteilerliste. Geben Sie '*' an, um einen 'catchall'-Alias (Bsp: *@example.com) zu erstellen." #: extensions/admin/forms/alias.py:23 msgid "Recipients" msgstr "Empfänger" #: extensions/admin/forms/alias.py:25 -msgid "" -"Mailbox(es) this alias will point to. Indicate only one address per input, " -"press ENTER to add a new input." -msgstr "" -"Mailboxen auf die der Alias verweist. Geben Sie jeweils nur eine Adresse ein " -"und bestätigen Sie mit ENTER." +msgid "Mailbox(es) this alias will point to. Indicate only one address per input, press ENTER to add a new input." +msgstr "Mailboxen auf die der Alias verweist. Geben Sie jeweils nur eine Adresse ein und bestätigen Sie mit ENTER." #: extensions/admin/forms/alias.py:68 msgid "You don't have access to this domain" @@ -822,12 +800,14 @@ msgstr "Der Zugriff auf diese Domain ist ihnen nicht gestattet" msgid "Invalid mailbox" msgstr "Ungültige Mailbox" -#: extensions/admin/forms/alias.py:108 extensions/admin/models/alias.py:182 +#: extensions/admin/forms/alias.py:108 +#: extensions/admin/models/alias.py:182 #, python-format msgid "Local recipient %s not found" msgstr "Lokaler Empfänger %s nicht gefunden" -#: extensions/admin/forms/alias.py:112 extensions/admin/forms/alias.py:120 +#: extensions/admin/forms/alias.py:112 +#: extensions/admin/forms/alias.py:120 #, python-format msgid "Recipient %s already present" msgstr "Empfänger %s existiert bereits" @@ -837,21 +817,12 @@ msgid "No recipient defined" msgstr "Keine Empfänger angegeben" #: extensions/admin/forms/domain.py:20 -msgid "" -"Default quota in MB applied to mailboxes. Leave empty to use the default " -"value." -msgstr "" -"Standardquota in MB für Mailboxen. Bei leerem Feld wird der Domain-Standard " -"genutzt." +msgid "Default quota in MB applied to mailboxes. Leave empty to use the default value." +msgstr "Standardquota in MB für Mailboxen. Bei leerem Feld wird der Domain-Standard genutzt." #: extensions/admin/forms/domain.py:29 -msgid "" -"Alias(es) of this domain. Indicate only one name per input, press ENTER to " -"add a new input." -msgstr "" -"Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro " -"Eingabefeld an. Bestätigen Sie mit ENTER, um ein neues Eingabefeld zu " -"erhalten." +msgid "Alias(es) of this domain. Indicate only one name per input, press ENTER to add a new input." +msgstr "Alias(e) für diese Mailbox. Geben Sie jeweils nur eine Adresse pro Eingabefeld an. Bestätigen Sie mit ENTER, um ein neues Eingabefeld zu erhalten." #: extensions/admin/forms/domain.py:75 #: extensions/postfix_relay_domains/forms.py:50 @@ -859,7 +830,8 @@ msgstr "" msgid "domain alias" msgstr "Domain-Alias" -#: extensions/admin/forms/domain.py:82 extensions/admin/forms/domain.py:98 +#: extensions/admin/forms/domain.py:82 +#: extensions/admin/forms/domain.py:98 #: extensions/postfix_relay_domains/forms.py:58 #: extensions/postfix_relay_domains/forms.py:78 #, python-format @@ -881,12 +853,8 @@ msgid "Automatically create an administrator for this domain" msgstr "Automatisch Administrator für diese Domain anlegen" #: extensions/admin/forms/domain.py:185 -msgid "" -"The administrator's name. Don't include the domain's name here, it will be " -"automatically appended." -msgstr "" -"Name des Administrators. Geben Sie nicht den Domainnamen mit an. Er wird " -"automatisch hinzugefügt." +msgid "The administrator's name. Don't include the domain's name here, it will be automatically appended." +msgstr "Name des Administrators. Geben Sie nicht den Domainnamen mit an. Er wird automatisch hinzugefügt." #: extensions/admin/forms/domain.py:193 msgid "Create aliases" @@ -909,7 +877,8 @@ msgstr "Identität %s existiert bereits" msgid "File name" msgstr "Dateiname" -#: extensions/admin/forms/export.py:10 extensions/admin/forms/import_.py:8 +#: extensions/admin/forms/export.py:10 +#: extensions/admin/forms/import_.py:8 msgid "Separator" msgstr "Separator" @@ -930,14 +899,11 @@ msgid "Forward messages and store copies into your local mailbox" msgstr "Nachricht weiterleiten und Kopie in Mailbox ablegen" #: extensions/admin/forms/forward.py:38 -msgid "" -"You can't define a forward to a local destination. Please ask your " -"administrator to create an alias instead." -msgstr "" -"Sie können keine Weiterleitung auf ein lokales Ziel anlegen. Bitten Sie " -"Ihren Administrator stattdessen einen Alias anzulegen." +msgid "You can't define a forward to a local destination. Please ask your administrator to create an alias instead." +msgstr "Sie können keine Weiterleitung auf ein lokales Ziel anlegen. Bitten Sie Ihren Administrator stattdessen einen Alias anzulegen." -#: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:26 +#: extensions/admin/forms/import_.py:6 +#: extensions/webmail/forms.py:26 msgid "Select a file" msgstr "Wählen Sie eine Datei" @@ -957,17 +923,14 @@ msgstr "Passworte verschlüsseln" msgid "Check this option if passwords contained in your file are not crypted" msgstr "Auswählen wenn Kennwörter in Datei nicht verschlüsselt sind" -#: extensions/admin/models/alias.py:16 extensions/admin/models/mailbox.py:51 +#: extensions/admin/models/alias.py:16 +#: extensions/admin/models/mailbox.py:51 msgid "address" msgstr "Adresse" #: extensions/admin/models/alias.py:18 -msgid "" -"The alias address (without the domain part). For a 'catch-all' address, just " -"enter an * character." -msgstr "" -"Die Alias-Adresse (ohne den Domain-Anteil). Geben sie für eine Adresse an, " -"die alles annimmt, * an." +msgid "The alias address (without the domain part). For a 'catch-all' address, just enter an * character." +msgstr "Die Alias-Adresse (ohne den Domain-Anteil). Geben sie für eine Adresse an, die alles annimmt, * an." #: extensions/admin/models/alias.py:24 msgid "mailboxes" @@ -1120,12 +1083,14 @@ msgid "Last modification date" msgstr "Datum der letzten Änderung" #: extensions/admin/templates/admin/editdomainform.html:24 -#: extensions/limits/app_settings.py:25 extensions/limits/models.py:20 +#: extensions/limits/app_settings.py:25 +#: extensions/limits/models.py:20 msgid "Domain aliases" msgstr "Domänen-Aliase" #: extensions/admin/templates/admin/editdomainform.html:26 -#: extensions/limits/app_settings.py:37 extensions/limits/models.py:25 +#: extensions/limits/app_settings.py:37 +#: extensions/limits/models.py:25 msgid "Mailbox aliases" msgstr "Mailboxen-Aliase" @@ -1193,13 +1158,15 @@ msgstr "Domain hinzufügen" #: extensions/admin/templatetags/admin_tags.py:42 #: extensions/admin/templatetags/admin_tags.py:106 -#: extensions/admin/views/import.py:51 extensions/admin/views/import.py:166 +#: extensions/admin/views/import.py:51 +#: extensions/admin/views/import.py:166 msgid "Import" msgstr "Importiere" #: extensions/admin/templatetags/admin_tags.py:48 #: extensions/admin/templatetags/admin_tags.py:112 -#: extensions/admin/views/export.py:38 extensions/admin/views/export.py:64 +#: extensions/admin/views/export.py:38 +#: extensions/admin/views/export.py:64 msgid "Export" msgstr "Exportiere" @@ -1247,11 +1214,14 @@ msgstr "Berechtigung entfernen" msgid "Alias with this name already exists" msgstr "Ein Alias mit diesem Namen existiert bereits" -#: extensions/admin/views/alias.py:49 extensions/admin/views/domain.py:100 -#: extensions/admin/views/domain.py:129 extensions/admin/views/identity.py:131 +#: extensions/admin/views/alias.py:49 +#: extensions/admin/views/domain.py:100 +#: extensions/admin/views/domain.py:129 +#: extensions/admin/views/identity.py:131 #: extensions/admin/views/identity.py:158 #: extensions/postfix_relay_domains/views.py:32 -#: extensions/sievefilters/views.py:141 extensions/sievefilters/views.py:230 +#: extensions/sievefilters/views.py:141 +#: extensions/sievefilters/views.py:230 #: extensions/webmail/views.py:151 msgid "Create" msgstr "Erstellen" @@ -1292,7 +1262,8 @@ msgstr "Weiterleitung verändert" msgid "Alias modified" msgstr "Alias verändert" -#: extensions/admin/views/domain.py:96 extensions/admin/views/identity.py:128 +#: extensions/admin/views/domain.py:96 +#: extensions/admin/views/identity.py:128 msgid "Next" msgstr "Nächstes" @@ -1300,7 +1271,8 @@ msgstr "Nächstes" msgid "Options" msgstr "optionen" -#: extensions/admin/views/domain.py:101 extensions/admin/views/identity.py:132 +#: extensions/admin/views/domain.py:101 +#: extensions/admin/views/identity.py:132 msgid "Previous" msgstr "Vorheriges" @@ -1336,16 +1308,26 @@ msgstr "Domains exportieren" #: extensions/admin/views/identity.py:103 #: extensions/admin/views/identity.py:224 -#: extensions/admin/views/identity.py:229 extensions/amavis/views.py:179 -#: extensions/amavis/views.py:185 extensions/amavis/views.py:220 -#: extensions/amavis/views.py:224 extensions/amavis/views.py:226 -#: extensions/webmail/views.py:47 extensions/webmail/views.py:65 -#: extensions/webmail/views.py:79 extensions/webmail/views.py:97 -#: extensions/webmail/views.py:114 extensions/webmail/views.py:200 -#: extensions/webmail/views.py:223 extensions/webmail/views.py:396 -#: extensions/webmail/views.py:430 extensions/webmail/views.py:443 -#: extensions/webmail/views.py:472 extensions/webmail/views.py:512 -#: lib/formutils.py:44 lib/formutils.py:49 +#: extensions/admin/views/identity.py:229 +#: extensions/amavis/views.py:179 +#: extensions/amavis/views.py:185 +#: extensions/amavis/views.py:220 +#: extensions/amavis/views.py:224 +#: extensions/amavis/views.py:226 +#: extensions/webmail/views.py:47 +#: extensions/webmail/views.py:65 +#: extensions/webmail/views.py:79 +#: extensions/webmail/views.py:97 +#: extensions/webmail/views.py:114 +#: extensions/webmail/views.py:200 +#: extensions/webmail/views.py:223 +#: extensions/webmail/views.py:396 +#: extensions/webmail/views.py:430 +#: extensions/webmail/views.py:443 +#: extensions/webmail/views.py:472 +#: extensions/webmail/views.py:512 +#: lib/formutils.py:44 +#: lib/formutils.py:49 msgid "Invalid request" msgstr "Ungültige Anfrage" @@ -1376,8 +1358,7 @@ msgid "" "
  • domainalias; name; targeted domain; enabled
  • \n" " %s\n" "\n" -"

    The first element of each line is mandatory and must be equal to one of " -"the previous values.

    \n" +"

    The first element of each line is mandatory and must be equal to one of the previous values.

    \n" "

    You can use a different character as separator.

    \n" msgstr "" "Verwenden sie eine CSV-Datei mit einem der folgenden Formate:\n" @@ -1386,8 +1367,7 @@ msgstr "" "
  • domainalias; name; targeted domain; enabled
  • \n" " %s\n" "\n" -"

    Das erste Element jeder Zeile ist zwingend und muss gleich zum " -"vorhergehenden sein.

    \n" +"

    Das erste Element jeder Zeile ist zwingend und muss gleich zum vorhergehenden sein.

    \n" "

    Ein anderes Zeichen als Trenner ist gestattet.

    \n" #: extensions/admin/views/import.py:50 @@ -1408,27 +1388,23 @@ msgstr "%d Objekte erfolgreich importiert" msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
      \n" -"
    • account; loginname; password; first name; last name; enabled; group; " -"address; quota; [, domain, ...]
    • \n" +"
    • account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
    • \n" "
    • alias; address; enabled; internal recipient
    • \n" "
    • forward; address; enabled; external recipient
    • \n" "
    • dlist; address; enabled; recipient; recipient; ...
    • \n" "
    \n" -"

    The first element of each line is mandatory and must be equal to one of " -"the previous values.

    \n" +"

    The first element of each line is mandatory and must be equal to one of the previous values.

    \n" "\n" "

    You can use a different character as separator.

    \n" msgstr "" "Verwenden sie eine CSV-Datei in einem der folgenden Formate:\n" "
      \n" -"
    • account; loginname; password; first name; last name; enabled; group; " -"address; quota; [, domain, ...]
    • \n" +"
    • account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
    • \n" "
    • alias; address; enabled; internal recipient
    • \n" "
    • forward; address; enabled; external recipient
    • \n" "
    • dlist; address; enabled; recipient; recipient; ...
    • \n" "
    \n" -"

    Das erste Element einer Zeile ist zwingend und muss gleich mit einem der " -"vorhergehenden sein.

    \n" +"

    Das erste Element einer Zeile ist zwingend und muss gleich mit einem der vorhergehenden sein.

    \n" "\n" "

    Ein anderes Zeichen als Separator ist gestattet.

    \n" @@ -1444,7 +1420,8 @@ msgstr "Weiterleitung aktualisiert" msgid "Simple amavis management frontend" msgstr "Einfache amavis Management Oberfläche" -#: extensions/amavis/__init__.py:52 extensions/amavis/general_callbacks.py:17 +#: extensions/amavis/__init__.py:52 +#: extensions/amavis/general_callbacks.py:17 msgid "Quarantine" msgstr "Quarantäne" @@ -1458,9 +1435,7 @@ msgstr "Maximales Alter einer Nachricht" #: extensions/amavis/app_settings.py:16 msgid "Quarantine messages maximum age (in days) before deletion" -msgstr "" -"Maximales Alter (in Tagen) von Nachrichten in der Quarantäne bevor sie " -"gelöscht werden" +msgstr "Maximales Alter (in Tagen) von Nachrichten in der Quarantäne bevor sie gelöscht werden" #: extensions/amavis/app_settings.py:19 msgid "Messages releasing" @@ -1536,18 +1511,16 @@ msgstr "Absender von Benachrichtigungen" #: extensions/amavis/app_settings.py:74 msgid "The e-mail address used to send notitications" -msgstr "" -"Die Mailadresse, die verwendet wird, um Benachrichtigungen zu versenden" +msgstr "Die Mailadresse, die verwendet wird, um Benachrichtigungen zu versenden" -#: extensions/amavis/app_settings.py:91 extensions/webmail/app_settings.py:91 +#: extensions/amavis/app_settings.py:91 +#: extensions/webmail/app_settings.py:91 msgid "Number of displayed emails per page" msgstr "Anzahl dargestellter Nachrichten pro Seite" #: extensions/amavis/app_settings.py:92 msgid "Set the maximum number of messages displayed in a page" -msgstr "" -"Legt die maximale Anzahl von Nachrichten fest, die in einer Seite " -"dargestellt werden" +msgstr "Legt die maximale Anzahl von Nachrichten fest, die in einer Seite dargestellt werden" #: extensions/amavis/general_callbacks.py:81 msgid "pending requests" @@ -1570,17 +1543,22 @@ msgstr "Verbindung zu amavis fehlgeschlagen: %s" msgid "Virus filter" msgstr "Virusfilter" -#: extensions/amavis/models.py:94 extensions/amavis/models.py:102 -#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:290 +#: extensions/amavis/models.py:94 +#: extensions/amavis/models.py:102 +#: extensions/amavis/models.py:110 +#: extensions/sievefilters/views.py:290 msgid "yes" msgstr "Ja" -#: extensions/amavis/models.py:95 extensions/amavis/models.py:103 -#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:294 +#: extensions/amavis/models.py:95 +#: extensions/amavis/models.py:103 +#: extensions/amavis/models.py:111 +#: extensions/sievefilters/views.py:294 msgid "no" msgstr "Nein" -#: extensions/amavis/models.py:96 extensions/amavis/models.py:104 +#: extensions/amavis/models.py:96 +#: extensions/amavis/models.py:104 #: extensions/amavis/models.py:112 #: extensions/amavis/templates/amavis/domain_content_filter.html:11 msgid "default" @@ -1588,9 +1566,7 @@ msgstr "Standard" #: extensions/amavis/models.py:98 msgid "Bypass virus checks or not. Choose 'default' to use global settings." -msgstr "" -"Virus-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu " -"nutzen, keinen individuellen Wert an." +msgstr "Virus-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu nutzen, keinen individuellen Wert an." #: extensions/amavis/models.py:101 msgid "Spam filter" @@ -1598,9 +1574,7 @@ msgstr "SPAM-Filter" #: extensions/amavis/models.py:106 msgid "Bypass spam checks or not. Choose 'default' to use global settings." -msgstr "" -"Spam-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu " -"nutzen, keinen individuellen Wert an." +msgstr "Spam-Prüfungen umgehen oder nicht. Geben Sie, um den Domain-Standard zu nutzen, keinen individuellen Wert an." #: extensions/amavis/models.py:109 msgid "Banned filter" @@ -1608,21 +1582,15 @@ msgstr "Filter für unerwünschte Dateien" #: extensions/amavis/models.py:114 msgid "Bypass banned checks or not. Choose 'default' to use global settings." -msgstr "" -"Unerwünschte Dateien umgehen oder nicht. Geben Sie, um den Domain-Standard " -"zu nutzen, keinen individuellen Wert an." +msgstr "Unerwünschte Dateien umgehen oder nicht. Geben Sie, um den Domain-Standard zu nutzen, keinen individuellen Wert an." #: extensions/amavis/models.py:144 msgid "Spam marker" msgstr "SPAM-Markierung" #: extensions/amavis/models.py:146 -msgid "" -"Modify spam subject using the specified text. Choose 'default' to use global " -"settings." -msgstr "" -"Betreff:-Zeile einer Spam-Nachricht mit dem angegebenen Text ergänzen. " -"Wählen Sie 'Standard' für den systemweiten Standard." +msgid "Modify spam subject using the specified text. Choose 'default' to use global settings." +msgstr "Betreff:-Zeile einer Spam-Nachricht mit dem angegebenen Text ergänzen. Wählen Sie 'Standard' für den systemweiten Standard." #: extensions/amavis/sql_listing.py:31 msgid "Score" @@ -1635,13 +1603,17 @@ msgid "To" msgstr "An" #: extensions/amavis/sql_listing.py:38 -#: extensions/postfix_autoreply/forms.py:11 extensions/webmail/lib.py:44 +#: extensions/postfix_autoreply/forms.py:11 +#: extensions/webmail/lib.py:44 msgid "From" msgstr "Von" -#: extensions/amavis/sql_listing.py:42 extensions/sievefilters/forms.py:77 -#: extensions/webmail/forms.py:11 extensions/webmail/lib.py:40 -#: extensions/webmail/lib.py:423 templates/common/email_searchbar.html:6 +#: extensions/amavis/sql_listing.py:42 +#: extensions/sievefilters/forms.py:77 +#: extensions/webmail/forms.py:11 +#: extensions/webmail/lib.py:40 +#: extensions/webmail/lib.py:423 +#: templates/common/email_searchbar.html:6 msgid "Subject" msgstr "Betreff" @@ -1810,18 +1782,15 @@ msgstr "Rektion auf diese Nachricht:" #: extensions/amavis/templates/amavis/notifications/pending_requests.html:14 #, python-format msgid "Please visit %(listingurl)s for a full listing." -msgstr "" -"Bitte besuchen sie %(listingurl)s um eine vollständige Ausgabe zu erhalten." +msgstr "Bitte besuchen sie %(listingurl)s um eine vollständige Ausgabe zu erhalten." #: extensions/amavis/templatetags/amavis_tags.py:28 msgid "View full headers" msgstr "Alle Mail-Header ansehen" #: extensions/limits/__init__.py:25 -msgid "" -"Per administrator resources to limit the number of objects they can create" -msgstr "" -"Administrator-Ressourcen, um die Anzahl erstellbarer Objekte einzuschränken" +msgid "Per administrator resources to limit the number of objects they can create" +msgstr "Administrator-Ressourcen, um die Anzahl erstellbarer Objekte einzuschränken" #: extensions/limits/__init__.py:56 msgid "Limits" @@ -1831,15 +1800,14 @@ msgstr "Grenzwerte" msgid "Default limits" msgstr "Standard-Grenzwerte" -#: extensions/limits/app_settings.py:13 extensions/limits/models.py:14 +#: extensions/limits/app_settings.py:13 +#: extensions/limits/models.py:14 msgid "Domain admins" msgstr "Domänen-Administratoren" #: extensions/limits/app_settings.py:15 msgid "Maximum number of allowed domain administrators for a new administrator" -msgstr "" -"Maximale Anzahl Domänenadministratoren, die ein neuer Administrator " -"erstellen darf" +msgstr "Maximale Anzahl Domänenadministratoren, die ein neuer Administrator erstellen darf" #: extensions/limits/app_settings.py:21 msgid "Maximum number of allowed domains for a new administrator" @@ -1847,8 +1815,7 @@ msgstr "Maximale Anzahl Domains, die ein neuer Administrator erstellen darf" #: extensions/limits/app_settings.py:27 msgid "Maximum number of allowed domain aliases for a new administrator" -msgstr "" -"Maximale Anzahl Domain Aliase, die ein neuer Administrator erstellen darf" +msgstr "Maximale Anzahl Domain Aliase, die ein neuer Administrator erstellen darf" #: extensions/limits/app_settings.py:33 msgid "Maximum number of allowed mailboxes for a new administrator" @@ -1858,7 +1825,8 @@ msgstr "Maximale Anzahl Mailboxen, die ein neuer Administrator erstellen darf" msgid "Maximum number of allowed aliases for a new administrator" msgstr "Maximale Anzahl Aliase, die ein neuer Administrator erstellen darf" -#: extensions/limits/forms.py:28 extensions/limits/forms.py:35 +#: extensions/limits/forms.py:28 +#: extensions/limits/forms.py:35 msgid "Invalid limit" msgstr "Ungültiger Grenzwert" @@ -1868,8 +1836,7 @@ msgstr "Ihre Ressourcen wurde noch nicht initialisiert" #: extensions/limits/forms.py:61 msgid "You're not allowed to define unlimited values" -msgstr "" -"Sie verfügen nicht über ausreichend Rechte, um unbegrenzte Werte anzugeben" +msgstr "Sie verfügen nicht über ausreichend Rechte, um unbegrenzte Werte anzugeben" #: extensions/limits/general_callbacks.py:10 msgid "Reseller" @@ -1922,8 +1889,7 @@ msgstr "Ressourcen-Verbrauch" #: extensions/postfix_autoreply/__init__.py:26 msgid "Auto-reply (vacation) functionality using Postfix" -msgstr "" -"Automatische Antwort (Abwesenheitsbenachrichtigung) über Postfix-Programm" +msgstr "Automatische Antwort (Abwesenheitsbenachrichtigung) über Postfix-Programm" #: extensions/postfix_autoreply/__init__.py:47 msgid "Automatic replies" @@ -1935,9 +1901,7 @@ msgstr "Zeitüberschreitung für automatische Antworten" #: extensions/postfix_autoreply/app_settings.py:16 msgid "Timeout in seconds between two auto-replies to the same recipient" -msgstr "" -"Zeit in Sekunden zwischen zwei automatisierten Antworten an denselben " -"Empfänger" +msgstr "Zeit in Sekunden zwischen zwei automatisierten Antworten an denselben Empfänger" #: extensions/postfix_autoreply/app_settings.py:20 msgid "Default subject" @@ -1948,8 +1912,7 @@ msgid "I'm off" msgstr "Ich bin weg" #: extensions/postfix_autoreply/app_settings.py:23 -msgid "" -"Default subject used when an auto-reply message is created automatically" +msgid "Default subject used when an auto-reply message is created automatically" msgstr "Standardbetreff wenn eine Antwortnachricht automatisch generiert wird" #: extensions/postfix_autoreply/app_settings.py:28 @@ -1971,12 +1934,8 @@ msgstr "" #: extensions/postfix_autoreply/app_settings.py:36 #, python-format -msgid "" -"Default content used when an auto-reply message is created automatically. " -"The '%(name)s' macro will be replaced by the user's full name." -msgstr "" -"Standardinhalt wenn eine Antwort automatisch erstellt wird. Das '%(name)s' " -"Makro wird gegen den vollen Anwendernamen ersetzt." +msgid "Default content used when an auto-reply message is created automatically. The '%(name)s' macro will be replaced by the user's full name." +msgstr "Standardinhalt wenn eine Antwort automatisch erstellt wird. Das '%(name)s' Makro wird gegen den vollen Anwendernamen ersetzt." #: extensions/postfix_autoreply/forms.py:13 msgid "Activate your auto reply from this date" @@ -2038,9 +1997,7 @@ msgstr "Automatische Antwort erfolgreich aktualisiert." #: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2 msgid "Define a message to automatically send when you are off" -msgstr "" -"Gegen sie eine Nachricht an, die gesendet werden soll, wenn Sie nicht " -"erreichbar sind" +msgstr "Gegen sie eine Nachricht an, die gesendet werden soll, wenn Sie nicht erreichbar sind" #: extensions/postfix_relay_domains/__init__.py:72 msgid "Relay domains support for Postfix" @@ -2061,12 +2018,8 @@ msgid "Path to the master.cf configuration file" msgstr "Pfad zur master.cf Konfigurationsdatei" #: extensions/postfix_relay_domains/forms.py:15 -msgid "" -"Alias(es) of this relay domain. Indicate only one name per input, press " -"ENTER to add a new input." -msgstr "" -"Alias(e) für diese Relaydomain. Geben Sie jeweils nur einen pro Eingabefeld " -"an. Bestätigen Sie mit ENTER, um ein weiteres Eingabefeld zu erhalten." +msgid "Alias(es) of this relay domain. Indicate only one name per input, press ENTER to add a new input." +msgstr "Alias(e) für diese Relaydomain. Geben Sie jeweils nur einen pro Eingabefeld an. Bestätigen Sie mit ENTER, um ein weiteres Eingabefeld zu erhalten." #: extensions/postfix_relay_domains/forms.py:51 #: extensions/postfix_relay_domains/general_callbacks.py:93 @@ -2098,25 +2051,20 @@ msgstr "Maximale Anzahl Relaydomain-Aliase, die dieser Anwender erstellen darf" #: extensions/postfix_relay_domains/general_callbacks.py:111 msgid "" "\n" -"
  • relaydomain; name; target host; service; enabled; verify recipients
  • \n" +"
  • relaydomain; name; target host; service; enabled; verify recipients
  • \n" "
  • relaydomainalias; name; target; enabled
  • \n" msgstr "" "\n" -"
  • relaydomain; name; target host; service; enabled; verify recipients
  • \n" +"
  • relaydomain; name; target host; service; enabled; verify recipients
  • \n" "
  • relaydomainalias; name; target; enabled
  • \n" #: extensions/postfix_relay_domains/limits_callbacks.py:19 msgid "Maximum number of allowed relay domains for a new administrator" -msgstr "" -"Maximale Anzahl Relaydomains, die ein neuer Administrator erstellen darf" +msgstr "Maximale Anzahl Relaydomains, die ein neuer Administrator erstellen darf" #: extensions/postfix_relay_domains/limits_callbacks.py:27 msgid "Maximum number of allowed relay domain aliases for a new administrator" -msgstr "" -"Maximale Anzahl Relaydomain-Aliase, die ein neuer Administrator erstellen " -"darf" +msgstr "Maximale Anzahl Relaydomain-Aliase, die ein neuer Administrator erstellen darf" #: extensions/postfix_relay_domains/models.py:59 msgid "The service name" @@ -2257,7 +2205,8 @@ msgstr "Sender" msgid "Recipient" msgstr "Empfänger" -#: extensions/sievefilters/forms.py:80 extensions/webmail/forms.py:8 +#: extensions/sievefilters/forms.py:80 +#: extensions/webmail/forms.py:8 msgid "Cc" msgstr "Cc" @@ -2283,9 +2232,7 @@ msgstr "Leite Nachricht um zu" #: extensions/sievefilters/lib.py:40 msgid "Connection to MANAGESIEVE server failed, check your configuration" -msgstr "" -"Verbindung zu MANAGESIEVE-Server fehlgeschlagen. Überprüfen Sie Ihre " -"Konfiguration." +msgstr "Verbindung zu MANAGESIEVE-Server fehlgeschlagen. Überprüfen Sie Ihre Konfiguration." #: extensions/sievefilters/lib.py:85 msgid "Not enough space on server" @@ -2362,11 +2309,8 @@ msgid "active" msgstr "aktiv" #: extensions/sievefilters/templates/sievefilters/index.html:94 -msgid "" -"No filters set defined yet. You must create one in order to define filters." -msgstr "" -"Nich keine Filter-Sätze definiert. Sie müssen einen erstellen, damit sie " -"Filter erstellen können." +msgid "No filters set defined yet. You must create one in order to define filters." +msgstr "Nich keine Filter-Sätze definiert. Sie müssen einen erstellen, damit sie Filter erstellen können." #: extensions/sievefilters/templatetags/sfilters_tags.py:15 msgid "New filters set" @@ -2506,7 +2450,8 @@ msgstr "Jahr" msgid "Total" msgstr "Gesamt" -#: extensions/stats/views.py:28 extensions/stats/templates/stats/graphs.html:4 +#: extensions/stats/views.py:28 +#: extensions/stats/templates/stats/graphs.html:4 msgid "No statistics available" msgstr "Keine Statistik-Daten verfügbar" @@ -2612,9 +2557,7 @@ msgstr "Aktiviere/Deaktiviere Darstellung von HTML-Links" #: extensions/webmail/app_settings.py:92 msgid "Sets the maximum number of messages displayed in a page" -msgstr "" -"Legt die maximale Anzahl von Nachrichten fest, die in einer Seite " -"dargestellt werden" +msgstr "Legt die maximale Anzahl von Nachrichten fest, die in einer Seite dargestellt werden" #: extensions/webmail/app_settings.py:97 msgid "Listing refresh rate" @@ -2625,13 +2568,12 @@ msgid "Automatic folder refresh rate (in seconds)" msgstr "Aktualisierungsintervall für Ordner (in Sekunden)" #: extensions/webmail/app_settings.py:103 -#, fuzzy msgid "Mailboxes container's width" -msgstr "Mailbox-Besitzer" +msgstr "Breite des Mailboxcontainers" #: extensions/webmail/app_settings.py:104 msgid "The width of the mailbox list container" -msgstr "" +msgstr "Die Breite der Mailbox-Liste" #: extensions/webmail/app_settings.py:111 msgid "Trash folder" @@ -2678,9 +2620,8 @@ msgid "User defined email signature" msgstr "Benutzerdefinierte E-Mail-Signatur" #: extensions/webmail/app_settings.py:160 -#, fuzzy msgid "Value must be a positive integer (> 0)" -msgstr "Muss eine positive Integer sein" +msgstr "Wert muss eine positive Integer sein (>0)" #: extensions/webmail/exceptions.py:20 msgid "Server response" @@ -2711,7 +2652,8 @@ msgstr "Verbindung zu IMAP-Server fehlgeschlagen: %s" msgid "wrote:" msgstr "schrieb:" -#: extensions/webmail/lib.py:437 extensions/webmail/lib.py:441 +#: extensions/webmail/lib.py:437 +#: extensions/webmail/lib.py:441 msgid "Original message" msgstr "Gesendete Nachrichten" @@ -2722,7 +2664,8 @@ msgid_plural "%(count)d messages deleted" msgstr[0] "%(count)d Nachricht gelöscht" msgstr[1] "%(count)d Nachrichten gelöscht" -#: extensions/webmail/views.py:116 lib/email_listing.py:138 +#: extensions/webmail/views.py:116 +#: lib/email_listing.py:138 msgid "Empty mailbox" msgstr "Mailbox leer" @@ -2735,7 +2678,8 @@ msgstr "Mailbox erstellt." msgid "Create a new mailbox" msgstr "Neue Mailbox erstellen" -#: extensions/webmail/views.py:167 extensions/webmail/views.py:202 +#: extensions/webmail/views.py:167 +#: extensions/webmail/views.py:202 msgid "Edit mailbox" msgstr "Mailbox bearbeiten" @@ -2879,7 +2823,8 @@ msgstr "Erlaubnis verweigert: %s" msgid "Permission denied" msgstr "Berechtigung verweigert" -#: lib/formutils.py:187 lib/formutils.py:195 +#: lib/formutils.py:187 +#: lib/formutils.py:195 msgid "Enter a valid domain name" msgstr "Geben Sie einen gültigen Domain-Namen an" @@ -2921,7 +2866,8 @@ msgstr "Keine Einträge darzustellen" msgid "activate" msgstr "aktivieren" -#: templates/404.html:4 templates/500.html:4 +#: templates/404.html:4 +#: templates/500.html:4 msgid "Sorry" msgstr "Entschuldigung" diff --git a/modoboa/locale/it/LC_MESSAGES/django.po b/modoboa/locale/it/LC_MESSAGES/django.po index f34f4bd71..5a0c0f658 100644 --- a/modoboa/locale/it/LC_MESSAGES/django.po +++ b/modoboa/locale/it/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-15 10:20+0100\n" -"PO-Revision-Date: 2013-09-27 00:07+0200\n" +"POT-Creation-Date: 2013-12-22 23:15+0100\n" +"PO-Revision-Date: 2013-12-23 00:56+0100\n" "Last-Translator: Alberto Berti \n" "Language-Team: ITALIANO \n" "Language: it\n" @@ -49,23 +49,23 @@ msgstr "Schema password predefinito" #: core/app_settings.py:51 msgid "md5crypt (weak)" -msgstr "" +msgstr "md5crypt (debole)" #: core/app_settings.py:52 msgid "sha256 (weak)" -msgstr "" +msgstr "sha256 (debole)" #: core/app_settings.py:53 msgid "md5 (weak)" -msgstr "" +msgstr "md5 (debole)" #: core/app_settings.py:54 msgid "crypt (weak)" -msgstr "" +msgstr "crypt (debole)" #: core/app_settings.py:55 msgid "plain (weak)" -msgstr "" +msgstr "plain (debole)" #: core/app_settings.py:57 msgid "Scheme used to crypt mailbox passwords" @@ -74,13 +74,13 @@ msgstr "" #: core/app_settings.py:61 msgid "Rounds" -msgstr "" +msgstr "Cicli" #: core/app_settings.py:64 msgid "" "Number of rounds to use (only used by sha256crypt and sha512crypt). Must be " "between 1000 and 999999999, inclusive." -msgstr "" +msgstr "Numero di cicli da utilizzare (valido per sha256crypt e sha512crypt). Dev'essere tra 1000 e 999999999, inclusivo." #: core/app_settings.py:70 msgid "Secret key" @@ -159,14 +159,12 @@ msgstr "" "DN')" #: core/app_settings.py:121 -#, fuzzy msgid "Users search base" -msgstr "Ricerca base" +msgstr "Base ricerca per gli utenti" #: core/app_settings.py:123 -#, fuzzy msgid "The distinguished name of the search base used to find users" -msgstr "Nome particolare della ricerca base" +msgstr "L'identificativo (dn:) della base di ricerca utilizzata per cercare gli utenti" #: core/app_settings.py:128 msgid "Search filter" @@ -210,25 +208,22 @@ msgid "Tell if the LDAP server is an Active Directory one" msgstr "Segnala se il server LDAP è una Active Directory" #: core/app_settings.py:154 -#, fuzzy msgid "Administrator groups" -msgstr "Amministratori" +msgstr "Gruppi degli amministratori" #: core/app_settings.py:157 msgid "" "Members of those LDAP Posix groups will be created as domain administrators. " "Use ';' characters to separate groups." -msgstr "" +msgstr "Gli appartenenti a questi gruppi LDAP Posix avranno i privilegi di amministratori di dominio. Utilizza il carattere ';' per separare valori multipli." #: core/app_settings.py:164 -#, fuzzy msgid "Groups search base" -msgstr "Ricerca base" +msgstr "Base ricerca per i gruppi" #: core/app_settings.py:167 -#, fuzzy msgid "The distinguished name of the search base used to find groups" -msgstr "Nome particolare della ricerca base" +msgstr "L'identificatore (dn:) della base di ricerca utilizzato per trovare i gruppi" #: core/app_settings.py:172 #: extensions/admin/templates/admin/editdomainform.html:7 @@ -270,9 +265,8 @@ msgid "Invalid syntax" msgstr "Sintassi errata" #: core/app_settings.py:233 -#, fuzzy msgid "Invalid rounds number" -msgstr "Richiesta non valida" +msgstr "Numero di cicli non valido" #: core/app_settings.py:256 msgid "This field is required" @@ -322,14 +316,12 @@ msgid "Passwords mismatch" msgstr "La password non corrisponde" #: core/models.py:50 -#, fuzzy msgid "password" -msgstr "Password" +msgstr "password" #: core/models.py:52 -#, fuzzy msgid "last login" -msgstr "Ultimo login" +msgstr "ultimo login" #: core/models.py:81 msgid "You can't delete your own account" @@ -513,7 +505,7 @@ msgstr "Aggiorna le informazioni personali" #: extensions/admin/views/identity.py:197 #: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:9 #: extensions/postfix_relay_domains/views.py:63 -#: extensions/sievefilters/views.py:163 extensions/webmail/views.py:170 +#: extensions/sievefilters/views.py:166 extensions/webmail/views.py:170 #: extensions/webmail/views.py:205 msgid "Update" msgstr "Aggiorna" @@ -613,9 +605,8 @@ msgid "Web based console to manage domains, accounts and aliases" msgstr "Interfaccia web per l'amministrazione di domini, account e alias" #: extensions/admin/__init__.py:55 -#, fuzzy msgid "Administration" -msgstr "Amministratori" +msgstr "Amministrazione" #: extensions/admin/__init__.py:79 #: extensions/admin/templates/admin/domains.html:2 @@ -668,15 +659,14 @@ msgid "The UNIX account who owns mailboxes on the filesystem" msgstr "L'account UNIX a cui appartengono le caselle postali nel filsystem" #: extensions/admin/app_settings.py:26 -#, fuzzy msgid "Default domain quota" -msgstr "Limiti predefiniti" +msgstr "Quota predefinita per il domini" #: extensions/admin/app_settings.py:29 msgid "" "Default quota (in MB) applied to freshly created domains with no value " "specified. A value of 0 means no quota." -msgstr "" +msgstr "Quota predefinita (in MB) applicata ai nuovi domini che non la specificano. Un valore 0 implica nessuna quota." #: extensions/admin/app_settings.py:36 msgid "Automatic account removal" @@ -690,19 +680,17 @@ msgstr "" #: extensions/admin/app_settings.py:69 extensions/admin/forms/account.py:178 #: extensions/admin/forms/domain.py:56 msgid "Must be a positive integer" -msgstr "" +msgstr "Dev'essere un intero positivo" #: extensions/admin/lib.py:28 -#, fuzzy msgid "A mailbox is required" -msgstr "È richiesta una quota" +msgstr "É necessaria una casella" #: extensions/admin/forms/account.py:21 -#, fuzzy msgid "" "The user's name. Must be a valid e-mail address for simple users or " "administrators with a mailbox." -msgstr "L'utente '%s' deve avere un indirizzo email valido" +msgstr "Il nome dell'utente. Dev'essere un indirizzo e-mail per gli utenti semplici o gli amministratori che posseggono una casella" #: extensions/admin/forms/account.py:26 msgid "Role" @@ -839,11 +827,10 @@ msgid "No recipient defined" msgstr "Non è stato definito un destinatario" #: extensions/admin/forms/domain.py:20 -#, fuzzy msgid "" "Default quota in MB applied to mailboxes. Leave empty to use the default " "value." -msgstr "Quota in MB predefinita applicata alle caselle di posta" +msgstr "Quota in MB predefinita applicata alle caselle di posta. Lascialo vuoto se vuoi applicare il valore predefinito." #: extensions/admin/forms/domain.py:29 msgid "" @@ -856,23 +843,21 @@ msgstr "" #: extensions/admin/forms/domain.py:75 #: extensions/postfix_relay_domains/forms.py:50 #: extensions/postfix_relay_domains/forms.py:70 -#, fuzzy msgid "domain alias" -msgstr "Alias del dominio" +msgstr "alias del dominio" #: extensions/admin/forms/domain.py:82 extensions/admin/forms/domain.py:98 #: extensions/postfix_relay_domains/forms.py:58 #: extensions/postfix_relay_domains/forms.py:78 -#, fuzzy, python-format +#, python-format msgid "A %s with this name already exists" -msgstr "Un alias con questo nome esiste già" +msgstr "Un %s con questo nome esiste già" #: extensions/admin/forms/domain.py:92 #: extensions/postfix_relay_domains/forms.py:49 #: extensions/postfix_relay_domains/forms.py:71 -#, fuzzy msgid "domain" -msgstr "Domini" +msgstr "dominio" #: extensions/admin/forms/domain.py:176 msgid "Create a domain administrator" @@ -1032,14 +1017,13 @@ msgid "Check to activate this domain" msgstr "Seleziona per attivare questo dominio" #: extensions/admin/models/domain.py:61 -#, fuzzy msgid "Domain" -msgstr "Domini" +msgstr "Dominio" #: extensions/admin/models/domain.py:140 #, python-format msgid "Invalid quota value for domain '%s'" -msgstr "" +msgstr "Valore della quota non valido per il dominio '%s'" #: extensions/admin/models/domain_alias.py:11 #: extensions/postfix_relay_domains/models.py:160 @@ -1056,9 +1040,9 @@ msgid "The domain this alias points to" msgstr "Il dominio a cui punta questo alias" #: extensions/admin/models/domain_alias.py:46 -#, fuzzy, python-format +#, python-format msgid "A domain %s already exists" -msgstr "La casella di posta %s esiste già" +msgstr "Esiste già un dominio %s" #: extensions/admin/models/domain_alias.py:51 #, python-format @@ -1090,9 +1074,8 @@ msgid "MB" msgstr "MB" #: extensions/admin/templates/admin/domain_options_form.html:5 -#, fuzzy msgid "You can't create a new domain administrator" -msgstr "Crea un amministratore di dominio" +msgstr "Non ti è possibile creare un amministratore di dominio" #: extensions/admin/templates/admin/domains_table.html:7 #: extensions/admin/templates/admin/identities_table.html:7 @@ -1102,7 +1085,7 @@ msgstr "Tag" #: extensions/admin/templates/admin/domains_table.html:8 #: extensions/admin/templates/admin/identities_table.html:8 #: extensions/admin/templates/admin/listing.html:17 -#: extensions/sievefilters/views.py:93 +#: extensions/sievefilters/views.py:95 #: extensions/sievefilters/templates/sievefilters/filter.html:17 #: extensions/sievefilters/templates/sievefilters/guieditor.html:5 #: extensions/webmail/templatetags/webmail_tags.py:101 @@ -1257,7 +1240,7 @@ msgstr "Un alias con questo nome esiste già" #: extensions/admin/views/domain.py:129 extensions/admin/views/identity.py:131 #: extensions/admin/views/identity.py:158 #: extensions/postfix_relay_domains/views.py:32 -#: extensions/sievefilters/views.py:141 extensions/sievefilters/views.py:230 +#: extensions/sievefilters/views.py:144 extensions/sievefilters/views.py:233 #: extensions/webmail/views.py:151 msgid "Create" msgstr "Crea" @@ -1374,7 +1357,7 @@ msgstr[0] "Account cancellato" msgstr[1] "Account cancellati" #: extensions/admin/views/import.py:39 -#, fuzzy, python-format +#, python-format msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
      \n" @@ -1389,10 +1372,10 @@ msgstr "" "Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n" "
        \n" "
      • dominio; nome; quota; abilitato
      • \n" -"
      • aliasdominio; nome; dominio target; abilitato
      • \n" +"
      • aliasdominio; nome; dominio di destinazione; abilitato
      • \n" +" %s\n" "
      \n" -"

      Il primo elemento di ogni riga è obbligatorio e deve essere uguale a " -"quello dei valori precedenti.

      \n" +"

      Il primo elemento di ogni riga è obbligatorio e deve essere uguale a quello dei valori precedenti.

      \n" "\n" "

      Come separatore puoi utilizzare un carattere diverso.

      \n" @@ -1411,7 +1394,6 @@ msgid "%d objects imported successfully" msgstr "%d oggetti importati correttamente" #: extensions/admin/views/import.py:153 -#, fuzzy msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
        \n" @@ -1428,15 +1410,12 @@ msgid "" msgstr "" "Fornire un file CSV le cui righe rispettino uno dei seguenti formati:\n" "
          \n" -"
        • account; loginname; password; nome; cognome; abilitato; group; " -"indirizzo[, dominio, ...]
        • \n" +"
        • account; id utente; password; nome; cognome; abilitato; gruppo; indirizzo; quota; [, dominio, ...]
        • \n" "
        • alias; indirizzo; abilitato; destinatario interno
        • \n" "
        • forward; indirizzo; abilitato; destinatario esterno
        • \n" -"
        • dlist; indirizzo; abilitato; destinatario; destinatario; ...\n" +"
        • dlist; indirizzo; abilitato; destinatario; destinatario; ...
        • \n" "
        \n" -"

        Il primo elemento di ogni riga è obbligatorio e deve essere uguale a " -"quello dei valori precedenti.

        \n" +"

        Il primo elemento di ogni riga è obbligatorio e deve essere uguale a quello dei valori precedenti.

        \n" "\n" "

        Come separatore puoi utilizzare un carattere diverso.

        \n" @@ -1558,9 +1537,8 @@ msgid "pending requests" msgstr "richieste in sospeso" #: extensions/amavis/general_callbacks.py:124 -#, fuzzy msgid "Pending requests" -msgstr "richieste in sospeso" +msgstr "Richieste in sospeso" #: extensions/amavis/general_callbacks.py:134 msgid "Content filter" @@ -1576,12 +1554,12 @@ msgid "Virus filter" msgstr "Filtro virus" #: extensions/amavis/models.py:94 extensions/amavis/models.py:102 -#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:290 +#: extensions/amavis/models.py:110 extensions/sievefilters/views.py:293 msgid "yes" msgstr "si" #: extensions/amavis/models.py:95 extensions/amavis/models.py:103 -#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:294 +#: extensions/amavis/models.py:111 extensions/sievefilters/views.py:297 msgid "no" msgstr "no" @@ -1631,7 +1609,7 @@ msgstr "" #: extensions/amavis/sql_listing.py:31 msgid "Score" -msgstr "" +msgstr "Punteggio" #: extensions/amavis/sql_listing.py:35 #: extensions/amavis/templatetags/amavis_tags.py:75 @@ -1708,9 +1686,8 @@ msgid "Quarantine management" msgstr "Gestione quarantena" #: extensions/amavis/templates/amavis/main_action_bar.html:3 -#, fuzzy msgid "Select" -msgstr "Seleziona un file" +msgstr "Seleziona" #: extensions/amavis/templates/amavis/main_action_bar.html:9 msgid "Spam" @@ -1721,7 +1698,6 @@ msgid "Virus" msgstr "Virus" #: extensions/amavis/templates/amavis/main_action_bar.html:11 -#, fuzzy msgid "Bad Header" msgstr "Intestazione errata" @@ -1730,9 +1706,8 @@ msgid "Bad MIME" msgstr "MIME errato" #: extensions/amavis/templates/amavis/main_action_bar.html:13 -#, fuzzy msgid "Banned" -msgstr "Filtro banned" +msgstr "Banditi" #: extensions/amavis/templates/amavis/main_action_bar.html:18 #: extensions/amavis/templatetags/amavis_tags.py:19 @@ -1754,32 +1729,27 @@ msgstr "Tutti i messaggi" #: extensions/amavis/templates/amavis/main_action_bar.html:31 msgid "All" -msgstr "" +msgstr "Tutti" #: extensions/amavis/templates/amavis/main_action_bar.html:32 -#, fuzzy msgid "Spam only" -msgstr "Spam" +msgstr "Solo messaggi di spam" #: extensions/amavis/templates/amavis/main_action_bar.html:33 -#, fuzzy msgid "Virus only" -msgstr "Virus" +msgstr "Solo messaggi con virus" #: extensions/amavis/templates/amavis/main_action_bar.html:34 -#, fuzzy msgid "Bad Header only" -msgstr "Intestazione errata" +msgstr "Solo messaggi con intestazione errata" #: extensions/amavis/templates/amavis/main_action_bar.html:35 -#, fuzzy msgid "Bad MIME only" -msgstr "MIME errato" +msgstr "Solo messaggi con struttura MIME errata" #: extensions/amavis/templates/amavis/main_action_bar.html:36 -#, fuzzy msgid "Banned only" -msgstr "Filtro banned" +msgstr "Solo messaggi banditi" #: extensions/amavis/templates/amavis/notifications/pending_requests.html:1 #, python-format @@ -1954,23 +1924,21 @@ msgstr "" "destinatario" #: extensions/postfix_autoreply/app_settings.py:20 -#, fuzzy msgid "Default subject" -msgstr "Editor predefinito" +msgstr "Oggetto predefinito" #: extensions/postfix_autoreply/app_settings.py:21 msgid "I'm off" -msgstr "" +msgstr "Sono via" #: extensions/postfix_autoreply/app_settings.py:23 msgid "" "Default subject used when an auto-reply message is created automatically" -msgstr "" +msgstr "Oggetto predefinito utilizzato nei messaggi di risposta automatica" #: extensions/postfix_autoreply/app_settings.py:28 -#, fuzzy msgid "Default content" -msgstr "Editor predefinito" +msgstr "Corpo del messaggio predefinito" #: extensions/postfix_autoreply/app_settings.py:30 #, python-format @@ -1980,18 +1948,21 @@ msgid "" "Best regards,\n" "%(name)s\n" msgstr "" +"Al momento non posso rispondere. Risponderò al mio ritorno.\n" +"\n" +"Distinti saluti,\n" +"%(name)s\n" #: extensions/postfix_autoreply/app_settings.py:36 #, python-format msgid "" "Default content used when an auto-reply message is created automatically. " "The '%(name)s' macro will be replaced by the user's full name." -msgstr "" +msgstr "Corpo del messaggio predefinito per i messaggi di risposta automatica. La macro '%(name)s' verrà sostituita con il nome dell'utente. " #: extensions/postfix_autoreply/forms.py:13 -#, fuzzy msgid "Activate your auto reply from this date" -msgstr "Attiva la tua risposta automatica fino a questa data" +msgstr "Attiva la risposta automatica da questa data" #: extensions/postfix_autoreply/forms.py:19 msgid "Until" @@ -2007,9 +1978,8 @@ msgid "This date is over" msgstr "Questa data è passata" #: extensions/postfix_autoreply/forms.py:59 -#, fuzzy msgid "Must be greater than start date" -msgstr "è maggiore di" +msgstr "Dev'essere successiva alla data di inizio" #: extensions/postfix_autoreply/general_callbacks.py:33 #: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2 @@ -2018,11 +1988,11 @@ msgstr "Messaggio di risposta automatica" #: extensions/postfix_autoreply/general_callbacks.py:118 msgid "Enable auto-reply" -msgstr "" +msgstr "Abilita la risposta automatica" #: extensions/postfix_autoreply/general_callbacks.py:120 msgid "Enable or disable Postfix auto-reply" -msgstr "" +msgstr "Abilita o disabilita la risposta automatica di Postfix" #: extensions/postfix_autoreply/models.py:20 msgid "subject" @@ -2054,65 +2024,54 @@ msgstr "Definisci un messaggio da inviare automaticamente quando sei via" #: extensions/postfix_relay_domains/__init__.py:72 msgid "Relay domains support for Postfix" -msgstr "" +msgstr "Supporto ai \"domini relè\" per Postfix" #: extensions/postfix_relay_domains/__init__.py:89 #: extensions/postfix_relay_domains/general_callbacks.py:100 #: extensions/postfix_relay_domains/limits_callbacks.py:16 -#, fuzzy msgid "Relay domains" -msgstr "Nuovo dominio" +msgstr "Domini relè" #: extensions/postfix_relay_domains/app_settings.py:10 msgid "Postfix's master.cf path" -msgstr "" +msgstr "Percorso del file master.cf di Postfix" #: extensions/postfix_relay_domains/app_settings.py:12 -#, fuzzy msgid "Path to the master.cf configuration file" -msgstr "Percorso del file di log" +msgstr "Percorso del file di configurazione master.cf" #: extensions/postfix_relay_domains/forms.py:15 -#, fuzzy msgid "" "Alias(es) of this relay domain. Indicate only one name per input, press " "ENTER to add a new input." -msgstr "" -"Alias per questo dominio. Inserire un solo nome alla volta, premere INVIO " -"per aggiungere un nuovo elemento" +msgstr "Alias per questo dominio relè. Inserisci un solo nome per casella, premi INVIO per aggiungere un nuovo elemento." #: extensions/postfix_relay_domains/forms.py:51 #: extensions/postfix_relay_domains/general_callbacks.py:93 -#, fuzzy msgid "relay domain alias" -msgstr "Alias del dominio" +msgstr "Alias del dominio relè" #: extensions/postfix_relay_domains/forms.py:69 #: extensions/postfix_relay_domains/general_callbacks.py:92 -#, fuzzy msgid "relay domain" -msgstr "Nuovo dominio" +msgstr "Dominio relè" #: extensions/postfix_relay_domains/general_callbacks.py:35 -#, fuzzy msgid "Add relay domain" -msgstr "Aggiungi dominio" +msgstr "Aggiungi dominio relè" #: extensions/postfix_relay_domains/general_callbacks.py:101 -#, fuzzy msgid "Maximum number of relay domains this user can create" -msgstr "Numero massimo di domini che questo utente può creare" +msgstr "Numero massimo di domini relè che questo utente può creare" #: extensions/postfix_relay_domains/general_callbacks.py:103 #: extensions/postfix_relay_domains/limits_callbacks.py:24 -#, fuzzy msgid "Relay domain aliases" -msgstr "Alias del dominio" +msgstr "Alias del dominio relè" #: extensions/postfix_relay_domains/general_callbacks.py:104 -#, fuzzy msgid "Maximum number of relay domain aliases this user can create" -msgstr "Numero massimo di alias di dominio che questo utente può creare" +msgstr "Numero massimo di alias di un dominio relè che questo utente può creare" #: extensions/postfix_relay_domains/general_callbacks.py:111 msgid "" @@ -2121,80 +2080,70 @@ msgid "" "em>\n" "
      • relaydomainalias; name; target; enabled
      • \n" msgstr "" +"\n" +"
      • dominio relè; nome; host di destinazione; servizio; abilitato; verifica caselle
      • \n" +"
      • alias dominio relè; nome; destinazione; abilitato
      • \n" #: extensions/postfix_relay_domains/limits_callbacks.py:19 -#, fuzzy msgid "Maximum number of allowed relay domains for a new administrator" -msgstr "Numero massimo di domini consentiti per un nuovo amministratore" +msgstr "Numero massimo di domini relè consentiti per un nuovo amministratore" #: extensions/postfix_relay_domains/limits_callbacks.py:27 -#, fuzzy msgid "Maximum number of allowed relay domain aliases for a new administrator" -msgstr "" -"Numero massimo di alias di dominio consentiti per un nuovo amministratore" +msgstr "Numero massimo di alias di dominio relè consentiti per un nuovo amministratore" #: extensions/postfix_relay_domains/models.py:59 -#, fuzzy msgid "The service name" -msgstr "Il nome dell'alias" +msgstr "Il nome del servizio" #: extensions/postfix_relay_domains/models.py:80 -#, fuzzy msgid "target host" msgstr "destinazione" #: extensions/postfix_relay_domains/models.py:81 -#, fuzzy msgid "Remote destination of this domain" -msgstr "Seleziona per attivare questo dominio" +msgstr "Destinazione remota per questo dominio" #: extensions/postfix_relay_domains/models.py:89 -#, fuzzy msgid "verify recipients" -msgstr "Destinatari" +msgstr "Verifica destinatari" #: extensions/postfix_relay_domains/models.py:90 msgid "Check for valid recipients" -msgstr "" +msgstr "Verifica validità destinatari" #: extensions/postfix_relay_domains/models.py:103 -#, fuzzy msgid "Relay Domain" -msgstr "Nuovo dominio" +msgstr "Dominio relè" #: extensions/postfix_relay_domains/models.py:164 -#, fuzzy msgid "The relay domain this alias points to" -msgstr "Il dominio a cui punta questo alias" +msgstr "Il dominio relè a cui punta questo alias" #: extensions/postfix_relay_domains/models.py:195 -#, fuzzy, python-format +#, python-format msgid "Relay domain %s does not exist" -msgstr "Il dominio '%s' non esiste" +msgstr "Il dominio relè '%s' non esiste" #: extensions/postfix_relay_domains/views.py:26 -#, fuzzy msgid "Relay domain created" -msgstr "Dominio creato" +msgstr "Dominio relè creato" #: extensions/postfix_relay_domains/views.py:31 -#, fuzzy msgid "New relay domain" -msgstr "Nuovo dominio" +msgstr "Nuovo dominio relè" #: extensions/postfix_relay_domains/views.py:54 -#, fuzzy msgid "Relay domain modified" -msgstr "Dominio modificato" +msgstr "Dominio relè modificato" #: extensions/postfix_relay_domains/views.py:77 -#, fuzzy msgid "Relay domain deleted" -msgstr "Dominio cancellato" +msgstr "Dominio relè cancellato" #: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:2 msgid "Scan" -msgstr "" +msgstr "Cerca" #: extensions/sievefilters/__init__.py:12 msgid "Plugin to easily create server-side filters" @@ -2315,53 +2264,53 @@ msgstr "" msgid "Not enough space on server" msgstr "Non c'è spazio sufficiente nel server" -#: extensions/sievefilters/views.py:78 +#: extensions/sievefilters/views.py:80 msgid "Failed to retrieve filters set" msgstr "Recupero delle impostazioni di filtro fallito" -#: extensions/sievefilters/views.py:138 +#: extensions/sievefilters/views.py:141 #: extensions/sievefilters/templatetags/sfilters_tags.py:33 msgid "New filter" msgstr "Nuovo filtro" -#: extensions/sievefilters/views.py:146 +#: extensions/sievefilters/views.py:149 msgid "Filter created" msgstr "Filtro creato" -#: extensions/sievefilters/views.py:160 +#: extensions/sievefilters/views.py:163 #: extensions/sievefilters/templatetags/sfilters_tags.py:78 msgid "Edit filter" msgstr "Modifica filtro" -#: extensions/sievefilters/views.py:169 +#: extensions/sievefilters/views.py:172 msgid "Filter modified" msgstr "Filtro modificato" -#: extensions/sievefilters/views.py:192 +#: extensions/sievefilters/views.py:195 msgid "Filter removed" msgstr "Filtro eliminato" -#: extensions/sievefilters/views.py:193 +#: extensions/sievefilters/views.py:196 msgid "Failed to remove filter" msgstr "Rimozione del filtro fallita" -#: extensions/sievefilters/views.py:208 +#: extensions/sievefilters/views.py:211 msgid "Filters set saved" msgstr "Gruppo filtri salvato" -#: extensions/sievefilters/views.py:224 +#: extensions/sievefilters/views.py:227 msgid "Filters set created" msgstr "Gruppo filtri creato" -#: extensions/sievefilters/views.py:228 +#: extensions/sievefilters/views.py:231 msgid "Create a new filters set" msgstr "Crea un nuovo gruppo di filtri" -#: extensions/sievefilters/views.py:247 +#: extensions/sievefilters/views.py:250 msgid "Filters set deleted" msgstr "Gruppo filtri eliminato" -#: extensions/sievefilters/views.py:260 +#: extensions/sievefilters/views.py:263 msgid "Filters set activated" msgstr "Gruppo filtri attivato" @@ -2649,13 +2598,12 @@ msgid "Automatic folder refresh rate (in seconds)" msgstr "Frequenza di aggiornamento automatico delle cartelle (in secondi)" #: extensions/webmail/app_settings.py:103 -#, fuzzy msgid "Mailboxes container's width" -msgstr "Proprietario delle caselle postali" +msgstr "Larghezza del contenitore delle caselle" #: extensions/webmail/app_settings.py:104 msgid "The width of the mailbox list container" -msgstr "" +msgstr "Larghezza della lista delle caselle" #: extensions/webmail/app_settings.py:111 msgid "Trash folder" @@ -2703,7 +2651,7 @@ msgstr "Signature delle e-mail personalizzato dall'utente" #: extensions/webmail/app_settings.py:160 msgid "Value must be a positive integer (> 0)" -msgstr "" +msgstr "Il valore dev'essere un intero positivo" #: extensions/webmail/exceptions.py:20 msgid "Server response" @@ -2889,9 +2837,9 @@ msgid "Remove the selected mailbox" msgstr "Elimina la cartella di posta selezionata" #: lib/dbutils.py:36 -#, fuzzy, python-format +#, python-format msgid "Connection to database %s not configured" -msgstr "Connessione ad amavis fallita: %s" +msgstr "La connessione con il database %s non è configurata" #: lib/exceptions.py:67 #, python-format @@ -2997,36 +2945,3 @@ msgstr "Ricordami" #: templates/registration/login.html:36 msgid "Log in" msgstr "Registrati" - -#~ msgid "An alias with this name already exists" -#~ msgstr "Esiste già un alias con questo nome" - -#~ msgid "A domain with this name already exists" -#~ msgstr "Esiste già un dominio con questo nome" - -#~ msgid "Edit domain" -#~ msgstr "Modifica dominio" - -#~ msgid "%d pending requests" -#~ msgstr "%d richieste in sospeso" - -#~ msgid "Content Class" -#~ msgstr "Classe dei contenuti" - -#~ msgid "Nothing" -#~ msgstr "Nulla" - -#~ msgid "Bad request" -#~ msgstr "Richiesta sbagliata" - -#~ msgid "Undefined action" -#~ msgstr "Azione non definita" - -#~ msgid "User preferences" -#~ msgstr "Preferenze utente" - -#~ msgid "Per-user settings" -#~ msgstr "Impostazioni per-utente" - -#~ msgid "You need a mailbox in order to define a forward" -#~ msgstr "Hai bisogno di una casella di posta per definire un inoltro" diff --git a/modoboa/locale/it/LC_MESSAGES/djangojs.po b/modoboa/locale/it/LC_MESSAGES/djangojs.po index e60178242..3d7c25ebd 100644 --- a/modoboa/locale/it/LC_MESSAGES/djangojs.po +++ b/modoboa/locale/it/LC_MESSAGES/djangojs.po @@ -7,9 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: Modoboa\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-15 10:16+0100\n" -"PO-Revision-Date: 2013-09-27 00:07+0200\n" -"Last-Translator: Giancarlo Gaifas \n" +"POT-Creation-Date: 2013-12-22 23:16+0100\n" +"PO-Revision-Date: 2013-12-23 00:58+0100\n" +"Last-Translator: Alberto Berti \n" "Language-Team: Italiano \n" "Language: it\n" "MIME-Version: 1.0\n" @@ -73,7 +73,7 @@ msgstr "Nascondi le intestazioni" #: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49 msgid "Services updated" -msgstr "" +msgstr "Servizi aggiornati" #: extensions/sievefilters/static/sievefilters/js/lib.js:14 msgid "Remove this filter?" @@ -135,13 +135,9 @@ msgid "Cancel" msgstr "Elimina" #: static/js/global.js:314 -#, fuzzy msgid "Internal error" msgstr "Errore interno" #: static/js/searchbar.js:20 msgid "Search..." msgstr "Ricerca ..." - -#~ msgid "Message deleted" -#~ msgstr "Messaggio eliminato" diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/django.po b/modoboa/locale/pt_PT/LC_MESSAGES/django.po index 278483fb7..3a55652fe 100644 --- a/modoboa/locale/pt_PT/LC_MESSAGES/django.po +++ b/modoboa/locale/pt_PT/LC_MESSAGES/django.po @@ -1,9 +1,10 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: # ddu17 , 2013 +# lusitan , 2013 # mikec , 2012 # mikec , 2013 # Sandra Ribeiro , 2012-2013 @@ -13,14 +14,13 @@ msgstr "" "Project-Id-Version: Modoboa\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-12-15 10:21+0100\n" -"PO-Revision-Date: 2013-10-04 21:10+0000\n" -"Last-Translator: ddu17 \n" -"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/" -"modoboa/language/pt_PT/)\n" -"Language: pt_PT\n" +"PO-Revision-Date: 2013-12-23 11:25+0000\n" +"Last-Translator: lusitan \n" +"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/modoboa/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: core/__init__.py:52 core/__init__.py:53 @@ -55,23 +55,23 @@ msgstr "Esquema pré-definido para passwords" #: core/app_settings.py:51 msgid "md5crypt (weak)" -msgstr "" +msgstr "md5crypt (fraco)" #: core/app_settings.py:52 msgid "sha256 (weak)" -msgstr "" +msgstr "sha256 (fraco)" #: core/app_settings.py:53 msgid "md5 (weak)" -msgstr "" +msgstr "md5 (fraco)" #: core/app_settings.py:54 msgid "crypt (weak)" -msgstr "" +msgstr "crypt (fraco)" #: core/app_settings.py:55 msgid "plain (weak)" -msgstr "" +msgstr "plain (fraco)" #: core/app_settings.py:57 msgid "Scheme used to crypt mailbox passwords" @@ -149,9 +149,7 @@ msgstr "\"Bind DN\"" msgid "" "The distinguished name to use when binding to the LDAP server. Leave empty " "for an anonymous bind" -msgstr "" -"O nome único usado para fazer o \"bind\" ao servidor LDAP. Deixar vario " -"para \"bind\" anónimo" +msgstr "O nome único usado para fazer o \"bind\" ao servidor LDAP. Deixar vario para \"bind\" anónimo" #: core/app_settings.py:113 msgid "Bind password" @@ -159,18 +157,15 @@ msgstr "Password para bind" #: core/app_settings.py:115 msgid "The password to use when binding to the LDAP server (with 'Bind DN')" -msgstr "" -"A password usada para fazer o \"bind\" ao servidor LDAP (com 'Bind DN')" +msgstr "A password usada para fazer o \"bind\" ao servidor LDAP (com 'Bind DN')" #: core/app_settings.py:121 -#, fuzzy msgid "Users search base" -msgstr "Base de pesquisa" +msgstr "" #: core/app_settings.py:123 -#, fuzzy msgid "The distinguished name of the search base used to find users" -msgstr "O nome único para a pesquisa base" +msgstr "" #: core/app_settings.py:128 msgid "Search filter" @@ -180,9 +175,7 @@ msgstr "Filtro de pesquisa" msgid "" "An optional filter string (e.g. '(objectClass=person)'). In order to be " "valid, it must be enclosed in parentheses." -msgstr "" -"Um filtro opcional (ex: '(objetClass=person)'). Tem de estar entre " -"parênteses para ser válido" +msgstr "Um filtro opcional (ex: '(objetClass=person)'). Tem de estar entre parênteses para ser válido" #: core/app_settings.py:135 msgid "User DN template" @@ -193,9 +186,7 @@ msgstr "Template DN de utilizador" msgid "" "The template used to construct a user's DN. It should contain one " "placeholder (ie. %(user)s)" -msgstr "" -"O template usado para construir o DN (nome único). Deve apenas conter um " -"'placeholder' (ex: %(user)s) " +msgstr "O template usado para construir o DN (nome único). Deve apenas conter um 'placeholder' (ex: %(user)s) " #: core/app_settings.py:142 msgid "Password attribute" @@ -214,25 +205,22 @@ msgid "Tell if the LDAP server is an Active Directory one" msgstr "Especificar se o servidor LDAP e um Active Directory" #: core/app_settings.py:154 -#, fuzzy msgid "Administrator groups" -msgstr "Administradores" +msgstr "" #: core/app_settings.py:157 msgid "" -"Members of those LDAP Posix groups will be created as domain administrators. " -"Use ';' characters to separate groups." +"Members of those LDAP Posix groups will be created as domain administrators." +" Use ';' characters to separate groups." msgstr "" #: core/app_settings.py:164 -#, fuzzy msgid "Groups search base" -msgstr "Base de pesquisa" +msgstr "" #: core/app_settings.py:167 -#, fuzzy msgid "The distinguished name of the search base used to find groups" -msgstr "O nome único para a pesquisa base" +msgstr "" #: core/app_settings.py:172 #: extensions/admin/templates/admin/editdomainform.html:7 @@ -261,9 +249,7 @@ msgstr "Redirecionamento pré-definido" #: core/app_settings.py:190 msgid "The default redirection used when no application is specified" -msgstr "" -"O redirecionamento padrão usado quando nenhuma aplicação se encontra " -"especificada" +msgstr "O redirecionamento padrão usado quando nenhuma aplicação se encontra especificada" #: core/app_settings.py:218 msgid "Key must be either 16, 24, or 32 bytes long" @@ -274,9 +260,8 @@ msgid "Invalid syntax" msgstr "Sintax inválida" #: core/app_settings.py:233 -#, fuzzy msgid "Invalid rounds number" -msgstr "Pedido inválido" +msgstr "" #: core/app_settings.py:256 msgid "This field is required" @@ -326,14 +311,12 @@ msgid "Passwords mismatch" msgstr "Passwords não coincidem" #: core/models.py:50 -#, fuzzy msgid "password" -msgstr "Password" +msgstr "" #: core/models.py:52 -#, fuzzy msgid "last login" -msgstr "Último login" +msgstr "" #: core/models.py:81 msgid "You can't delete your own account" @@ -366,9 +349,7 @@ msgstr "O simple utilizador '%s' deve ter endereço de e-mail válido" #: core/models.py:335 #, python-format msgid "username and email fields must not differ for '%s'" -msgstr "" -"Os campos nome de utilizador e endereço de email não deve ser diferente para " -"'%s'" +msgstr "Os campos nome de utilizador e endereço de email não deve ser diferente para '%s'" #: core/models.py:404 extensions/admin/models/alias.py:33 #: extensions/admin/models/domain.py:32 @@ -583,31 +564,15 @@ msgid "" "\n" "

        Welcome to the online demo!

        \n" "

        Warning: the demo's concent is resetted every two hours.

        \n" -"

        To try the demo, the following users are available (username/password):

        \n" +"

        To try the demo, the following users are available (username/password):

        \n" "
          \n" "
        • A super administrator : admin/password
        • \n" "
        • A domain administrator : admin@demo.local/admin
        • \n" "
        • A simple user : user@demo.local/user
        • \n" "
        \n" "

        Please report any issue or give any suggestion to \n" -" the " -"mailing list.

        \n" -msgstr "" -"\n" -"

        Bem-vindo à demo online!

        \n" -"

        Aviso: os conteúdos desta demo são limpos a cada duas horas.

        \n" -"

        Para experimentar a demo, estão disponíveis os seguintes utilizadores " -"(username/password):

        \n" -"
          \n" -"
        • Super administrador: admin/password
        • \n" -"
        • Administrador de domínio: admin@demo.local/admin
        • \n" -"
        • Utilizador básico: user@demo.local/user
        • \n" -"
        \n" -"

        Para reportar qualquer problema ou apresentar uma sugestão, utilize o " -"seguinte link \n" -" mailing " -"list.

        \n" +" the mailing list.

        \n" +msgstr "\n

        Bem-vindo à demo online!

        \n

        Aviso: os conteúdos desta demo são limpos a cada duas horas.

        \n

        Para experimentar a demo, estão disponíveis os seguintes utilizadores (username/password):

        \n
          \n
        • Super administrador: admin/password
        • \n
        • Administrador de domínio: admin@demo.local/admin
        • \n
        • Utilizador básico: user@demo.local/user
        • \n
        \n

        Para reportar qualquer problema ou apresentar uma sugestão, utilize o seguinte link \n mailing list.

        \n" #: extensions/admin/__init__.py:48 msgid "Administration console" @@ -618,9 +583,8 @@ msgid "Web based console to manage domains, accounts and aliases" msgstr "Consola baseada na web para gestão de domínios, contas e aliases" #: extensions/admin/__init__.py:55 -#, fuzzy msgid "Administration" -msgstr "Administradores" +msgstr "" #: extensions/admin/__init__.py:79 #: extensions/admin/templates/admin/domains.html:2 @@ -660,9 +624,7 @@ msgstr "Lidar com caixas de correio no sistema de ficheiros" msgid "" "Rename or remove mailboxes on the filesystem when they get renamed or " "removed within Modoboa" -msgstr "" -"Renomear ou remover as caixas de correio no sistema de ficheiros quando " -"estas são renomeadas no Modoboa" +msgstr "Renomear ou remover as caixas de correio no sistema de ficheiros quando estas são renomeadas no Modoboa" #: extensions/admin/app_settings.py:20 msgid "Mailboxes ower" @@ -673,9 +635,8 @@ msgid "The UNIX account who owns mailboxes on the filesystem" msgstr "A conta UNIX que detém as caixas de correio no sistema de ficheiros" #: extensions/admin/app_settings.py:26 -#, fuzzy msgid "Default domain quota" -msgstr "Limites predefinidos" +msgstr "" #: extensions/admin/app_settings.py:29 msgid "" @@ -689,8 +650,7 @@ msgstr "Remoção automática de conta" #: extensions/admin/app_settings.py:38 msgid "When a mailbox is removed, also remove the associated account" -msgstr "" -"Ao remover uma caixa de correio estará também a remover a conta associada" +msgstr "Ao remover uma caixa de correio estará também a remover a conta associada" #: extensions/admin/app_settings.py:69 extensions/admin/forms/account.py:178 #: extensions/admin/forms/domain.py:56 @@ -698,16 +658,14 @@ msgid "Must be a positive integer" msgstr "" #: extensions/admin/lib.py:28 -#, fuzzy msgid "A mailbox is required" -msgstr "É necessário uma quota" +msgstr "" #: extensions/admin/forms/account.py:21 -#, fuzzy msgid "" "The user's name. Must be a valid e-mail address for simple users or " "administrators with a mailbox." -msgstr "O simple utilizador '%s' deve ter endereço de e-mail válido" +msgstr "" #: extensions/admin/forms/account.py:26 msgid "Role" @@ -750,10 +708,7 @@ msgid "" "Quota in MB for this mailbox. Define a custom value or use domain's default " "one. Leave empty to define an unlimited value (not allowed for domain " "administrators)." -msgstr "" -"Quota em MB para esta caixa de correio. Definir uma valor personalizado ou " -"usar o valor predefinido pelo domínio. Deixar em branco para definir uma " -"valor ilimitado (não permitido para administradores do domínio)." +msgstr "Quota em MB para esta caixa de correio. Definir uma valor personalizado ou usar o valor predefinido pelo domínio. Deixar em branco para definir uma valor ilimitado (não permitido para administradores do domínio)." #: extensions/admin/forms/account.py:123 extensions/admin/forms/domain.py:26 #: extensions/admin/templates/admin/domains_table.html:6 @@ -766,10 +721,7 @@ msgid "" "Alias(es) of this mailbox. Indicate only one address per input, press ENTER " "to add a new input. Use the '*' character to create a 'catchall' alias (ex: " "*@domain.tld)." -msgstr "" -"Alias(es) desta caixa de correio. Indique apenas um endereço por entrada, " -"clique ENTER para adicionar uma nova entrada. Use o '*' para criar um alias " -"'catchall' (ex: *@domain.tld)." +msgstr "Alias(es) desta caixa de correio. Indique apenas um endereço por entrada, clique ENTER para adicionar uma nova entrada. Use o '*' para criar um alias 'catchall' (ex: *@domain.tld)." #: extensions/admin/forms/account.py:187 extensions/admin/forms/account.py:217 #: extensions/admin/forms/alias.py:65 @@ -806,9 +758,7 @@ msgstr "Endereço de e-mail" msgid "" "The distribution list address. Use the '*' character to create a 'catchall' " "address (ex: *@domain.tld)." -msgstr "" -"Os endereços da lista de distribuição. Use o '*' para criar um endereço " -"'catchall' (Ex: *@domain.tld)." +msgstr "Os endereços da lista de distribuição. Use o '*' para criar um endereço 'catchall' (Ex: *@domain.tld)." #: extensions/admin/forms/alias.py:23 msgid "Recipients" @@ -818,9 +768,7 @@ msgstr "Destinatários" msgid "" "Mailbox(es) this alias will point to. Indicate only one address per input, " "press ENTER to add a new input." -msgstr "" -"Caixa(s) de correio para o qual este 'alias' aponta. Indicar apenas um " -"endereço por entrada, pressionar ENTER para acrescentar uma nova entrada." +msgstr "Caixa(s) de correio para o qual este 'alias' aponta. Indicar apenas um endereço por entrada, pressionar ENTER para acrescentar uma nova entrada." #: extensions/admin/forms/alias.py:68 msgid "You don't have access to this domain" @@ -845,40 +793,35 @@ msgid "No recipient defined" msgstr "Sem destinatário definido" #: extensions/admin/forms/domain.py:20 -#, fuzzy msgid "" "Default quota in MB applied to mailboxes. Leave empty to use the default " "value." -msgstr "Quota em MB aplicada por defeito às caixas de correio" +msgstr "" #: extensions/admin/forms/domain.py:29 msgid "" "Alias(es) of this domain. Indicate only one name per input, press ENTER to " "add a new input." -msgstr "" -"Alias(es) deste domínio. Indicar apenas um nome por entrada, pressionar " -"ENTER para acrescentar uma nova entrada." +msgstr "Alias(es) deste domínio. Indicar apenas um nome por entrada, pressionar ENTER para acrescentar uma nova entrada." #: extensions/admin/forms/domain.py:75 #: extensions/postfix_relay_domains/forms.py:50 #: extensions/postfix_relay_domains/forms.py:70 -#, fuzzy msgid "domain alias" -msgstr "Aliases de domínio" +msgstr "" #: extensions/admin/forms/domain.py:82 extensions/admin/forms/domain.py:98 #: extensions/postfix_relay_domains/forms.py:58 #: extensions/postfix_relay_domains/forms.py:78 -#, fuzzy, python-format +#, python-format msgid "A %s with this name already exists" -msgstr "Já existe um 'alias' com este nome" +msgstr "" #: extensions/admin/forms/domain.py:92 #: extensions/postfix_relay_domains/forms.py:49 #: extensions/postfix_relay_domains/forms.py:71 -#, fuzzy msgid "domain" -msgstr "Domínios" +msgstr "" #: extensions/admin/forms/domain.py:176 msgid "Create a domain administrator" @@ -892,9 +835,7 @@ msgstr "Criar automaticamente um administrador para este domínio" msgid "" "The administrator's name. Don't include the domain's name here, it will be " "automatically appended." -msgstr "" -"O nome do administrador. Não inclua o nome do domínio já que este será " -"automaticamente anexado." +msgstr "O nome do administrador. Não inclua o nome do domínio já que este será automaticamente anexado." #: extensions/admin/forms/domain.py:193 msgid "Create aliases" @@ -935,16 +876,13 @@ msgstr "Conservar cópias locais" #: extensions/admin/forms/forward.py:20 msgid "Forward messages and store copies into your local mailbox" -msgstr "" -"Reencaminhar mensagens e armazenar cópias na sua caixa de correio local" +msgstr "Reencaminhar mensagens e armazenar cópias na sua caixa de correio local" #: extensions/admin/forms/forward.py:38 msgid "" "You can't define a forward to a local destination. Please ask your " "administrator to create an alias instead." -msgstr "" -"Não é possível definir um reencaminhamento para um destino local. Por favor " -"informe-se junto de um administrador para criar um alias." +msgstr "Não é possível definir um reencaminhamento para um destino local. Por favor informe-se junto de um administrador para criar um alias." #: extensions/admin/forms/import_.py:6 extensions/webmail/forms.py:26 msgid "Select a file" @@ -972,11 +910,9 @@ msgstr "endereços" #: extensions/admin/models/alias.py:18 msgid "" -"The alias address (without the domain part). For a 'catch-all' address, just " -"enter an * character." -msgstr "" -"O endereço do alias (sem a parte do domínio). Para um endereço 'cath-all', " -"digite apenas o caractere *" +"The alias address (without the domain part). For a 'catch-all' address, just" +" enter an * character." +msgstr "O endereço do alias (sem a parte do domínio). Para um endereço 'cath-all', digite apenas o caractere *" #: extensions/admin/models/alias.py:24 msgid "mailboxes" @@ -1037,9 +973,8 @@ msgid "Check to activate this domain" msgstr "Marcar para ativar este domínio" #: extensions/admin/models/domain.py:61 -#, fuzzy msgid "Domain" -msgstr "Domínios" +msgstr "" #: extensions/admin/models/domain.py:140 #, python-format @@ -1061,9 +996,9 @@ msgid "The domain this alias points to" msgstr "O domínio para o qual este alias irá apontar" #: extensions/admin/models/domain_alias.py:46 -#, fuzzy, python-format +#, python-format msgid "A domain %s already exists" -msgstr "Caixa de correio %s já existe" +msgstr "" #: extensions/admin/models/domain_alias.py:51 #, python-format @@ -1095,9 +1030,8 @@ msgid "MB" msgstr "MB" #: extensions/admin/templates/admin/domain_options_form.html:5 -#, fuzzy msgid "You can't create a new domain administrator" -msgstr "Criar um administrador de domínio" +msgstr "" #: extensions/admin/templates/admin/domains_table.html:7 #: extensions/admin/templates/admin/identities_table.html:7 @@ -1379,7 +1313,7 @@ msgstr[0] "Conta eliminada" msgstr[1] "Contas eliminadas" #: extensions/admin/views/import.py:39 -#, fuzzy, python-format +#, python-format msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
          \n" @@ -1387,15 +1321,9 @@ msgid "" "
        • domainalias; name; targeted domain; enabled
        • \n" " %s\n" "
        \n" -"

        The first element of each line is mandatory and must be equal to one of " -"the previous values.

        \n" +"

        The first element of each line is mandatory and must be equal to one of the previous values.

        \n" "

        You can use a different character as separator.

        \n" msgstr "" -"Forneça um ficheiro CSV cujas linhas respeitem um dos seguintes formatos:⏎ " -"
          ⏎
        • domain; name; quota; enabled
        • ⏎
        • domainalias; " -"name; targeted domain; enabled
        • ⏎
        ⏎

        O primeiro elemento de " -"cada linha é obrigatório e deve ser igual a um dos valores anteriores.

        ⏎ " -"

        Pode utilizar um caractere diferente como separador.

        ⏎\n" #: extensions/admin/views/import.py:50 msgid "Import domains" @@ -1412,33 +1340,18 @@ msgid "%d objects imported successfully" msgstr "%d objetos importados com sucesso" #: extensions/admin/views/import.py:153 -#, fuzzy msgid "" "Provide a CSV file where lines respect one of the following formats:\n" "
          \n" -"
        • account; loginname; password; first name; last name; enabled; group; " -"address; quota; [, domain, ...]
        • \n" +"
        • account; loginname; password; first name; last name; enabled; group; address; quota; [, domain, ...]
        • \n" "
        • alias; address; enabled; internal recipient
        • \n" "
        • forward; address; enabled; external recipient
        • \n" "
        • dlist; address; enabled; recipient; recipient; ...
        • \n" "
        \n" -"

        The first element of each line is mandatory and must be equal to one of " -"the previous values.

        \n" +"

        The first element of each line is mandatory and must be equal to one of the previous values.

        \n" "\n" "

        You can use a different character as separator.

        \n" msgstr "" -"Forneça um ficheiro CSV cujas linhas respeitem um dos seguintes formatos:⏎\n" -"
          ⏎\n" -"
        • account; loginname; password; first name; last name; enabled; group; " -"address[, domain, ...]
        • ⏎\n" -"
        • alias; address; enabled; internal recipient
        • ⏎\n" -"
        • forward; address; enabled; external recipient
        • ⏎\n" -"
        • dlist; address; enabled; recipient; recipient; ...
        • ⏎\n" -"
        ⏎\n" -"

        O primeiro elemento de cada linha é obrigatório e deve ser igual a um dos " -"valores anteriores..

        ⏎\n" -"⏎\n" -"

        Pode utilizar um caractere diferente como separador.

        ⏎\n" #: extensions/admin/views/import.py:165 msgid "Import identities" @@ -1466,9 +1379,7 @@ msgstr "Idade maxima da messagem" #: extensions/amavis/app_settings.py:16 msgid "Quarantine messages maximum age (in days) before deletion" -msgstr "" -"Tempo máximo que as mensagens ficam na quarentena (em dias) até serem " -"eliminadas" +msgstr "Tempo máximo que as mensagens ficam na quarentena (em dias) até serem eliminadas" #: extensions/amavis/app_settings.py:19 msgid "Messages releasing" @@ -1480,9 +1391,7 @@ msgstr "Remover mensagens libertadas" #: extensions/amavis/app_settings.py:24 msgid "Remove messages marked as released while cleaning up the database" -msgstr "" -"Remova as mensagens, marcadas como enviadas, durante a limpeza da base de " -"dados" +msgstr "Remova as mensagens, marcadas como enviadas, durante a limpeza da base de dados" #: extensions/amavis/app_settings.py:28 msgid "Amavis connection mode" @@ -1561,9 +1470,8 @@ msgid "pending requests" msgstr "pedidos pendentes" #: extensions/amavis/general_callbacks.py:124 -#, fuzzy msgid "Pending requests" -msgstr "pedidos pendentes" +msgstr "" #: extensions/amavis/general_callbacks.py:134 msgid "Content filter" @@ -1596,9 +1504,7 @@ msgstr "predifinido" #: extensions/amavis/models.py:98 msgid "Bypass virus checks or not. Choose 'default' to use global settings." -msgstr "" -"Ignorar a verificação de vírus ou não. Escolher 'predefinido' para utilizar " -"as definições gerais." +msgstr "Ignorar a verificação de vírus ou não. Escolher 'predefinido' para utilizar as definições gerais." #: extensions/amavis/models.py:101 msgid "Spam filter" @@ -1606,9 +1512,7 @@ msgstr "Filtro de spam" #: extensions/amavis/models.py:106 msgid "Bypass spam checks or not. Choose 'default' to use global settings." -msgstr "" -"Ignorar filtros de spam ou não. Escolher 'predefinido' para utilizar as " -"definições gerais." +msgstr "Ignorar filtros de spam ou não. Escolher 'predefinido' para utilizar as definições gerais." #: extensions/amavis/models.py:109 msgid "Banned filter" @@ -1616,9 +1520,7 @@ msgstr "Ficheiros proibidos" #: extensions/amavis/models.py:114 msgid "Bypass banned checks or not. Choose 'default' to use global settings." -msgstr "" -"Ignorar a verificação de ficheiros proibidos. Escolher 'predefinido' para " -"utilizar as definições gerais." +msgstr "Ignorar a verificação de ficheiros proibidos. Escolher 'predefinido' para utilizar as definições gerais." #: extensions/amavis/models.py:144 msgid "Spam marker" @@ -1626,11 +1528,9 @@ msgstr "Marcador spam" #: extensions/amavis/models.py:146 msgid "" -"Modify spam subject using the specified text. Choose 'default' to use global " -"settings." -msgstr "" -"Modifique o assunto de spam usando o texto especificado. Escolha 'default' " -"para usar as configurações globais." +"Modify spam subject using the specified text. Choose 'default' to use global" +" settings." +msgstr "Modifique o assunto de spam usando o texto especificado. Escolha 'default' para usar as configurações globais." #: extensions/amavis/sql_listing.py:31 msgid "Score" @@ -1711,9 +1611,8 @@ msgid "Quarantine management" msgstr "Gestão de Quarentena" #: extensions/amavis/templates/amavis/main_action_bar.html:3 -#, fuzzy msgid "Select" -msgstr "Escolha um ficheiro" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:9 msgid "Spam" @@ -1724,18 +1623,16 @@ msgid "Virus" msgstr "Vírus" #: extensions/amavis/templates/amavis/main_action_bar.html:11 -#, fuzzy msgid "Bad Header" -msgstr "Cabeçalho inválido" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:12 msgid "Bad MIME" msgstr "Formato MIME inválido" #: extensions/amavis/templates/amavis/main_action_bar.html:13 -#, fuzzy msgid "Banned" -msgstr "Ficheiros proibidos" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:18 #: extensions/amavis/templatetags/amavis_tags.py:19 @@ -1760,29 +1657,24 @@ msgid "All" msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:32 -#, fuzzy msgid "Spam only" -msgstr "Spam" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:33 -#, fuzzy msgid "Virus only" -msgstr "Vírus" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:34 -#, fuzzy msgid "Bad Header only" -msgstr "Cabeçalho inválido" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:35 -#, fuzzy msgid "Bad MIME only" -msgstr "Formato MIME inválido" +msgstr "" #: extensions/amavis/templates/amavis/main_action_bar.html:36 -#, fuzzy msgid "Banned only" -msgstr "Ficheiros proibidos" +msgstr "" #: extensions/amavis/templates/amavis/notifications/pending_requests.html:1 #, python-format @@ -1792,12 +1684,8 @@ msgid "" msgid_plural "" "\n" "%(counter)s release requests are pending for action.\n" -msgstr[0] "" -"\n" -"%(counter)s pedido de libertação pendente\n" -msgstr[1] "" -"\n" -"%(counter)s pedidos de libertação pendentes\n" +msgstr[0] "\n%(counter)s pedido de libertação pendente\n" +msgstr[1] "\n%(counter)s pedidos de libertação pendentes\n" #: extensions/amavis/templates/amavis/notifications/pending_requests.html:6 msgid "Sketch:" @@ -1850,10 +1738,9 @@ msgid "Domain admins" msgstr "Administradores de domínio" #: extensions/limits/app_settings.py:15 -msgid "Maximum number of allowed domain administrators for a new administrator" -msgstr "" -"Número máximo permitido de administradores de domínio para um novo " -"administrador" +msgid "" +"Maximum number of allowed domain administrators for a new administrator" +msgstr "Número máximo permitido de administradores de domínio para um novo administrador" #: extensions/limits/app_settings.py:21 msgid "Maximum number of allowed domains for a new administrator" @@ -1861,8 +1748,7 @@ msgstr "Número máximo permitido de domínios para novo administrador" #: extensions/limits/app_settings.py:27 msgid "Maximum number of allowed domain aliases for a new administrator" -msgstr "" -"Número máximo permitido de aliases de domínio para um novo administrador" +msgstr "Número máximo permitido de aliases de domínio para um novo administrador" #: extensions/limits/app_settings.py:33 msgid "Maximum number of allowed mailboxes for a new administrator" @@ -1903,8 +1789,7 @@ msgstr "Recursos insuficientes" #: extensions/limits/models.py:15 msgid "Maximum number of domain administrators this user can create" -msgstr "" -"Número máximo de administradores de domínio que este utilizador pode criar" +msgstr "Número máximo de administradores de domínio que este utilizador pode criar" #: extensions/limits/models.py:18 msgid "Maximum number of domains this user can create" @@ -1920,8 +1805,7 @@ msgstr "Número máximo de caixas de correio que este utilizador por criar" #: extensions/limits/models.py:26 msgid "Maximum number of mailbox aliases this user can create" -msgstr "" -"Número máximo de aliases para caixas de correio que este utilizador por criar" +msgstr "Número máximo de aliases para caixas de correio que este utilizador por criar" #: extensions/limits/models.py:136 msgid "undefined" @@ -1949,14 +1833,11 @@ msgstr "Tempo limite de resposta automática" #: extensions/postfix_autoreply/app_settings.py:16 msgid "Timeout in seconds between two auto-replies to the same recipient" -msgstr "" -"Tempo limite em segundos entre duas respostas automáticas para o mesmo " -"destinatário" +msgstr "Tempo limite em segundos entre duas respostas automáticas para o mesmo destinatário" #: extensions/postfix_autoreply/app_settings.py:20 -#, fuzzy msgid "Default subject" -msgstr "Editor predefinido" +msgstr "" #: extensions/postfix_autoreply/app_settings.py:21 msgid "I'm off" @@ -1968,9 +1849,8 @@ msgid "" msgstr "" #: extensions/postfix_autoreply/app_settings.py:28 -#, fuzzy msgid "Default content" -msgstr "Editor predefinido" +msgstr "" #: extensions/postfix_autoreply/app_settings.py:30 #, python-format @@ -1989,9 +1869,8 @@ msgid "" msgstr "" #: extensions/postfix_autoreply/forms.py:13 -#, fuzzy msgid "Activate your auto reply from this date" -msgstr "Ativar o seu aviso de ausência até esta data" +msgstr "" #: extensions/postfix_autoreply/forms.py:19 msgid "Until" @@ -2007,9 +1886,8 @@ msgid "This date is over" msgstr "Esta data ultrapassa" #: extensions/postfix_autoreply/forms.py:59 -#, fuzzy msgid "Must be greater than start date" -msgstr "é maior do que" +msgstr "" #: extensions/postfix_autoreply/general_callbacks.py:33 #: extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html:2 @@ -2059,138 +1937,113 @@ msgstr "" #: extensions/postfix_relay_domains/__init__.py:89 #: extensions/postfix_relay_domains/general_callbacks.py:100 #: extensions/postfix_relay_domains/limits_callbacks.py:16 -#, fuzzy msgid "Relay domains" -msgstr "Novo domínio" +msgstr "" #: extensions/postfix_relay_domains/app_settings.py:10 msgid "Postfix's master.cf path" msgstr "" #: extensions/postfix_relay_domains/app_settings.py:12 -#, fuzzy msgid "Path to the master.cf configuration file" -msgstr "Caminho para o ficheiro log" +msgstr "" #: extensions/postfix_relay_domains/forms.py:15 -#, fuzzy msgid "" "Alias(es) of this relay domain. Indicate only one name per input, press " "ENTER to add a new input." msgstr "" -"Alias(es) deste domínio. Indicar apenas um nome por entrada, pressionar " -"ENTER para acrescentar uma nova entrada." #: extensions/postfix_relay_domains/forms.py:51 #: extensions/postfix_relay_domains/general_callbacks.py:93 -#, fuzzy msgid "relay domain alias" -msgstr "Aliases de domínio" +msgstr "" #: extensions/postfix_relay_domains/forms.py:69 #: extensions/postfix_relay_domains/general_callbacks.py:92 -#, fuzzy msgid "relay domain" -msgstr "Novo domínio" +msgstr "" #: extensions/postfix_relay_domains/general_callbacks.py:35 -#, fuzzy msgid "Add relay domain" -msgstr "Adicionar domínio" +msgstr "" #: extensions/postfix_relay_domains/general_callbacks.py:101 -#, fuzzy msgid "Maximum number of relay domains this user can create" -msgstr "Número máximo de domínios que este utilizador pode criar" +msgstr "" #: extensions/postfix_relay_domains/general_callbacks.py:103 #: extensions/postfix_relay_domains/limits_callbacks.py:24 -#, fuzzy msgid "Relay domain aliases" -msgstr "Aliases de domínio" +msgstr "" #: extensions/postfix_relay_domains/general_callbacks.py:104 -#, fuzzy msgid "Maximum number of relay domain aliases this user can create" -msgstr "Número máximo de aliases de domínio que este utilizador pode criar" +msgstr "" #: extensions/postfix_relay_domains/general_callbacks.py:111 msgid "" "\n" -"
      • relaydomain; name; target host; service; enabled; verify recipients
      • \n" +"
      • relaydomain; name; target host; service; enabled; verify recipients
      • \n" "
      • relaydomainalias; name; target; enabled
      • \n" msgstr "" #: extensions/postfix_relay_domains/limits_callbacks.py:19 -#, fuzzy msgid "Maximum number of allowed relay domains for a new administrator" -msgstr "Número máximo permitido de domínios para novo administrador" +msgstr "" #: extensions/postfix_relay_domains/limits_callbacks.py:27 -#, fuzzy msgid "Maximum number of allowed relay domain aliases for a new administrator" msgstr "" -"Número máximo permitido de aliases de domínio para um novo administrador" #: extensions/postfix_relay_domains/models.py:59 -#, fuzzy msgid "The service name" -msgstr "O nome do 'alias'" +msgstr "" #: extensions/postfix_relay_domains/models.py:80 -#, fuzzy msgid "target host" -msgstr "alvo" +msgstr "" #: extensions/postfix_relay_domains/models.py:81 -#, fuzzy msgid "Remote destination of this domain" -msgstr "Marcar para ativar este domínio" +msgstr "" #: extensions/postfix_relay_domains/models.py:89 -#, fuzzy msgid "verify recipients" -msgstr "Destinatários" +msgstr "" #: extensions/postfix_relay_domains/models.py:90 msgid "Check for valid recipients" msgstr "" #: extensions/postfix_relay_domains/models.py:103 -#, fuzzy msgid "Relay Domain" -msgstr "Novo domínio" +msgstr "" #: extensions/postfix_relay_domains/models.py:164 -#, fuzzy msgid "The relay domain this alias points to" -msgstr "O domínio para o qual este alias irá apontar" +msgstr "" #: extensions/postfix_relay_domains/models.py:195 -#, fuzzy, python-format +#, python-format msgid "Relay domain %s does not exist" -msgstr "O domínio '%s' não existe" +msgstr "" #: extensions/postfix_relay_domains/views.py:26 -#, fuzzy msgid "Relay domain created" -msgstr "Domínio criado" +msgstr "" #: extensions/postfix_relay_domains/views.py:31 -#, fuzzy msgid "New relay domain" -msgstr "Novo domínio" +msgstr "" #: extensions/postfix_relay_domains/views.py:54 -#, fuzzy msgid "Relay domain modified" -msgstr "Domínio alterado" +msgstr "" #: extensions/postfix_relay_domains/views.py:77 -#, fuzzy msgid "Relay domain deleted" -msgstr "Domínio criado" +msgstr "" #: extensions/postfix_relay_domains/templates/postfix_relay_domains/service_field.html:2 msgid "Scan" @@ -2387,8 +2240,7 @@ msgstr "ativo" #: extensions/sievefilters/templates/sievefilters/index.html:94 msgid "" "No filters set defined yet. You must create one in order to define filters." -msgstr "" -"Não existem grupos de filtros. Terá de criar um para poder definir filtros." +msgstr "Não existem grupos de filtros. Terá de criar um para poder definir filtros." #: extensions/sievefilters/templatetags/sfilters_tags.py:15 msgid "New filters set" @@ -2645,9 +2497,8 @@ msgid "Automatic folder refresh rate (in seconds)" msgstr "Taxa de actualização automática de pastas (em segundos)" #: extensions/webmail/app_settings.py:103 -#, fuzzy msgid "Mailboxes container's width" -msgstr "Detentor das Caixas de Correio (Owner)" +msgstr "" #: extensions/webmail/app_settings.py:104 msgid "The width of the mailbox list container" @@ -2885,9 +2736,9 @@ msgid "Remove the selected mailbox" msgstr "Eliminar caixa de correio selecionada" #: lib/dbutils.py:36 -#, fuzzy, python-format +#, python-format msgid "Connection to database %s not configured" -msgstr "Não foi possível estabelecer ligação com o amavis: %s" +msgstr "" #: lib/exceptions.py:67 #, python-format @@ -2993,36 +2844,3 @@ msgstr "Lembrar-me" #: templates/registration/login.html:36 msgid "Log in" msgstr "Entrar" - -#~ msgid "An alias with this name already exists" -#~ msgstr "Já existe um alias com este nome" - -#~ msgid "A domain with this name already exists" -#~ msgstr "Este nome de domínio já existe" - -#~ msgid "Edit domain" -#~ msgstr "Editar domínio" - -#~ msgid "%d pending requests" -#~ msgstr "%d pedidos pendentes" - -#~ msgid "Content Class" -#~ msgstr "Tipo de Conteúdo" - -#~ msgid "Nothing" -#~ msgstr "Nenhum" - -#~ msgid "Bad request" -#~ msgstr "Pedido inválido" - -#~ msgid "Undefined action" -#~ msgstr "Ação indefinida" - -#~ msgid "User preferences" -#~ msgstr "Preferências do utilizador" - -#~ msgid "Per-user settings" -#~ msgstr "Configurações por usuário" - -#~ msgid "You need a mailbox in order to define a forward" -#~ msgstr "Precisa de uma caixa de correio para definir um reencaminhamento" diff --git a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po index 441d28c53..9e2768f05 100644 --- a/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po +++ b/modoboa/locale/pt_PT/LC_MESSAGES/djangojs.po @@ -1,8 +1,9 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Translators: +# lusitan , 2013 # mikec , 2012 # Sandra Ribeiro , 2013 msgid "" @@ -10,14 +11,13 @@ msgstr "" "Project-Id-Version: Modoboa\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-12-15 10:16+0100\n" -"PO-Revision-Date: 2013-06-03 17:44+0000\n" -"Last-Translator: Sandra Ribeiro \n" -"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/" -"modoboa/language/pt_PT/)\n" -"Language: pt_PT\n" +"PO-Revision-Date: 2013-12-23 11:22+0000\n" +"Last-Translator: lusitan \n" +"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/modoboa/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: extensions/admin/static/admin/js/admin.js:32 @@ -36,9 +36,7 @@ msgstr "Esta operação irá remover TODOS os dados associados a este domínio." msgid "" "This operation will remove all data associated to this domain, excepting " "accounts." -msgstr "" -"Esta operação irá remover TODOS os dados associados a este domínio, excepto " -"as contas." +msgstr "Esta operação irá remover TODOS os dados associados a este domínio, excepto as contas." #: extensions/admin/static/admin/js/admin.js:222 msgid "No domain administrator defined" @@ -76,7 +74,7 @@ msgstr "Esconder cabeçalho completo" #: extensions/postfix_relay_domains/static/postfix_relay_domains/js/relay_domains.js:49 msgid "Services updated" -msgstr "" +msgstr "Atualizados os serviços" #: extensions/sievefilters/static/sievefilters/js/lib.js:14 msgid "Remove this filter?" @@ -138,28 +136,9 @@ msgid "Cancel" msgstr "Cancelar" #: static/js/global.js:314 -#, fuzzy msgid "Internal error" -msgstr "Erro Interno" +msgstr "Erro interno" #: static/js/searchbar.js:20 msgid "Search..." msgstr "Pesquisar..." - -#~ msgid "Message deleted" -#~ msgstr "Mensagem apagada" - -#~ msgid "Delete this domain?" -#~ msgstr "Apagar este domínio?" - -#~ msgid "Delete this account?" -#~ msgstr "Apagar esta conta?" - -#~ msgid "Delete this list?" -#~ msgstr "Apagar esta lista?" - -#~ msgid "Delete this forward?" -#~ msgstr "Apagar este reencaminhamento?" - -#~ msgid "Delete this alias?" -#~ msgstr "Apagar este alias?" diff --git a/modoboa/static/css/viewmail.css b/modoboa/static/css/viewmail.css index 778e8dd77..2e669648a 100644 --- a/modoboa/static/css/viewmail.css +++ b/modoboa/static/css/viewmail.css @@ -49,6 +49,6 @@ pre { margin-left: 10px; margin-right: 20px; font-weight: bold; - width: 6.38%; - padding: 2px 0; + width: 7.5%; + padding: 0 0 2px 0; } \ No newline at end of file diff --git a/setup.py b/setup.py index 18f760183..bb2669e0c 100644 --- a/setup.py +++ b/setup.py @@ -54,7 +54,7 @@ def read(fname): setup( name="modoboa", - version='1.0.1', + version='1.1.0', url='http://modoboa.org/', license='MIT', description="Mail hosting made simple",