mirror of https://github.com/zulip/zulip.git
zilencer: Disambiguate no MX records from the domain not existing.
This switches to dnspython, since it offers the higher-level `resolve_name` method to look up both A and AAAA records, and set timeouts.
This commit is contained in:
parent
9388805471
commit
e5a0b3b3c5
|
@ -8,7 +8,6 @@ from typing import Any, Dict, Iterator, List, Mapping, Optional, Tuple, Union
|
||||||
from unittest import mock, skipUnless
|
from unittest import mock, skipUnless
|
||||||
|
|
||||||
import aioapns
|
import aioapns
|
||||||
import DNS
|
|
||||||
import orjson
|
import orjson
|
||||||
import responses
|
import responses
|
||||||
import time_machine
|
import time_machine
|
||||||
|
@ -19,6 +18,7 @@ from django.http.response import ResponseHeaders
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
from dns.resolver import NoAnswer as DNSNoAnswer
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError
|
||||||
from requests.models import PreparedRequest
|
from requests.models import PreparedRequest
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
@ -5247,17 +5247,24 @@ class PushBouncerSignupTest(ZulipTestCase):
|
||||||
self.assert_json_error(result, "Please use your real email address.")
|
self.assert_json_error(result, "Please use your real email address.")
|
||||||
|
|
||||||
request["contact_email"] = "admin@zulip.com"
|
request["contact_email"] = "admin@zulip.com"
|
||||||
with mock.patch("DNS.mxlookup", side_effect=DNS.Base.ServerError("test", 1)):
|
with mock.patch("zilencer.views.dns_resolver.Resolver") as resolver:
|
||||||
|
resolver.return_value.resolve.side_effect = DNSNoAnswer
|
||||||
|
resolver.return_value.resolve_name.return_value = ["whee"]
|
||||||
result = self.client_post("/api/v1/remotes/server/register", request)
|
result = self.client_post("/api/v1/remotes/server/register", request)
|
||||||
self.assert_json_error(
|
self.assert_json_error(
|
||||||
result, "zulip.com does not exist or is not configured to accept email."
|
result, "zulip.com is invalid because it does not have any MX records"
|
||||||
)
|
)
|
||||||
|
|
||||||
with mock.patch("DNS.mxlookup", return_value=[]):
|
with mock.patch("zilencer.views.dns_resolver.Resolver") as resolver:
|
||||||
|
resolver.return_value.resolve.side_effect = DNSNoAnswer
|
||||||
|
resolver.return_value.resolve_name.side_effect = DNSNoAnswer
|
||||||
result = self.client_post("/api/v1/remotes/server/register", request)
|
result = self.client_post("/api/v1/remotes/server/register", request)
|
||||||
self.assert_json_error(
|
self.assert_json_error(result, "zulip.com does not exist")
|
||||||
result, "zulip.com does not exist or is not configured to accept email."
|
|
||||||
)
|
with mock.patch("zilencer.views.dns_resolver.Resolver") as resolver:
|
||||||
|
resolver.return_value.resolve.return_value = ["whee"]
|
||||||
|
result = self.client_post("/api/v1/remotes/server/register", request)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
|
|
||||||
class TestUserPushIdentityCompat(ZulipTestCase):
|
class TestUserPushIdentityCompat(ZulipTestCase):
|
||||||
|
|
|
@ -5,7 +5,6 @@ from email.headerregistry import Address
|
||||||
from typing import Any, Dict, List, Optional, Type, TypedDict, TypeVar, Union
|
from typing import Any, Dict, List, Optional, Type, TypedDict, TypeVar, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import DNS
|
|
||||||
import orjson
|
import orjson
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
@ -18,6 +17,8 @@ from django.utils.timezone import now as timezone_now
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.utils.translation import gettext as err_
|
from django.utils.translation import gettext as err_
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from dns import resolver as dns_resolver
|
||||||
|
from dns.exception import DNSException
|
||||||
from pydantic import BaseModel, ConfigDict, Json, StringConstraints
|
from pydantic import BaseModel, ConfigDict, Json, StringConstraints
|
||||||
from pydantic.functional_validators import AfterValidator
|
from pydantic.functional_validators import AfterValidator
|
||||||
from typing_extensions import Annotated
|
from typing_extensions import Annotated
|
||||||
|
@ -170,19 +171,25 @@ def register_remote_server(
|
||||||
raise JsonableError(_("Invalid email address."))
|
raise JsonableError(_("Invalid email address."))
|
||||||
|
|
||||||
# Check if the domain has an MX record
|
# Check if the domain has an MX record
|
||||||
|
resolver = dns_resolver.Resolver()
|
||||||
|
resolver.timeout = 3
|
||||||
|
dns_mx_check_successful = False
|
||||||
try:
|
try:
|
||||||
records = DNS.mxlookup(contact_email_domain)
|
if resolver.resolve(contact_email_domain, "MX"):
|
||||||
dns_mx_check_successful = True
|
dns_mx_check_successful = True
|
||||||
if not records:
|
except DNSException:
|
||||||
dns_mx_check_successful = False
|
pass
|
||||||
except DNS.Base.ServerError:
|
|
||||||
dns_mx_check_successful = False
|
|
||||||
if not dns_mx_check_successful:
|
if not dns_mx_check_successful:
|
||||||
raise JsonableError(
|
# Check if the A/AAAA exist, for better error reporting
|
||||||
_("{domain} does not exist or is not configured to accept email.").format(
|
try:
|
||||||
domain=contact_email_domain
|
resolver.resolve_name(contact_email_domain)
|
||||||
|
raise JsonableError(
|
||||||
|
_("{domain} is invalid because it does not have any MX records").format(
|
||||||
|
domain=contact_email_domain
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
except DNSException:
|
||||||
|
raise JsonableError(_("{domain} does not exist").format(domain=contact_email_domain))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
validate_uuid(zulip_org_id)
|
validate_uuid(zulip_org_id)
|
||||||
|
|
Loading…
Reference in New Issue