From fea879a809c38ff346e6c7f2f0aeb53705a40f60 Mon Sep 17 00:00:00 2001 From: Sergey Shevchenko Date: Thu, 11 Feb 2021 17:41:21 +0400 Subject: [PATCH 1/3] Add no_smtp argument that allows us to validate only mx records without SMTP request --- tests/test_mx_check.py | 12 +++++++++++- validate_email/mx_check.py | 4 +++- validate_email/validate_email.py | 9 +++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/test_mx_check.py b/tests/test_mx_check.py index a2cde64..b00326f 100644 --- a/tests/test_mx_check.py +++ b/tests/test_mx_check.py @@ -5,8 +5,9 @@ from unittest.mock import Mock, patch from dns.exception import Timeout from validate_email import mx_check as mx_module +from validate_email.email_address import EmailAddress from validate_email.exceptions import DNSTimeoutError, NoValidMXError -from validate_email.mx_check import _get_mx_records +from validate_email.mx_check import _get_mx_records, mx_check class DnsNameStub(object): @@ -62,3 +63,12 @@ class GetMxRecordsTestCase(TestCase): with self.assertRaises(DNSTimeoutError) as exc: _get_mx_records(domain='testdomain3', timeout=10) self.assertTupleEqual(exc.exception.args, ()) + + @patch.object(target=mx_module, attribute='_check_mx_records') + def test_no_smtp_argument(self, check_mx_records_mock): + 'Check correct work of no_smtp argument.' + + self.assertTrue( + mx_check(EmailAddress('test@mail.ru'), debug=False, no_smtp=True) + ) + self.assertEqual(check_mx_records_mock.call_count, 0) diff --git a/validate_email/mx_check.py b/validate_email/mx_check.py index 042e0c3..971e0e4 100644 --- a/validate_email/mx_check.py +++ b/validate_email/mx_check.py @@ -167,7 +167,7 @@ def mx_check( email_address: EmailAddress, debug: bool, from_address: Optional[EmailAddress] = None, helo_host: Optional[str] = None, smtp_timeout: int = 10, - dns_timeout: int = 10 + dns_timeout: int = 10, no_smtp: bool = False ) -> Optional[bool]: """ Return `True` if the host responds with a deliverable response code, @@ -181,6 +181,8 @@ def mx_check( else: mx_records = _get_mx_records( domain=email_address.domain, timeout=dns_timeout) + if no_smtp: + return True return _check_mx_records( mx_records=mx_records, smtp_timeout=smtp_timeout, helo_host=host, from_address=from_address, email_address=email_address, debug=debug) diff --git a/validate_email/validate_email.py b/validate_email/validate_email.py index e25fae0..2fb6dfc 100644 --- a/validate_email/validate_email.py +++ b/validate_email/validate_email.py @@ -13,9 +13,10 @@ LOGGER = getLogger(name=__name__) def validate_email_or_fail( email_address: str, check_regex: bool = True, check_mx: bool = True, - from_address: Optional[str] = None, helo_host: Optional[str] = None, - smtp_timeout: int = 10, dns_timeout: int = 10, - use_blacklist: bool = True, debug: bool = False) -> Optional[bool]: + no_smtp: bool = False, from_address: Optional[str] = None, + helo_host: Optional[str] = None, smtp_timeout: int = 10, + dns_timeout: int = 10, use_blacklist: bool = True, debug: bool = False + ) -> Optional[bool]: """ Return `True` if the email address validation is successful, `None` if the validation result is ambigious, and raise an exception if the validation @@ -37,7 +38,7 @@ def validate_email_or_fail( return mx_check( email_address=email_address, from_address=from_address, helo_host=helo_host, smtp_timeout=smtp_timeout, - dns_timeout=dns_timeout, debug=debug) + dns_timeout=dns_timeout, no_smtp=no_smtp, debug=debug) def validate_email( -- 2.44.0 From 607ae44ce8ba8cd4ec3102b7e8300bd76e3188ad Mon Sep 17 00:00:00 2001 From: Sergey Shevchenko Date: Thu, 11 Feb 2021 17:48:41 +0400 Subject: [PATCH 2/3] Move no_smtp argumeent to the end of arguments list --- validate_email/validate_email.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/validate_email/validate_email.py b/validate_email/validate_email.py index 2fb6dfc..6fb50d8 100644 --- a/validate_email/validate_email.py +++ b/validate_email/validate_email.py @@ -13,9 +13,9 @@ LOGGER = getLogger(name=__name__) def validate_email_or_fail( email_address: str, check_regex: bool = True, check_mx: bool = True, - no_smtp: bool = False, from_address: Optional[str] = None, - helo_host: Optional[str] = None, smtp_timeout: int = 10, - dns_timeout: int = 10, use_blacklist: bool = True, debug: bool = False + from_address: Optional[str] = None, helo_host: Optional[str] = None, + smtp_timeout: int = 10, dns_timeout: int = 10, + use_blacklist: bool = True, debug: bool = False, no_smtp: bool = False, ) -> Optional[bool]: """ Return `True` if the email address validation is successful, `None` if the -- 2.44.0 From 8f08c0152316ff45ce10f1a2c2cb10f24f917055 Mon Sep 17 00:00:00 2001 From: Sergey Shevchenko Date: Thu, 11 Feb 2021 18:48:35 +0400 Subject: [PATCH 3/3] Add no_smtp argument to README --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 258b586..e053779 100644 --- a/README.rst +++ b/README.rst @@ -43,6 +43,8 @@ Basic usage:: :code:`debug`: emit debug/warning messages while checking email +:code:`no_smtp`: not send SMTP HELO requests when checking for an email + The function :code:`validate_email_or_fail()` works exactly like :code:`validate_email`, except that it raises an exception in the case of validation failure instead of returning :code:`False`. The module will try to negotiate a TLS connection with STARTTLS, and silently fall back to an unencrypted SMTP connection if the server doesn't support it. -- 2.44.0