diff --git a/modoboa_contacts/importer/__init__.py b/modoboa_contacts/importer/__init__.py index 9946d01..a59d381 100644 --- a/modoboa_contacts/importer/__init__.py +++ b/modoboa_contacts/importer/__init__.py @@ -8,7 +8,7 @@ ] -def detect_import_backend(fp, delimiter: str = ";"): +def get_import_backend(fp, delimiter: str = ";", name: str = "auto"): reader = csv.DictReader( fp, delimiter=delimiter, @@ -18,16 +18,21 @@ def detect_import_backend(fp, delimiter: str = ";"): rows = reader for backend in BACKENDS: - if backend.detect_from_columns(columns): + if name == "auto": + if backend.detect_from_columns(columns): + return backend, rows + elif name == backend.name: return backend, rows raise RuntimeError("Failed to detect backend to use") def import_csv_file(addressbook, + backend_name: str, csv_filename: str, delimiter: str, carddav_password: str = None): with open(csv_filename) as fp: - backend, rows = detect_import_backend(fp, delimiter) + backend, rows = get_import_backend( + fp, delimiter, backend_name) backend(addressbook).proceed(rows, carddav_password) diff --git a/modoboa_contacts/importer/backends/outlook.py b/modoboa_contacts/importer/backends/outlook.py index 597fc20..4ebc87a 100644 --- a/modoboa_contacts/importer/backends/outlook.py +++ b/modoboa_contacts/importer/backends/outlook.py @@ -32,7 +32,7 @@ class OutlookBackend(ImporterBackend): @classmethod def detect_from_columns(cls, columns): - return columns == OUTLOOK_COLUMNS + return set(OUTLOOK_COLUMNS).issubset(columns) def get_first_name(self, values: dict) -> str: result = values["First Name"] diff --git a/modoboa_contacts/management/commands/import_contacts.py b/modoboa_contacts/management/commands/import_contacts.py index 7e59a27..4fbcb25 100644 --- a/modoboa_contacts/management/commands/import_contacts.py +++ b/modoboa_contacts/management/commands/import_contacts.py @@ -23,6 +23,13 @@ def add_arguments(self, parser): "contacts will be synced to CardDAV servert too" ) ) + parser.add_argument( + "--backend", type=str, default="auto", + help=( + "Specify import backend to use. Defaults to 'auto', " + "meaning the script will try to guess which one to use" + ) + ) parser.add_argument( "email", type=str, help="Email address to import contacts for" @@ -44,6 +51,7 @@ def handle(self, *args, **options): try: import_csv_file( addressbook, + options["backend"], options["file"], options["delimiter"], options.get("carddav_password") diff --git a/modoboa_contacts/tests.py b/modoboa_contacts/tests.py index 476bf9a..0e73b12 100644 --- a/modoboa_contacts/tests.py +++ b/modoboa_contacts/tests.py @@ -375,7 +375,7 @@ def test_import_unknown_backend(self): self.assertEqual(str(ctx.exception), "Failed to detect backend to use") - def test_import_from_outlook(self): + def test_import_from_outlook_auto(self): management.call_command( "import_contacts", "user@test.com", self.path) address = models.EmailAddress.objects.get( @@ -389,6 +389,24 @@ def test_import_from_outlook(self): "Street 1 Street 2" ) + def test_import_from_outlook(self): + management.call_command( + "import_contacts", + "user@test.com", + self.path, + backend="outlook", + ) + address = models.EmailAddress.objects.get( + address="toto@titi.com") + phone = models.PhoneNumber.objects.get( + number="12345678") + self.assertEqual(address.contact.first_name, "Toto Tata") + self.assertEqual(address.contact.addressbook.user.email, "user@test.com") + self.assertEqual( + address.contact.address, + "Street 1 Street 2" + ) + def test_import_and_carddav_sync(self): with httmock.HTTMock(mocks.options_mock, mocks.put_mock): management.call_command(