mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-22 06:28:41 +02:00
Started import work
This commit is contained in:
@@ -89,6 +89,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.maillog',
|
||||
'modoboa.pdfcredentials',
|
||||
'modoboa.dmarc',
|
||||
'modoboa.imap_migration',
|
||||
# Modoboa extensions here.
|
||||
{% for extension in extensions %} '{{ extension }}',
|
||||
{% endfor %}
|
||||
@@ -119,6 +120,7 @@ AUTHENTICATION_BACKENDS = (
|
||||
#'modoboa.lib.authbackends.LDAPBackend',
|
||||
#'modoboa.lib.authbackends.SMTPBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'modoboa.imap_migration.auth_backends.IMAPBackend',
|
||||
)
|
||||
|
||||
# SMTP authentication
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""A plugin to migrate mailboxes using IMAP."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from pkg_resources import get_distribution, DistributionNotFound
|
||||
|
||||
|
||||
try:
|
||||
__version__ = get_distribution(__name__).version
|
||||
except DistributionNotFound:
|
||||
# package is not installed
|
||||
pass
|
||||
|
||||
default_app_config = "modoboa.imap_migration.apps.IMAPMigrationConfig"
|
||||
@@ -0,0 +1,93 @@
|
||||
"""API serializers."""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
|
||||
from modoboa.imap_migration import models
|
||||
|
||||
|
||||
class EmailProviderDomainSerializer(serializers.ModelSerializer):
|
||||
"""Serializer class for EmailProviderDomain."""
|
||||
|
||||
id = serializers.IntegerField(required=False)
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
"name": {
|
||||
"validators": []
|
||||
}
|
||||
}
|
||||
fields = ("id", "name", "new_domain")
|
||||
model = models.EmailProviderDomain
|
||||
|
||||
|
||||
class EmailProviderSerializer(serializers.ModelSerializer):
|
||||
"""Serializer class for EmailProvider."""
|
||||
|
||||
domains = EmailProviderDomainSerializer(many=True, required=False)
|
||||
|
||||
class Meta:
|
||||
fields = "__all__"
|
||||
model = models.EmailProvider
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Create provider and domains."""
|
||||
domains = validated_data.pop("domains", None)
|
||||
validated_data.pop("id", None)
|
||||
provider = models.EmailProvider.objects.create(**validated_data)
|
||||
if domains:
|
||||
to_create = []
|
||||
for domain in domains:
|
||||
to_create.append(models.EmailProviderDomain(
|
||||
provider=provider, **domain))
|
||||
models.EmailProviderDomain.objects.bulk_create(to_create)
|
||||
return provider
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""Update provider and domains."""
|
||||
domains = validated_data.pop("domains", [])
|
||||
domain_ids = [domain["id"] for domain in domains if "id" in domain]
|
||||
for key, value in validated_data.items():
|
||||
setattr(instance, key, value)
|
||||
instance.save()
|
||||
for domain in instance.domains.all():
|
||||
if domain.id not in domain_ids:
|
||||
domain.delete()
|
||||
else:
|
||||
for updated_domain in domains:
|
||||
if updated_domain.get("id") != domain.id:
|
||||
continue
|
||||
domain.name = updated_domain["name"]
|
||||
domain.new_domain = updated_domain.get("new_domain")
|
||||
domain.save()
|
||||
domains.remove(updated_domain)
|
||||
break
|
||||
to_create = []
|
||||
for new_domain in domains:
|
||||
to_create.append(models.EmailProviderDomain(
|
||||
name=new_domain["name"],
|
||||
new_domain=new_domain.get("new_domain"),
|
||||
provider=instance
|
||||
))
|
||||
models.EmailProviderDomain.objects.bulk_create(to_create)
|
||||
return instance
|
||||
|
||||
|
||||
class MailboxSerializer(serializers.ModelSerializer):
|
||||
"""Simple mailbox serializer."""
|
||||
|
||||
class Meta:
|
||||
fields = ("id", "full_address")
|
||||
model = admin_models.Mailbox
|
||||
|
||||
|
||||
class MigrationSerializer(serializers.ModelSerializer):
|
||||
"""Serializer class for Migration."""
|
||||
|
||||
mailbox = MailboxSerializer()
|
||||
|
||||
class Meta:
|
||||
depth = 1
|
||||
fields = ("id", "provider", "mailbox", "username")
|
||||
model = models.Migration
|
||||
@@ -0,0 +1,12 @@
|
||||
"""API urls."""
|
||||
|
||||
from rest_framework import routers
|
||||
|
||||
from . import viewsets
|
||||
|
||||
|
||||
router = routers.SimpleRouter()
|
||||
router.register(r"email-providers", viewsets.EmailProviderViewSet)
|
||||
router.register(r"migrations", viewsets.MigrationViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
@@ -0,0 +1,39 @@
|
||||
"""API viewsets."""
|
||||
|
||||
from rest_framework import filters, mixins, permissions, viewsets
|
||||
|
||||
from ... import models
|
||||
|
||||
from . import serializers
|
||||
|
||||
|
||||
class EmailProviderViewSet(viewsets.ModelViewSet):
|
||||
"""ViewSet class for EmailProvider."""
|
||||
|
||||
filter_backends = (filters.SearchFilter, )
|
||||
permission_classes = (
|
||||
permissions.IsAuthenticated,
|
||||
permissions.DjangoModelPermissions
|
||||
)
|
||||
queryset = models.EmailProvider.objects.all().prefetch_related("domains")
|
||||
search_fields = ("name", )
|
||||
serializer_class = serializers.EmailProviderSerializer
|
||||
|
||||
|
||||
class MigrationViewSet(mixins.ListModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
"""ViewSet class for Migration."""
|
||||
|
||||
filter_backends = (filters.SearchFilter, )
|
||||
permission_classes = (
|
||||
permissions.IsAuthenticated,
|
||||
permissions.DjangoModelPermissions
|
||||
)
|
||||
queryset = models.Migration.objects.all().select_related(
|
||||
"provider", "mailbox__domain")
|
||||
search_fields = (
|
||||
"username", "provider__name", "mailbox__address",
|
||||
"mailbox__domain__name")
|
||||
serializer_class = serializers.MigrationSerializer
|
||||
@@ -0,0 +1,30 @@
|
||||
"""APIv2 serializers."""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class IMAPMigrationSettingsSerializer(serializers.Serializer):
|
||||
"""A serializer for global parameters."""
|
||||
|
||||
# General
|
||||
enabled_imapmigration = serializers.BooleanField(default=True)
|
||||
|
||||
# OfflineIMAP settings
|
||||
max_sync_accounts = serializers.IntegerField(default=1)
|
||||
|
||||
# OfflineIMAP Filter settings
|
||||
create_folders = serializers.BooleanField(default=True)
|
||||
folder_filter_exclude = serializers.CharField(required=False,
|
||||
allow_blank=True,
|
||||
default="")
|
||||
folder_filter_include = serializers.CharField(required=False,
|
||||
allow_blank=True,
|
||||
default="")
|
||||
|
||||
|
||||
class CheckProviderSerializer(serializers.Serializer):
|
||||
"""A serializer for checking connection to IMAP server."""
|
||||
|
||||
address = serializers.CharField()
|
||||
port = serializers.IntegerField(min_value=0, max_value=65535)
|
||||
secured = serializers.BooleanField()
|
||||
@@ -0,0 +1,13 @@
|
||||
"""API urls."""
|
||||
|
||||
from rest_framework import routers
|
||||
|
||||
from ..v1 import viewsets as v1_viewsets
|
||||
from .viewsets import EmailProviderViewSet
|
||||
|
||||
|
||||
router = routers.SimpleRouter()
|
||||
router.register(r"email-providers", EmailProviderViewSet)
|
||||
router.register(r"migrations", v1_viewsets.MigrationViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
@@ -0,0 +1,35 @@
|
||||
"""Viewsets for API V2 for imap_migration."""
|
||||
|
||||
import imaplib
|
||||
import socket
|
||||
import ssl
|
||||
|
||||
from rest_framework import serializers, response
|
||||
from rest_framework.decorators import action
|
||||
|
||||
from modoboa.imap_migration.api.v1 import viewsets as v1_viewsets
|
||||
from .serializers import CheckProviderSerializer
|
||||
|
||||
|
||||
class EmailProviderViewSet(v1_viewsets.EmailProviderViewSet):
|
||||
|
||||
@action(methods=["post"], detail=False)
|
||||
def check_connection(self, request, **kwargs):
|
||||
"""check that provided information allow connection to imap server."""
|
||||
serializer = CheckProviderSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
secured = serializer.data["secured"]
|
||||
address = serializer.data["address"]
|
||||
port = serializer.data["port"]
|
||||
try:
|
||||
if secured:
|
||||
print(address)
|
||||
print(port)
|
||||
imaplib.IMAP4_SSL(address, port)
|
||||
else:
|
||||
imaplib.IMAP4(address, port)
|
||||
except (socket.error, imaplib.IMAP4.error, ssl.SSLError) as error:
|
||||
print(type(error))
|
||||
print(error)
|
||||
return response.Response({'status': 'failed'}, 400)
|
||||
return response.Response(status=200)
|
||||
@@ -0,0 +1,107 @@
|
||||
"""IMAP migration forms."""
|
||||
|
||||
import collections
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
|
||||
IMAP_MIGRATION_PARAMETERS_STRUCT = collections.OrderedDict([
|
||||
("general", {
|
||||
"label": _("General"),
|
||||
"params": collections.OrderedDict([
|
||||
("enabled_imapmigration", {
|
||||
"label": _("Enable IMAP Migration"),
|
||||
"help_text": _(
|
||||
"Enable IMAP Migration."),
|
||||
})
|
||||
])
|
||||
}),
|
||||
("offlineimap", {
|
||||
"label": _("OfflineIMAP"),
|
||||
"params": collections.OrderedDict([
|
||||
("max_sync_accounts", {
|
||||
"label": _("Concurrent sync jobs"),
|
||||
"help_text": _(
|
||||
"The maximum number of concurrent synchronization jobs")
|
||||
})
|
||||
])
|
||||
}),
|
||||
("offlineimapfilter", {
|
||||
"label": _("OfflineIMAP Filter"),
|
||||
"params": collections.OrderedDict([
|
||||
("create_folders", {
|
||||
"label": _("Create Folders"),
|
||||
"help_text": _(
|
||||
"Allow Creation of missing folders during sync"),
|
||||
}),
|
||||
("folder_filter_exclude", {
|
||||
"label": _("Folder Filter Exclusions"),
|
||||
"help_text": _(
|
||||
"Use a regular expression to explicitly include folders in sync. "
|
||||
"Example: ^Trash$|Del")
|
||||
}),
|
||||
("folder_filter_include", {
|
||||
"label": _("Folder Filter Inclusions"),
|
||||
"help_text": _(
|
||||
"A comma seperated list of folders to explicitly include in sync "
|
||||
"even if filtered by the Folder Filter Exclusions. Example: "
|
||||
"debian.user, debian.personal ")
|
||||
})
|
||||
])
|
||||
})
|
||||
])
|
||||
|
||||
|
||||
class ParametersForm(param_forms.AdminParametersForm):
|
||||
"""IMAP migration settings."""
|
||||
|
||||
app = "imap_migration"
|
||||
|
||||
sep1 = form_utils.SeparatorField(label=_("General"))
|
||||
|
||||
enabled_imapmigration = form_utils.YesNoField(
|
||||
label=_("Enable IMAP Migration"),
|
||||
initial=True,
|
||||
help_text=_("Enable IMAP Migration.")
|
||||
)
|
||||
|
||||
sep2 = form_utils.SeparatorField(label=_("OfflineIMAP settings"))
|
||||
|
||||
max_sync_accounts = forms.IntegerField(
|
||||
label=_("Concurrent sync jobs"),
|
||||
initial=1,
|
||||
help_text=_("The maximum number of concurrent synchronization jobs")
|
||||
)
|
||||
|
||||
sep3 = form_utils.SeparatorField(label=_("OfflineIMAP Filter settings"))
|
||||
|
||||
create_folders = form_utils.YesNoField(
|
||||
label=_("Create Folders"),
|
||||
initial=True,
|
||||
help_text=_("Allow Creation of missing folders during sync")
|
||||
)
|
||||
|
||||
folder_filter_exclude = forms.CharField(
|
||||
required=False,
|
||||
label=_("Folder Filter Exclusions"),
|
||||
initial="",
|
||||
help_text=_(
|
||||
"Use a regular expression to explicitly include folders in sync. "
|
||||
"Example: ^Trash$|Del"
|
||||
)
|
||||
)
|
||||
|
||||
folder_filter_include = forms.CharField(
|
||||
required=False,
|
||||
label=_("Folder Filter Inclusions"),
|
||||
initial="",
|
||||
help_text=_(
|
||||
"A comma seperated list of folders to explicitly include in sync "
|
||||
"even if filtered by the Folder Filter Exclusions. Example: "
|
||||
"debian.user, debian.personal "
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
"""AppConfig for IMAP migration."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
||||
def load_imapmigration_settings():
|
||||
"""Load core settings.
|
||||
|
||||
This function must be manually called (see :file:`urls.py`) in
|
||||
order to load base settings.
|
||||
"""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from . import app_settings
|
||||
from .api.v2 import serializers
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", app_settings.ParametersForm, ugettext_lazy("IMAP Migration"))
|
||||
param_tools.registry.add2(
|
||||
"global", "imap_migration", ugettext_lazy("IMAP Migration"),
|
||||
app_settings.IMAP_MIGRATION_PARAMETERS_STRUCT,
|
||||
serializers.IMAPMigrationSettingsSerializer)
|
||||
|
||||
|
||||
class IMAPMigrationConfig(AppConfig):
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.imap_migration"
|
||||
verbose_name = "Migration through IMAP for Modoboa"
|
||||
|
||||
def ready(self):
|
||||
from . import checks # noqa
|
||||
from . import handlers # noqa
|
||||
|
||||
load_imapmigration_settings()
|
||||
@@ -0,0 +1,105 @@
|
||||
"""IMAP authentication backend for Django."""
|
||||
|
||||
import imaplib
|
||||
import socket
|
||||
import ssl
|
||||
|
||||
from django.utils.encoding import smart_bytes, smart_str
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib import email_utils
|
||||
from modoboa.lib.exceptions import ModoboaException
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class IMAPBackend:
|
||||
"""IMAP authentication backend."""
|
||||
|
||||
def authenticate(self, request, username=None, password=None):
|
||||
"""Check the username/password and return a User."""
|
||||
if not param_tools.get_global_parameter("enabled_imapmigration"):
|
||||
return None
|
||||
condition = not param_tools.get_global_parameter(
|
||||
"auto_create_domain_and_mailbox", "admin")
|
||||
if condition:
|
||||
# Automatic domain/mailbox is disabled. Deny auth to
|
||||
# prevent further issues...
|
||||
return None
|
||||
self.address, domain = email_utils.split_mailbox(username)
|
||||
provider_domain = models.EmailProviderDomain.objects.filter(
|
||||
name=domain).select_related("provider").first()
|
||||
if not provider_domain:
|
||||
# Domain not allowed for migration: failure
|
||||
return None
|
||||
address = provider_domain.provider.address
|
||||
port = provider_domain.provider.port
|
||||
try:
|
||||
if provider_domain.provider.secured:
|
||||
conn = imaplib.IMAP4_SSL(address, port)
|
||||
else:
|
||||
conn = imaplib.IMAP4(address, port)
|
||||
except (socket.error, imaplib.IMAP4.error, ssl.SSLError) as error:
|
||||
raise ModoboaException(
|
||||
_("Connection to IMAP server failed: %s") % error)
|
||||
|
||||
try:
|
||||
typ, data = conn.login(
|
||||
smart_bytes(username), smart_str(password))
|
||||
except imaplib.IMAP4.error:
|
||||
typ = "NO"
|
||||
conn.logout()
|
||||
if typ != "OK":
|
||||
return None
|
||||
self.provider_domain = provider_domain
|
||||
return self.get_or_create_user(username, password)
|
||||
|
||||
def get_or_create_user(self, username, password):
|
||||
"""Get a user or create it the first time.
|
||||
|
||||
.. note::
|
||||
|
||||
We assume the username is a valid email address.
|
||||
"""
|
||||
orig_username = username
|
||||
# Check if old addresses must be converted
|
||||
if self.provider_domain.new_domain:
|
||||
username = u"{}@{}".format(
|
||||
self.address, self.provider_domain.new_domain.name)
|
||||
user, created = core_models.User.objects.get_or_create(
|
||||
username__iexact=username, defaults={
|
||||
"username": username.lower(), "email": username.lower()
|
||||
}
|
||||
)
|
||||
if created:
|
||||
user.set_password(password)
|
||||
user.save()
|
||||
core_models.populate_callback(user)
|
||||
models.Migration.objects.create(
|
||||
provider=self.provider_domain.provider,
|
||||
mailbox=user.mailbox,
|
||||
username=orig_username,
|
||||
password=password
|
||||
)
|
||||
else:
|
||||
# What happens if an account already exists?
|
||||
if not hasattr(user, "mailbox"):
|
||||
# No mailbox => might be an admin account
|
||||
return None
|
||||
qset = models.Migration.objects.filter(mailbox=user.mailbox)
|
||||
if not qset.exists():
|
||||
# No migration => either someone else account, or
|
||||
# migration is done
|
||||
return None
|
||||
return user
|
||||
|
||||
def get_user(self, user_pk):
|
||||
"""Retrieve a User instance."""
|
||||
user = None
|
||||
try:
|
||||
user = core_models.User.objects.get(pk=user_pk)
|
||||
except core_models.User.DoesNotExist:
|
||||
pass
|
||||
return user
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Deployment checks."""
|
||||
|
||||
from django.core.checks import Warning, register
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
|
||||
|
||||
W001 = Warning(
|
||||
_("Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."),
|
||||
hint=_("Go to the online parameters panel (admin tab) and activate "
|
||||
"this feature."),
|
||||
id="modoboa-imap-migration.W001"
|
||||
)
|
||||
|
||||
|
||||
@register(deploy=True)
|
||||
def check_auto_creation_is_enabled(app_configs, **kwargs):
|
||||
"""Ensure automatic domain/mailbox creation is on."""
|
||||
lc = core_models.LocalConfig.objects.first()
|
||||
if not lc:
|
||||
return []
|
||||
errors = []
|
||||
if not lc.parameters.get_value(
|
||||
"auto_create_domain_and_mailbox", app="admin"):
|
||||
errors.append(W001)
|
||||
return errors
|
||||
@@ -0,0 +1,37 @@
|
||||
"""IMAP migration factories."""
|
||||
|
||||
import factory
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class EmailProviderFactory(factory.django.DjangoModelFactory):
|
||||
"""Factory for EmailProvider."""
|
||||
|
||||
class Meta:
|
||||
model = models.EmailProvider
|
||||
|
||||
name = factory.Sequence(lambda n: "Provider {}".format(n))
|
||||
address = "127.0.0.1"
|
||||
port = 143
|
||||
|
||||
|
||||
class EmailProviderDomainFactory(factory.django.DjangoModelFactory):
|
||||
"""Factory for EmailProviderDomain."""
|
||||
|
||||
class Meta:
|
||||
model = models.EmailProviderDomain
|
||||
|
||||
provider = factory.SubFactory(EmailProviderFactory)
|
||||
|
||||
|
||||
class MigrationFactory(factory.django.DjangoModelFactory):
|
||||
"""Factory for Migration."""
|
||||
|
||||
class Meta:
|
||||
model = models.Migration
|
||||
|
||||
mailbox = factory.SubFactory(admin_factories.MailboxFactory)
|
||||
provider = factory.SubFactory(EmailProviderFactory)
|
||||
@@ -0,0 +1,19 @@
|
||||
"""IMAP migration handlers."""
|
||||
|
||||
from django.urls import reverse
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
|
||||
|
||||
@receiver(core_signals.extra_user_menu_entries)
|
||||
def menu(sender, location, user, **kwargs):
|
||||
"""Return extra menu entry."""
|
||||
if location != "top_menu" or not user.is_superuser:
|
||||
return []
|
||||
return [
|
||||
{"name": "imap_migrations",
|
||||
"label": _("IMAP migrations"),
|
||||
"url": reverse("imap_migration:index")}
|
||||
]
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Jan Laufik, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-28 11:43+0000\n"
|
||||
"Last-Translator: Jan Laufik\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/tonio/"
|
||||
"modoboa/language/cs_CZ/)\n"
|
||||
"Language: cs_CZ\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Spojení se serverem IMAP selhalo: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "Nastavení OfflineIMAP"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Souběžné synchronizační úkoly"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Maximální počet souběžných synchronizačních úkolů"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "Nastavení OfflineIMAP"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "IMAP migrace"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "IMAP migrace pomocí OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migrace existujících schránek pomocí IMAP protokolu a OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa.imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "IMAP migrace"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Konfigurace připojení"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Adresa serveru"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Adresa vašeho IMAP serveru"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Použít zabezpečené připojení"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Použít zabezpečené připojení pro přístup k IMAP serveru"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Port serveru"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Port, na kterém naslouchá váš IMAP server"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Zrušit migraci tohoto účtu"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Zrušit migraci pro %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Nenznámá migrace"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Migrace úspěšně zrušena"
|
||||
@@ -0,0 +1,133 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# controlc.de, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: controlc.de\n"
|
||||
"Language-Team: German (http://www.transifex.com/tonio/modoboa/language/de/)\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Verbindung zu IMAP-Server fehlgeschlagen: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "OfflineIMAP-Einstellungen"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Gleichzeitige Synchronisierungsaufgaben"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Die maximale Anzahl von gleichzeitigen Synchronisierungsaufgaben"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "OfflineIMAP-Einstellungen"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "IMAP-Migration"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "IMAP-Migration benutzt OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migration existierender Postfächer benutzt IMAP und OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "IMAP-Migration"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Verbindungseinstellungen"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Server-Adresse"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Addresse Ihres IMAP-Servers"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Gesicherte Verbindung verwenden"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Gesicherte Verbindung für Zugriff auf IMAP-Server verwenden"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Server-Port"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Port auf dem der IMAP-Server lauscht"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Diese Konten-Migration abbrechen"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Migration für %s abbrechen?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Unbekannte Migration"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Abbruch der Migration war erfolgreich"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Giannis Kapetanakis <bilias@edu.physics.uoc.gr>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: Giannis Kapetanakis <bilias@edu.physics.uoc.gr>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/el_GR/)\n"
|
||||
"Language: el_GR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Παρουσιάστηκε σφάλμα στη σύνδεση με τον εξυπηρετητή IMAP: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "Ρυθμίσεις OfflineIMAP"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Ταυτόχρονες εργασίες συγχρονισμού"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Ο μέγιστος αριθμός ταυτόχρονων εργασιών συγχρονισμού"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "Ρυθμίσεις OfflineIMAP"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "Μετάβαση IMAP"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "Μετάβαση IMAP με χρήση του OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Μετάβαση υπαρχόντων γραμματοκιβωτίων με χρήση IMAP και του OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "Μετάβαση IMAP"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Ρυθμίσεις σύνδεσης"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Διεύθυνση εξυπηρετητή"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Η διεύθυνση του εξυπηρετητή IMAP"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Χρήση ασφαλής σύνδεσης"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Χρήση ασφαλής σύνδεσης με τον εξυπηρετητή IMAP"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Πόρτα εξυπηρετητή"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Η πόρτα λειτουργίας του εξυπηρετητή IMAP"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Ακύρωση της μετάβασης αυτού του λογαριασμού"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Ακύρωση της μετάβασης του %s;"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Άγνωστη μετάβαση"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Η μετάβαση ακυρώθηκε με επιτυχία"
|
||||
@@ -0,0 +1,95 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:23
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
msgid "IMAP migrations"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr ""
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,101 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2019-03-01 18:09+0100\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Echec lors de la connexion au serveur IMAP : %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr "La création automatique de domaine/compte est désactivée, ce qui veut dire que l'authentification IMAP ne fonctionnera pas."
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr "Rendez vous sur le panneau de configuration des paramètres (onglet Administration) et activez cette fonctionnalité."
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "Paramètres OfflineIMAP"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Tâche(s) de synchronisation concurrente(s)"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Nombre maximal de tâche de synchronisation concurrente"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "Paramètres de filtragre OfflineIMAP"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr "Création des dossiers"
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr "Autoriser la création des dossiers manquant pendant la synchro"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr "Filtre d'exclusion de dossier"
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
"Utiliser une expression régulière pour explicitement inclure des dossiers à "
|
||||
"synchroniser. Exemple : ^Trash$|Del"
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr "Filtre d'inclusion de dossier"
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
"Une liste de dossiers séparés par des virgules à explicitement inclure "
|
||||
"pendant la synchronisation même s'ils sont concernés par le filtre "
|
||||
"d'exclusion. Exemple debian.user, debian.personal"
|
||||
|
||||
#: handlers.py:17
|
||||
msgid "IMAP migrations"
|
||||
msgstr "Migrations IMAP"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "Migration IMAP basée sur OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migrer des boites existantes en utilisant IMAP et OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "Migration IMAP"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Rocco <mors10@hotmail.com>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: Rocco <mors10@hotmail.com>\n"
|
||||
"Language-Team: Italian (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"it/)\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Conennessione al server IMAP fallito: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "Impostazioni OfflineIMAP"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Sincronizzazioni contemporanee"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Il numero massimo si sincronizzazioni contemporanee"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "Impostazioni OfflineIMAP"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "Migrazione IMAP"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "Migrazione IMAP utilizzado OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migrare caselle di posta elettronica utilizzando IMAP e OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "Migrazione IMAP"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Impostazioni di connessione"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Indirizzo del Server"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Indirizzo del server IMAP"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Utilizza connessione sicura"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Utilizza una connessione sicura per l'accesso al server IMAP"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Porta del server"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Porta in ascolto del server IMAP"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Cancellare l'account di questa migrazione"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Cancellare la migrazione %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Migrazione sconosciuta"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Migrazione avvenuta con successo"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# cwatanab <chihiro.watanabe@live.jp>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: cwatanab <chihiro.watanabe@live.jp>\n"
|
||||
"Language-Team: Japanese (Japan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ja_JP/)\n"
|
||||
"Language: ja_JP\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "IMAP サーバーへの接続に失敗しました: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "オフライン IMAP 設定"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "同期ジョブの並列度"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "同期ジョブを同時に行う最大数"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "オフライン IMAP 設定"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "IMAP マイグレーション"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "オフライン IMAP を使用して IMAP マイグレーション"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "IMAP と オフライン IMAP を使って既存のメールボックスを移行します"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "IMAP マイグレーション"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "接続設定"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "サーバーアドレス"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "IMAP サーバーのアドレス"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "セキュアな接続を使う"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "IMAP サーバーへのアクセスにセキュアな接続を使う"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "サーバーポート"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "IMAP サーバーの待受ポート"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "このアカウントのマイグレーションをキャンセルする"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "%s のマイグレーションをキャンセルしますか?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "不明なマイグレーション"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "マイグレーションのキャンセルに成功しました"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Tuxis Internet Engineering V.O.F. <info@tuxis.nl>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-12-20 14:22+0000\n"
|
||||
"Last-Translator: Tuxis Internet Engineering V.O.F. <info@tuxis.nl>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/nl_NL/)\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Verbinding met de IMAP server mislukt: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "OfflineIMAP instellingen"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Gelijktijdige synchronisatietaken"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Het maximale aantal gelijktijdige synchronisatietaken"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "OfflineIMAP instellingen"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "IMAP migratie"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "IMAP migratie door middel van OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migreer bestaande mailboxen door middel van IMAP en OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "IMAP migratie"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Verbinding instellingen"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Serveradres"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Adres van uw IMAP-server"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Gebruik een beveiligde verbinding"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Gebruik een beveiligde verbinding met de IMAP server"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Serverpoort"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Poort van uw IMAP server"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Annuleer de migratie van dit account"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Annuleer de migratie van %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Onbekende migratie"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Migratie succesvol geannuleerd"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Paulino Michelazzo <paulino@michelazzo.com.br>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: Paulino Michelazzo <paulino@michelazzo.com.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/pt_BR/)\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Falha ao conectar no servidor IMAP: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "Configurações OfflineIMAP"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Tarefas de sincronismo concorrentes"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "O número máximo de tarefas de sincronismo concorrentes"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "Configurações OfflineIMAP"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "Migração IMAP"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "Migração IMAP usando OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migrar as caixas postais existentes usando IMAP e OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "Migração IMAP"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Configurações de conexão"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Endereço do servidor"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Endereço do seu servidor IMAP"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Usar conexão segura"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Usar uma conexão segura para acessar o servidor IMAP"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Porta do servidor"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Porta de escuta do seu servidor IMAP"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Cancelar esta migração de conta"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Cancelar a migração para %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Migração desconhecida"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Migração cancelada com sucesso"
|
||||
@@ -0,0 +1,135 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Gregor <info@gregorjev.net>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: Gregor <info@gregorjev.net>\n"
|
||||
"Language-Team: Slovenian (Slovenia) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/sl_SI/)\n"
|
||||
"Language: sl_SI\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
|
||||
"%100==4 ? 2 : 3);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Povezava z IMAP strežnikom ni uspela: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "IMAP nastavitve brez povezave"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Concurrent sync jobs"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "The maximum number of concurrent synchronization jobs"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "IMAP nastavitve brez povezave"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "Selitev IMAP"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "IMAP selitev z uporabo IMAP brez povezave"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Preseli obstoječe poštne predale z uporabo IMAP in IMAP brez povezave"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "Selitev IMAP"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Nastavitve povezave"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Naslov strežnika"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Naslov vašega IMAP strežnika"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Uporabi zavarovano povezavo"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Za dostop do IMAP strežnika, uporabite zavarovano povezavo"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Vrata strežnika"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Vrata vašega IMAP strežnika"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Prekliči selitev računa"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Prekličem selitev za %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Neznana selitev"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Selivet je uspešno preklicana"
|
||||
@@ -0,0 +1,134 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-01 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-11-09 16:13+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\n"
|
||||
"Language-Team: Swedish (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"sv/)\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: auth_backends.py:45
|
||||
#, python-format
|
||||
msgid "Connection to IMAP server failed: %s"
|
||||
msgstr "Anslutning till IMAP server misslyckades: %s"
|
||||
|
||||
#: checks.py:11
|
||||
msgid ""
|
||||
"Automatic domain/mailbox creation is disabled which means IMAP "
|
||||
"authentication won't work."
|
||||
msgstr ""
|
||||
|
||||
#: checks.py:13
|
||||
msgid ""
|
||||
"Go to the online parameters panel (admin tab) and activate this feature."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid "OfflineIMAP settings"
|
||||
msgstr "OfflineIMAP inställningar"
|
||||
|
||||
#: forms.py:18
|
||||
msgid "Concurrent sync jobs"
|
||||
msgstr "Samtidiga synkroniserings jobb"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "The maximum number of concurrent synchronization jobs"
|
||||
msgstr "Det maximala antalet samtidiga synkroniserings jobb"
|
||||
|
||||
#: forms.py:23
|
||||
#, fuzzy
|
||||
#| msgid "OfflineIMAP settings"
|
||||
msgid "OfflineIMAP Filter settings"
|
||||
msgstr "OfflineIMAP inställningar"
|
||||
|
||||
#: forms.py:26
|
||||
msgid "Create Folders"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:28
|
||||
msgid "Allow Creation of missing folders during sync"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Folder Filter Exclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:36
|
||||
msgid ""
|
||||
"Use a regular expression to explicitly include folders in sync. Example: "
|
||||
"^Trash$|Del"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:43
|
||||
msgid "Folder Filter Inclusions"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:46
|
||||
msgid ""
|
||||
"A comma seperated list of folders to explicitly include in sync even if "
|
||||
"filtered by the Folder Filter Exclusions. Example: debian.user, debian."
|
||||
"personal "
|
||||
msgstr ""
|
||||
|
||||
#: handlers.py:17
|
||||
#, fuzzy
|
||||
#| msgid "IMAP migration"
|
||||
msgid "IMAP migrations"
|
||||
msgstr "IMAP migrering"
|
||||
|
||||
#: modo_extension.py:16
|
||||
msgid "IMAP migration using OfflineIMAP"
|
||||
msgstr "IMAP migrering med hjälp av OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:19
|
||||
msgid "Migrate existing mailboxes using IMAP and OfflineIMAP"
|
||||
msgstr "Migrera existerande brevlådor med hjälp av IMAP och OfflineIMAP"
|
||||
|
||||
#: modo_extension.py:25 templates/modoboa_imap_migration/index.html:6
|
||||
msgid "IMAP migration"
|
||||
msgstr "IMAP migrering"
|
||||
|
||||
#~ msgid "Connection settings"
|
||||
#~ msgstr "Anslutningsinställningar"
|
||||
|
||||
#~ msgid "Server address"
|
||||
#~ msgstr "Server adress"
|
||||
|
||||
#~ msgid "Address of your IMAP server"
|
||||
#~ msgstr "Adress till din IMAP server"
|
||||
|
||||
#~ msgid "Use a secured connection"
|
||||
#~ msgstr "Använd en säker anslutning"
|
||||
|
||||
#~ msgid "Use a secured connection to access IMAP server"
|
||||
#~ msgstr "Använd en säker anslutning för åtkomst till IMAP server"
|
||||
|
||||
#~ msgid "Server port"
|
||||
#~ msgstr "Server port"
|
||||
|
||||
#~ msgid "Listening port of your IMAP server"
|
||||
#~ msgstr "Lyssningsport för din IMAP server"
|
||||
|
||||
#~ msgid "Cancel this account's migration"
|
||||
#~ msgstr "Avbryt detta kontos migrering"
|
||||
|
||||
#~ msgid "Cancel the migration for %s?"
|
||||
#~ msgstr "Avbryt migreringen för %s?"
|
||||
|
||||
#~ msgid "Unknow migration"
|
||||
#~ msgstr "Okänd migrering"
|
||||
|
||||
#~ msgid "Migration cancelled successfully"
|
||||
#~ msgstr "Migrering avbröts framgångsrikt"
|
||||
@@ -0,0 +1,44 @@
|
||||
"""A management command to create an offlineimap configuration file."""
|
||||
|
||||
import os
|
||||
import stat
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from modoboa.admin.app_settings import load_admin_settings
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from ...models import Migration
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""Command definition."""
|
||||
|
||||
help = "Generate an offlineimap configuration file."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
"""Add extra arguments to command line."""
|
||||
parser.add_argument(
|
||||
"--output", default="/tmp/offlineimap.conf",
|
||||
help="Path of the generated file")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Entry point."""
|
||||
load_admin_settings()
|
||||
conf = dict(
|
||||
param_tools.get_global_parameters("imap_migration"))
|
||||
context = {
|
||||
"imap_create_folders": conf["create_folders"],
|
||||
"imap_folder_filter_exclude": conf["folder_filter_exclude"],
|
||||
"imap_folder_filter_include": ", ".join(
|
||||
"'{0}'".format(w)
|
||||
for w in conf["folder_filter_include"].split(",")),
|
||||
"migrations": Migration.objects.select_related(
|
||||
"provider", "mailbox__domain"),
|
||||
}
|
||||
with open(options["output"], "w") as fpo:
|
||||
content = render_to_string(
|
||||
"imap_migration/offlineimap.conf", context)
|
||||
fpo.write(content)
|
||||
os.chmod(options["output"], stat.S_IRUSR | stat.S_IWUSR)
|
||||
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('admin', '__first__'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Migration',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('_password', models.CharField(max_length=100)),
|
||||
('mailbox', models.ForeignKey(to='admin.Mailbox', on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('imap_migration', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='migration',
|
||||
name='_password',
|
||||
field=models.CharField(max_length=255),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,81 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.18 on 2019-02-07 08:19
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def create_default_provider(apps, schema_editor):
|
||||
"""Create default provider based on old settings."""
|
||||
EmailProvider = apps.get_model("imap_migration", "EmailProvider")
|
||||
Migration = apps.get_model("imap_migration", "Migration")
|
||||
LocalConfig = apps.get_model("core", "LocalConfig")
|
||||
lc = LocalConfig.objects.first()
|
||||
if not lc:
|
||||
return
|
||||
params = lc._parameters.get("imap_migration")
|
||||
if params is None:
|
||||
return
|
||||
provider = EmailProvider.objects.create(
|
||||
name="Default",
|
||||
address=params["server_address"],
|
||||
port=params["server_port"],
|
||||
secured=params["secured"]
|
||||
)
|
||||
for migration in Migration.objects.select_related("mailbox__domain"):
|
||||
migration.provider = provider
|
||||
migration.username = (
|
||||
migration.mailbox.address + "@" + migration.mailbox.domain.name)
|
||||
migration.save(update_fields=["provider", "username"])
|
||||
|
||||
|
||||
def backwards(apps, schema_editor):
|
||||
pass
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('admin', '0014_auto_20181017_1628'),
|
||||
('imap_migration', '0002_password'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EmailProvider',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('address', models.CharField(max_length=200)),
|
||||
('port', models.PositiveIntegerField(default=143)),
|
||||
('secured', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EmailProviderDomain',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('new_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='admin.Domain')),
|
||||
('provider', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='imap_migration.EmailProvider')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['provider', 'name'],
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='migration',
|
||||
name='username',
|
||||
field=models.CharField(max_length=254, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='migration',
|
||||
name='provider',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='imap_migration.EmailProvider'),
|
||||
),
|
||||
migrations.RunPython(create_default_provider, backwards)
|
||||
]
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.18 on 2019-02-07 08:39
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('imap_migration', '0003_auto_20190207_0919'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='migration',
|
||||
name='provider',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='imap_migration.EmailProvider'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='migration',
|
||||
name='username',
|
||||
field=models.CharField(max_length=254),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 2.2.12 on 2021-04-01 07:38
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('imap_migration', '0004_auto_20190207_0939'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='emailproviderdomain',
|
||||
name='provider',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='domains', to='imap_migration.EmailProvider'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='migration',
|
||||
name='username',
|
||||
field=models.CharField(max_length=254, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
IMAP migration models.
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
from modoboa.admin.models import Mailbox
|
||||
from modoboa.lib.cryptutils import encrypt, decrypt
|
||||
|
||||
|
||||
class EmailProvider(models.Model):
|
||||
"""Email provider model."""
|
||||
|
||||
name = models.CharField(max_length=50)
|
||||
address = models.CharField(max_length=200)
|
||||
port = models.PositiveIntegerField(default=143)
|
||||
secured = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
ordering = ["name"]
|
||||
|
||||
|
||||
class EmailProviderDomain(models.Model):
|
||||
"""Email provider domain class."""
|
||||
|
||||
provider = models.ForeignKey(
|
||||
EmailProvider, on_delete=models.CASCADE, related_name="domains")
|
||||
name = models.CharField(max_length=100, unique=True)
|
||||
new_domain = models.ForeignKey(
|
||||
"admin.Domain", on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ["provider", "name"]
|
||||
|
||||
|
||||
class Migration(models.Model):
|
||||
"""Represent mailboxes to migrate."""
|
||||
|
||||
provider = models.ForeignKey(EmailProvider, on_delete=models.CASCADE)
|
||||
mailbox = models.ForeignKey(Mailbox, on_delete=models.CASCADE)
|
||||
username = models.CharField(max_length=254, unique=True)
|
||||
_password = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
"""Password getter."""
|
||||
return decrypt(self._password)
|
||||
|
||||
@password.setter
|
||||
def password(self, value):
|
||||
"""Password setter."""
|
||||
self._password = encrypt(value)
|
||||
@@ -0,0 +1,27 @@
|
||||
{% extends "fluid.html" %}
|
||||
|
||||
{% load i18n lib_tags static %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
|
||||
{% block pagetitle %}{% trans "IMAP migration" %}{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
{% if not debug %}
|
||||
{% render_bundle 'chunk-vendors' 'css' 'IMAP_MIGRATION' %}
|
||||
{% render_bundle 'app' 'css' 'IMAP_MIGRATION' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
{% if not debug %}
|
||||
{% render_bundle 'chunk-vendors' 'js' 'IMAP_MIGRATION' %}
|
||||
{% endif %}
|
||||
{% render_bundle 'app' 'js' 'IMAP_MIGRATION' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block container_content %}
|
||||
|
||||
<div id="app">
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,40 @@
|
||||
[general]
|
||||
accounts = {{ migrations|join:", " }}
|
||||
|
||||
{% for migration in migrations %}
|
||||
[Account {{ migration }}]
|
||||
localrepository = Local_{{ migration }}
|
||||
remoterepository = Remote_{{ migration }}
|
||||
|
||||
[Repository Local_{{ migration }}]
|
||||
type = IMAP
|
||||
ssl = false
|
||||
remotehost = localhost
|
||||
remoteuser = {{ migration }}
|
||||
remotepass = {{ migration.password }}
|
||||
{% if imap_create_folders == False %}
|
||||
createfolders = False
|
||||
{% endif %}
|
||||
|
||||
[Repository Remote_{{ migration }}]
|
||||
type = IMAP
|
||||
remotehost = {{ migration.provider.address }}
|
||||
remoteport = {{ migration.provider.port }}
|
||||
{% if migration.provider.secured %}
|
||||
ssl = yes
|
||||
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
|
||||
{% else %}
|
||||
ssl = no
|
||||
{% endif %}
|
||||
remoteuser = {{ migration }}
|
||||
remotepass = {{ migration.password }}
|
||||
readonly = true
|
||||
{% autoescape off %}
|
||||
{% if imap_folder_filter_exclude|length > 0 %}
|
||||
folderfilter = lambda folder: not re.search('({{ imap_folder_filter_exclude }})', folder)
|
||||
{% endif %}
|
||||
{% if imap_folder_filter_include|length > 2 %}
|
||||
folderincludes = [{{ imap_folder_filter_include }}]
|
||||
{% endif %}
|
||||
{% endautoescape %}
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,204 @@
|
||||
"""IMAP migration tests."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
from six.moves import configparser
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.urls import reverse
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.core import factories as core_factories
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.tests import ModoTestCase, ModoAPITestCase
|
||||
|
||||
from . import checks
|
||||
from . import factories
|
||||
from . import models
|
||||
|
||||
|
||||
class DataMixin(object):
|
||||
"""A mixin to provide test data."""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(DataMixin, cls).setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.mb = admin_models.Mailbox.objects.get(
|
||||
user__username="user@test.com")
|
||||
cls.migration = factories.MigrationFactory(
|
||||
password="Toto1234", mailbox=cls.mb, username="user@test.com")
|
||||
|
||||
|
||||
# class ViewsTestCase(DataMixin, ModoTestCase):
|
||||
# """Views test cases."""
|
||||
|
||||
# def test_index(self):
|
||||
# """Test index view."""
|
||||
# url = reverse("modoboa_imap_migration:index")
|
||||
# response = self.client.get(url)
|
||||
# self.assertContains(response, '<div id="app">')
|
||||
|
||||
|
||||
class AuthenticationTestCase(DataMixin, ModoTestCase):
|
||||
"""IMAP authentication test case."""
|
||||
|
||||
@mock.patch("imaplib.IMAP4")
|
||||
def test_authentication(self, mock_imap):
|
||||
"""Check IMAP authentication."""
|
||||
factories.EmailProviderDomainFactory(name="test.com")
|
||||
mock_imap.return_value.login.return_value = ["OK", b""]
|
||||
url = reverse("core:login")
|
||||
data = {"username": "new_user@test.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
user = core_models.User.objects.get(username="new_user@test.com")
|
||||
self.assertEqual(user.mailbox.domain.name, "test.com")
|
||||
|
||||
mock_imap.return_value.login.return_value = ["NO", b"Error"]
|
||||
data = {"username": "new_user@test.com", "password": "Toto123"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
mock_imap.return_value.login.return_value = ["OK", b""]
|
||||
data = {"username": "new_user@test2.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
self.set_global_parameter(
|
||||
"auto_create_domain_and_mailbox", False, app="admin")
|
||||
data = {"username": "new_user2@test.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
@mock.patch("imaplib.IMAP4")
|
||||
def test_authenticate_and_rename(self, mock_imap):
|
||||
"""Check address renaming."""
|
||||
domain = admin_models.Domain.objects.get(name="test.com")
|
||||
factories.EmailProviderDomainFactory(
|
||||
name="gmail.com", new_domain=domain)
|
||||
mock_imap.return_value.login.return_value = ["OK", b""]
|
||||
url = reverse("core:login")
|
||||
data = {"username": "new_user@gmail.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
user = core_models.User.objects.get(username="new_user@test.com")
|
||||
self.assertEqual(user.mailbox.domain.name, "test.com")
|
||||
|
||||
@mock.patch("imaplib.IMAP4")
|
||||
def test_authenticate_conflicts(self, mock_imap):
|
||||
"""Check potential conflicts."""
|
||||
core_factories.UserFactory(
|
||||
username="admin2@test.com", groups=("DomainAdmins", ),
|
||||
password="{PLAIN}toto"
|
||||
)
|
||||
domain = admin_models.Domain.objects.get(name="test.com")
|
||||
factories.EmailProviderDomainFactory(
|
||||
name="gmail.com", new_domain=domain)
|
||||
mock_imap.return_value.login.return_value = ["OK", b""]
|
||||
url = reverse("core:login")
|
||||
data = {"username": "admin@gmail.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
data = {"username": "admin2@gmail.com", "password": "Toto1234"}
|
||||
response = self.client.post(url, data)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
|
||||
|
||||
class ManagementCommandTestCase(DataMixin, ModoTestCase):
|
||||
"""Management command test cases."""
|
||||
|
||||
def setUp(self):
|
||||
super(ManagementCommandTestCase, self).setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.workdir)
|
||||
|
||||
def test_generate_offlineimap_config(self):
|
||||
"""Test generate_offlineimap_config command."""
|
||||
path = os.path.join(self.workdir, "offlineimap.conf")
|
||||
call_command("generate_offlineimap_config", "--output", path)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read(path)
|
||||
self.assertTrue(conf.has_section("Account user@test.com"))
|
||||
|
||||
|
||||
class ViewSetTestCase(DataMixin, ModoAPITestCase):
|
||||
"""ViewSet related tests."""
|
||||
|
||||
def test_create_provider(self):
|
||||
url = reverse("api:emailprovider-list")
|
||||
data = {
|
||||
"name": "Google",
|
||||
"address": "imap.google.com",
|
||||
"port": 143,
|
||||
"secured": True,
|
||||
"domains": [
|
||||
{"id": 1000,
|
||||
"name": "gmail.com"}
|
||||
]
|
||||
}
|
||||
response = self.client.post(url, data, format="json")
|
||||
self.assertEqual(response.status_code, 201)
|
||||
self.assertTrue(
|
||||
models.EmailProviderDomain.objects.filter(name="gmail.com")
|
||||
.exists()
|
||||
)
|
||||
|
||||
def test_update_provider(self):
|
||||
provider_domain = factories.EmailProviderDomainFactory(
|
||||
name="outlook.com")
|
||||
url = reverse(
|
||||
"api:emailprovider-detail", args=[provider_domain.provider.pk])
|
||||
data = {
|
||||
"id": provider_domain.provider.id,
|
||||
"name": provider_domain.provider.name,
|
||||
"address": provider_domain.provider.address,
|
||||
"port": provider_domain.provider.port,
|
||||
"domains": [
|
||||
{"id": provider_domain.id,
|
||||
"name": "hotmail.com",
|
||||
"new_domain": None},
|
||||
{"name": "gmail.com",
|
||||
"new_domain": admin_models.Domain.objects.get(
|
||||
name="test.com").pk}
|
||||
]
|
||||
}
|
||||
response = self.client.put(url, data, format="json")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
provider_domain.refresh_from_db()
|
||||
self.assertEqual(provider_domain.name, data["domains"][0]["name"])
|
||||
self.assertTrue(
|
||||
models.EmailProviderDomain.objects.filter(name="gmail.com")
|
||||
.exists()
|
||||
)
|
||||
data["domains"].pop()
|
||||
response = self.client.put(url, data, format="json")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(
|
||||
models.EmailProviderDomain.objects.filter(name="gmail.com")
|
||||
.exists()
|
||||
)
|
||||
|
||||
|
||||
class ChecksTestCase(ModoTestCase):
|
||||
"""Deploy checks test case."""
|
||||
|
||||
def test_auto_creation_check(self):
|
||||
self.assertEqual(
|
||||
checks.check_auto_creation_is_enabled(None),
|
||||
[]
|
||||
)
|
||||
self.set_global_parameter(
|
||||
"auto_create_domain_and_mailbox", False, app="admin")
|
||||
self.assertEqual(
|
||||
checks.check_auto_creation_is_enabled(None),
|
||||
[checks.W001]
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
"""Custom urls."""
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "imap_migration"
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.IndexView.as_view(), name="index"),
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
"""Views for the IMAP migration extension."""
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
|
||||
from django.views import generic
|
||||
|
||||
|
||||
class IndexView(auth_mixins.LoginRequiredMixin,
|
||||
auth_mixins.PermissionRequiredMixin,
|
||||
generic.TemplateView):
|
||||
"""Index view."""
|
||||
|
||||
permission_required = "modoboa.imap_migration.add_migration"
|
||||
template_name = "modoboa.imap_migration/index.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Set menu selection."""
|
||||
kwargs.update({"selection": "imap_migrations"})
|
||||
return super(IndexView, self).get_context_data(**kwargs)
|
||||
@@ -12,7 +12,7 @@ class ParametersAPITestCase(ModoAPITestCase):
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
# core, admin, limits, pdf credentials
|
||||
self.assertEqual(len(resp.json()), 5)
|
||||
self.assertEqual(len(resp.json()), 6)
|
||||
|
||||
def test_get_structure(self):
|
||||
url = reverse("v2:parameter-structure")
|
||||
|
||||
@@ -30,6 +30,7 @@ urlpatterns = [
|
||||
path('pdfcredentials', include("modoboa.pdfcredentials.urls")),
|
||||
path('stats/', include("modoboa.maillog.urls")),
|
||||
path('dmarc/', include("modoboa.dmarc.urls")),
|
||||
path('imap_migration/', include("modoboa.imap_migration.urls")),
|
||||
|
||||
path('user/forward/', user_views.forward, name="user_forward"),
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ app_name = "api"
|
||||
urlpatterns = [
|
||||
path('', include("modoboa.core.api.v1.urls")),
|
||||
path('', include("modoboa.admin.api.v1.urls")),
|
||||
path('', include("modoboa.imap_migration.api.v1.urls")),
|
||||
path('', include("modoboa.limits.api.v1.urls")),
|
||||
path('', include("modoboa.relaydomains.api.v1.urls"))
|
||||
]
|
||||
|
||||
@@ -10,13 +10,14 @@ urlpatterns = [
|
||||
path('', include("modoboa.core.api.v2.urls")),
|
||||
path('', include("modoboa.admin.api.v2.urls")),
|
||||
path('', include("modoboa.parameters.api.v2.urls")),
|
||||
path('', include("modoboa.imap_migration.api.v2.urls")),
|
||||
path('', include("modoboa.limits.api.v1.urls")),
|
||||
path('', include("modoboa.relaydomains.api.v1.urls")),
|
||||
path('', include("modoboa.dmarc.api.v2.urls")),
|
||||
path('', include("modoboa.dnstools.api.v2.urls")),
|
||||
path('', include("modoboa.maillog.api.v2.urls")),
|
||||
path('', include("modoboa.transport.api.v2.urls")),
|
||||
path('', include("modoboa.pdfcredentials.api.v2.urls")),
|
||||
path('', include("modoboa.pdfcredentials.api.v2.urls"))
|
||||
]
|
||||
|
||||
urlpatterns += exts_pool.get_urls(category="api")
|
||||
|
||||
Reference in New Issue
Block a user