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. 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..6fb50d8 100644 --- a/validate_email/validate_email.py +++ b/validate_email/validate_email.py @@ -15,7 +15,8 @@ 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]: + 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 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(