193 lines
6.7 KiB
Python
193 lines
6.7 KiB
Python
"""
|
|
Unit tests for dimail client
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
from email.errors import HeaderParseError, NonASCIILocalPartDefect
|
|
from logging import Logger
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
import responses
|
|
from rest_framework import status
|
|
|
|
from mailbox_manager import enums, factories, models
|
|
from mailbox_manager.utils.dimail import DimailAPIClient
|
|
|
|
from .fixtures.dimail import CHECK_DOMAIN_BROKEN, CHECK_DOMAIN_OK
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_dimail_synchronization__already_sync():
|
|
"""
|
|
No mailbox should be created when everything is already synced.
|
|
"""
|
|
domain = factories.MailDomainEnabledFactory()
|
|
factories.MailboxFactory.create_batch(3, domain=domain)
|
|
|
|
pre_sync_mailboxes = models.Mailbox.objects.filter(domain=domain)
|
|
assert pre_sync_mailboxes.count() == 3
|
|
|
|
dimail_client = DimailAPIClient()
|
|
with responses.RequestsMock() as rsps:
|
|
# Ensure successful response using "responses":
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(r".*/token/"),
|
|
body='{"access_token": "dimail_people_token"}',
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(rf".*/domains/{domain.name}/mailboxes/"),
|
|
body=str(
|
|
[
|
|
{
|
|
"type": "mailbox",
|
|
"status": "broken",
|
|
"email": f"{mailbox.local_part}@{domain.name}",
|
|
"givenName": mailbox.first_name,
|
|
"surName": mailbox.last_name,
|
|
"displayName": f"{mailbox.first_name} {mailbox.last_name}",
|
|
}
|
|
for mailbox in pre_sync_mailboxes
|
|
]
|
|
),
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
imported_mailboxes = dimail_client.import_mailboxes(domain)
|
|
|
|
post_sync_mailboxes = models.Mailbox.objects.filter(domain=domain)
|
|
assert post_sync_mailboxes.count() == 3
|
|
assert imported_mailboxes == []
|
|
assert set(models.Mailbox.objects.filter(domain=domain)) == set(pre_sync_mailboxes)
|
|
|
|
|
|
@mock.patch.object(Logger, "warning")
|
|
def test_dimail_synchronization__synchronize_mailboxes(mock_warning):
|
|
"""A mailbox existing solely on dimail should be synchronized
|
|
upon calling sync function on its domain"""
|
|
domain = factories.MailDomainEnabledFactory()
|
|
assert not models.Mailbox.objects.exists()
|
|
|
|
dimail_client = DimailAPIClient()
|
|
with responses.RequestsMock() as rsps:
|
|
# Ensure successful response using "responses":
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(r".*/token/"),
|
|
body='{"access_token": "dimail_people_token"}',
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
|
|
mailbox_valid = {
|
|
"type": "mailbox",
|
|
"status": "broken",
|
|
"email": f"oxadmin@{domain.name}",
|
|
"givenName": "Admin",
|
|
"surName": "Context",
|
|
"displayName": "Context Admin",
|
|
}
|
|
mailbox_with_wrong_domain = {
|
|
"type": "mailbox",
|
|
"status": "broken",
|
|
"email": "johndoe@wrongdomain.com",
|
|
"givenName": "John",
|
|
"surName": "Doe",
|
|
"displayName": "John Doe",
|
|
}
|
|
mailbox_with_invalid_domain = {
|
|
"type": "mailbox",
|
|
"status": "broken",
|
|
"email": f"naw@ake@{domain.name}",
|
|
"givenName": "Joe",
|
|
"surName": "Doe",
|
|
"displayName": "Joe Doe",
|
|
}
|
|
mailbox_with_invalid_local_part = {
|
|
"type": "mailbox",
|
|
"status": "broken",
|
|
"email": f"obalmaské@{domain.name}",
|
|
"givenName": "Jean",
|
|
"surName": "Vang",
|
|
"displayName": "Jean Vang",
|
|
}
|
|
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(rf".*/domains/{domain.name}/mailboxes/"),
|
|
body=str(
|
|
[
|
|
mailbox_valid,
|
|
mailbox_with_wrong_domain,
|
|
mailbox_with_invalid_domain,
|
|
mailbox_with_invalid_local_part,
|
|
]
|
|
),
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
|
|
imported_mailboxes = dimail_client.import_mailboxes(domain)
|
|
|
|
# 3 imports failed: wrong domain, HeaderParseError, NonASCIILocalPartDefect
|
|
assert mock_warning.call_count == 3
|
|
|
|
# first we try to import email with a wrong domain
|
|
assert mock_warning.call_args_list[0][0] == (
|
|
"Import of email %s failed because of a wrong domain",
|
|
mailbox_with_wrong_domain["email"],
|
|
)
|
|
|
|
# then we try to import email with invalid domain
|
|
invalid_mailbox_log = mock_warning.call_args_list[1][0]
|
|
assert invalid_mailbox_log[1] == mailbox_with_invalid_domain["email"]
|
|
assert isinstance(invalid_mailbox_log[2], HeaderParseError)
|
|
|
|
# finally we try to import email with non ascii local part
|
|
non_ascii_mailbox_log = mock_warning.call_args_list[2][0]
|
|
assert non_ascii_mailbox_log[1] == mailbox_with_invalid_local_part["email"]
|
|
assert isinstance(non_ascii_mailbox_log[2], NonASCIILocalPartDefect)
|
|
|
|
mailbox = models.Mailbox.objects.get()
|
|
assert mailbox.local_part == "oxadmin"
|
|
assert imported_mailboxes == [mailbox_valid["email"]]
|
|
|
|
|
|
def test_dimail__fetch_domain_status_from_dimail():
|
|
"""Request to dimail health status of a domain"""
|
|
domain = factories.MailDomainEnabledFactory()
|
|
with responses.RequestsMock() as rsps:
|
|
body_content = CHECK_DOMAIN_BROKEN.copy()
|
|
body_content["name"] = domain.name
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(rf".*/domains/{domain.name}/check/"),
|
|
body=json.dumps(body_content),
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
dimail_client = DimailAPIClient()
|
|
response = dimail_client.fetch_domain_status(domain)
|
|
assert response.status_code == status.HTTP_200_OK
|
|
assert domain.status == enums.MailDomainStatusChoices.FAILED
|
|
|
|
# Now domain is ok again
|
|
body_content = CHECK_DOMAIN_OK.copy()
|
|
body_content["name"] = domain.name
|
|
rsps.add(
|
|
rsps.GET,
|
|
re.compile(rf".*/domains/{domain.name}/check/"),
|
|
body=json.dumps(body_content),
|
|
status=status.HTTP_200_OK,
|
|
content_type="application/json",
|
|
)
|
|
response = dimail_client.fetch_domain_status(domain)
|
|
assert response.status_code == status.HTTP_200_OK
|
|
assert domain.status == enums.MailDomainStatusChoices.ENABLED
|