Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-email-validator for openSUSE:Factory checked in at 2023-11-23 21:38:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-email-validator (Old) and /work/SRC/openSUSE:Factory/.python-email-validator.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-email-validator" Thu Nov 23 21:38:34 2023 rev:6 rq:1128295 version:2.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-email-validator/python-email-validator.changes 2023-05-26 20:15:09.320148885 +0200 +++ /work/SRC/openSUSE:Factory/.python-email-validator.new.25432/python-email-validator.changes 2023-11-23 21:38:38.155044165 +0100 @@ -1,0 +2,16 @@ +Thu Nov 16 10:02:55 UTC 2023 - Dirk Müller <dmueller@suse.com> + +- update to 2.1.0: + * Python 3.8+ is now required (support for Python 3.7 was + dropped). + * The old `email` field on the returned `ValidatedEmail` + object, which in the previous version was superseded by + `normalized`, will now raise a deprecation warning if used. + See https://stackoverflow.com/q/879173 for strategies to + suppress the DeprecationWarning. + * A `__version__` module attribute is added. + * The email address argument to validate_email is now marked as + positional-only to better reflect the documented usage using + the new Python 3.8 feature. + +------------------------------------------------------------------- Old: ---- email_validator-2.0.0.tar.gz New: ---- email_validator-2.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-email-validator.spec ++++++ --- /var/tmp/diff_new_pack.huSog3/_old 2023-11-23 21:38:38.991074963 +0100 +++ /var/tmp/diff_new_pack.huSog3/_new 2023-11-23 21:38:38.995075110 +0100 @@ -17,9 +17,8 @@ %{?sle15_python_module_pythons} -%define skip_python2 1 Name: python-email-validator -Version: 2.0.0 +Version: 2.1.0 Release: 0 Summary: A robust email syntax and deliverability validation library for Python License: CC0-1.0 @@ -30,6 +29,7 @@ Patch0: ignore-urllib3-pyopenssl-warning.patch # PATCH-FIX-OPENSUSE do not require /etc/resolv.conf for testing Patch1: dont-require-resolv-tests.patch +BuildRequires: %{python_module base >= 3.8} BuildRequires: %{python_module dnspython >= 1.15.0} BuildRequires: %{python_module idna >= 2.0.0} BuildRequires: %{python_module pytest >= 5.0} ++++++ email_validator-2.0.0.tar.gz -> email_validator-2.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/.github/workflows/test_and_build.yaml new/python-email-validator-2.1.0/.github/workflows/test_and_build.yaml --- old/python-email-validator-2.0.0/.github/workflows/test_and_build.yaml 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/.github/workflows/test_and_build.yaml 2023-10-22 13:30:59.000000000 +0200 @@ -8,7 +8,7 @@ runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12.0-alpha.5"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12.0"] steps: - uses: actions/checkout@v3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/.travis.yml new/python-email-validator-2.1.0/.travis.yml --- old/python-email-validator-2.0.0/.travis.yml 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -os: linux -dist: bionic -language: python -cache: pip - -python: -- '3.7' -- '3.8' -- '3.9' -- '3.10' -- '3.11' -- '3.12-dev' - -install: -- make install - -script: -- make typing -- make lint -- make test - -after_success: -- bash <(curl -s https://codecov.io/bash) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/CHANGELOG.md new/python-email-validator-2.1.0/CHANGELOG.md --- old/python-email-validator-2.0.0/CHANGELOG.md 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/CHANGELOG.md 2023-10-22 13:30:59.000000000 +0200 @@ -1,3 +1,11 @@ +2.1.0 (October 22, 2023) +------------------------ + +* Python 3.8+ is now required (support for Python 3.7 was dropped). +* The old `email` field on the returned `ValidatedEmail` object, which in the previous version was superseded by `normalized`, will now raise a deprecation warning if used. See https://stackoverflow.com/q/879173 for strategies to suppress the DeprecationWarning. +* A `__version__` module attribute is added. +* The email address argument to validate_email is now marked as positional-only to better reflect the documented usage using the new Python 3.8 feature. + 2.0.0 (April 15, 2023) ---------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/README.md new/python-email-validator-2.1.0/README.md --- old/python-email-validator-2.0.0/README.md 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/README.md 2023-10-22 13:30:59.000000000 +0200 @@ -2,7 +2,7 @@ ========================================= A robust email address syntax and deliverability validation library for -Python 3.7+ by [Joshua Tauberer](https://joshdata.me). +Python 3.8+ by [Joshua Tauberer](https://joshdata.me). This library validates that a string is of the form `name@example.com` and optionally checks that the domain name is set up to receive email. @@ -163,7 +163,7 @@ ### Test addresses -This library rejects email addresess that use the [Special Use Domain Names](https://www.iana.org/assignments/special-use-domain-names/special-use-domain...) `invalid`, `localhost`, `test`, and some others by raising `EmailSyntaxError`. This is to protect your system from abuse: You probably don't want a user to be able to cause an email to be sent to `localhost` (although they might be able to still do so via a malicious MX record). However, in your non-production test environments you may want to use `@test` or `@myname.test` email addresses. There are three ways you can allow this: +This library rejects email addresses that use the [Special Use Domain Names](https://www.iana.org/assignments/special-use-domain-names/special-use-domain...) `invalid`, `localhost`, `test`, and some others by raising `EmailSyntaxError`. This is to protect your system from abuse: You probably don't want a user to be able to cause an email to be sent to `localhost` (although they might be able to still do so via a malicious MX record). However, in your non-production test environments you may want to use `@test` or `@myname.test` email addresses. There are three ways you can allow this: 1. Add `test_environment=True` to the call to `validate_email` (see above). 2. Set `email_validator.TEST_ENVIRONMENT` to `True` globally. @@ -315,6 +315,14 @@ normalized to condensed form. [RFC 2142](https://datatracker.ietf.org/doc/html/rfc2142) also requires lowercase normalization for some specific mailbox names like `postmaster@`. +### Length checks + +This library checks that the length of the email address is not longer than +the maximum length. The check is performed on the normalized form of the +address, which might be different from a string provided by a user. If you +send email to the original string and not the normalized address, the email +might be rejected because the original address could be too long. + Examples -------- @@ -436,14 +444,14 @@ To release: * Update CHANGELOG.md. -* Update the version number in setup.cfg. +* Update the version number in `email_validator/version.py`. * Make & push a commit with the new version number and make sure tests pass. * Make & push a tag (see command below). * Make a release at https://github.com/JoshData/python-email-validator/releases/new. * Publish a source and wheel distribution to pypi (see command below). ```sh -git tag v$(grep version setup.cfg | sed "s/.*= //") +git tag v$(cat email_validator/version.py | sed "s/.* = //" | sed 's/"//g') git push --tags ./release_to_pypi.sh ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/email_validator/__init__.py new/python-email-validator-2.1.0/email_validator/__init__.py --- old/python-email-validator-2.0.0/email_validator/__init__.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/email_validator/__init__.py 2023-10-22 13:30:59.000000000 +0200 @@ -4,12 +4,12 @@ from .exceptions_types import ValidatedEmail, EmailNotValidError, \ EmailSyntaxError, EmailUndeliverableError from .validate_email import validate_email - +from .version import __version__ __all__ = ["validate_email", "ValidatedEmail", "EmailNotValidError", "EmailSyntaxError", "EmailUndeliverableError", - "caching_resolver"] + "caching_resolver", "__version__"] def caching_resolver(*args, **kwargs): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/email_validator/exceptions_types.py new/python-email-validator-2.1.0/email_validator/exceptions_types.py --- old/python-email-validator-2.0.0/email_validator/exceptions_types.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/email_validator/exceptions_types.py 2023-10-22 13:30:59.000000000 +0200 @@ -76,7 +76,13 @@ return self.original if key == "email": return self.normalized - raise AttributeError() + raise AttributeError(key) + + @property + def email(self): + import warnings + warnings.warn("ValidatedEmail.email is deprecated and will be removed, use ValidatedEmail.normalized instead", DeprecationWarning) + return self.normalized """For backwards compatibility, some fields are also exposed through a dict-like interface. Note that some of the names changed when they became attributes.""" @@ -123,9 +129,10 @@ + ",".join("\n {}={}".format( key, repr(getattr(self, key))) - for key in ('email', 'local_part', 'domain', + for key in ('normalized', 'local_part', 'domain', 'ascii_email', 'ascii_local_part', 'ascii_domain', 'smtputf8', 'mx', 'mx_fallback_type') + if hasattr(self, key) ) \ + ")" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/email_validator/syntax.py new/python-email-validator-2.1.0/email_validator/syntax.py --- old/python-email-validator-2.0.0/email_validator/syntax.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/email_validator/syntax.py 2023-10-22 13:30:59.000000000 +0200 @@ -1,7 +1,8 @@ from .exceptions_types import EmailSyntaxError from .rfc_constants import EMAIL_MAX_LENGTH, LOCAL_PART_MAX_LENGTH, DOMAIN_MAX_LENGTH, \ DOT_ATOM_TEXT, DOT_ATOM_TEXT_INTL, ATEXT_RE, ATEXT_INTL_RE, ATEXT_HOSTNAME_INTL, QTEXT_INTL, \ - DNS_LABEL_LENGTH_LIMIT, DOT_ATOM_TEXT_HOSTNAME, DOMAIN_NAME_REGEX, DOMAIN_LITERAL_CHARS + DNS_LABEL_LENGTH_LIMIT, DOT_ATOM_TEXT_HOSTNAME, DOMAIN_NAME_REGEX, DOMAIN_LITERAL_CHARS, \ + QUOTED_LOCAL_PART_ADDR import re import unicodedata @@ -10,6 +11,35 @@ from typing import Optional +def split_email(email): + # Return the local part and domain part of the address and + # whether the local part was quoted as a three-tuple. + + # Typical email addresses have a single @-sign, but the + # awkward "quoted string" local part form (RFC 5321 4.1.2) + # allows @-signs (and escaped quotes) to appear in the local + # part if the local part is quoted. If the address is quoted, + # split it at a non-escaped @-sign and unescape the escaping. + if m := QUOTED_LOCAL_PART_ADDR.match(email): + local_part, domain_part = m.groups() + + # Since backslash-escaping is no longer needed because + # the quotes are removed, remove backslash-escaping + # to return in the normalized form. + import re + local_part = re.sub(r"\\(.)", "\\1", local_part) + + return local_part, domain_part, True + + else: + # Split at the one and only at-sign. + parts = email.split('@') + if len(parts) != 2: + raise EmailSyntaxError("The email address is not valid. It must have exactly one @-sign.") + local_part, domain_part = parts + return local_part, domain_part, False + + def get_length_reason(addr, utf8=False, limit=EMAIL_MAX_LENGTH): """Helper function to return an error message related to invalid length.""" diff = len(addr) - limit @@ -69,8 +99,7 @@ # so if it was originally quoted (quoted_local_part is True) and this regex matches, # it's ok. # (RFC 5321 4.1.2 / RFC 5322 3.2.4). - m = DOT_ATOM_TEXT.match(local) - if m: + if DOT_ATOM_TEXT.match(local): # It's valid. And since it's just the permitted ASCII characters, # it's normalized and safe. If the local part was originally quoted, # the quoting was unnecessary and it'll be returned as normalized to @@ -89,8 +118,7 @@ # RFC 6531 section 3.3. valid: Optional[str] = None requires_smtputf8 = False - m = DOT_ATOM_TEXT_INTL.match(local) - if m: + if DOT_ATOM_TEXT_INTL.match(local): # But international characters in the local part may not be permitted. if not allow_smtputf8: # Check for invalid characters against the non-internationalized @@ -347,8 +375,7 @@ # Check the syntax of the string returned by idna.encode. # It should never fail. - m = DOT_ATOM_TEXT_HOSTNAME.match(ascii_domain) - if not m: + if not DOT_ATOM_TEXT_HOSTNAME.match(ascii_domain): raise EmailSyntaxError("The email address contains invalid characters after the @-sign after IDNA encoding.") # Check the length of the domain name in bytes. @@ -370,7 +397,7 @@ raise EmailSyntaxError(f"After the @-sign, periods cannot be separated by so many characters {reason}.") if globally_deliverable: - # All publicly deliverable addresses have domain named with at least + # All publicly deliverable addresses have domain names with at least # one period, at least for gTLDs created since 2013 (per the ICANN Board # New gTLD Program Committee, https://www.icann.org/en/announcements/details/new-gtld-dotless-domain-names...). # We'll consider the lack of a period a syntax error @@ -431,7 +458,48 @@ } -def validate_email_domain_literal(domain_literal, allow_domain_literal=False): +def validate_email_length(addrinfo): + # If the email address has an ASCII representation, then we assume it may be + # transmitted in ASCII (we can't assume SMTPUTF8 will be used on all hops to + # the destination) and the length limit applies to ASCII characters (which is + # the same as octets). The number of characters in the internationalized form + # may be many fewer (because IDNA ASCII is verbose) and could be less than 254 + # Unicode characters, and of course the number of octets over the limit may + # not be the number of characters over the limit, so if the email address is + # internationalized, we can't give any simple information about why the address + # is too long. + if addrinfo.ascii_email and len(addrinfo.ascii_email) > EMAIL_MAX_LENGTH: + if addrinfo.ascii_email == addrinfo.normalized: + reason = get_length_reason(addrinfo.ascii_email) + elif len(addrinfo.normalized) > EMAIL_MAX_LENGTH: + # If there are more than 254 characters, then the ASCII + # form is definitely going to be too long. + reason = get_length_reason(addrinfo.normalized, utf8=True) + else: + reason = "(when converted to IDNA ASCII)" + raise EmailSyntaxError(f"The email address is too long {reason}.") + + # In addition, check that the UTF-8 encoding (i.e. not IDNA ASCII and not + # Unicode characters) is at most 254 octets. If the addres is transmitted using + # SMTPUTF8, then the length limit probably applies to the UTF-8 encoded octets. + # If the email address has an ASCII form that differs from its internationalized + # form, I don't think the internationalized form can be longer, and so the ASCII + # form length check would be sufficient. If there is no ASCII form, then we have + # to check the UTF-8 encoding. The UTF-8 encoding could be up to about four times + # longer than the number of characters. + # + # See the length checks on the local part and the domain. + if len(addrinfo.normalized.encode("utf8")) > EMAIL_MAX_LENGTH: + if len(addrinfo.normalized) > EMAIL_MAX_LENGTH: + # If there are more than 254 characters, then the UTF-8 + # encoding is definitely going to be too long. + reason = get_length_reason(addrinfo.normalized, utf8=True) + else: + reason = "(when encoded in bytes)" + raise EmailSyntaxError(f"The email address is too long {reason}.") + + +def validate_email_domain_literal(domain_literal): # This is obscure domain-literal syntax. Parse it and return # a compressed/normalized address. # RFC 5321 4.1.3 and RFC 5322 3.4.1. @@ -444,8 +512,6 @@ addr = ipaddress.IPv4Address(domain_literal) except ValueError as e: raise EmailSyntaxError(f"The address in brackets after the @-sign is not valid: It is not an IPv4 address ({e}) or is missing an address literal tag.") - if not allow_domain_literal: - raise EmailSyntaxError("A bracketed IPv4 address after the @-sign is not allowed here.") # Return the IPv4Address object and the domain back unchanged. return { @@ -459,8 +525,6 @@ addr = ipaddress.IPv6Address(domain_literal[5:]) except ValueError as e: raise EmailSyntaxError(f"The IPv6 address in brackets after the @-sign is not valid ({e}).") - if not allow_domain_literal: - raise EmailSyntaxError("A bracketed IPv6 address after the @-sign is not allowed here.") # Return the IPv6Address object and construct a normalized # domain literal. @@ -469,6 +533,8 @@ "domain": f"[IPv6:{addr.compressed}]", } + # Nothing else is valid. + if ":" not in domain_literal: raise EmailSyntaxError("The part after the @-sign in brackets is not an IPv4 address and has no address literal tag.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/email_validator/validate_email.py new/python-email-validator-2.1.0/email_validator/validate_email.py --- old/python-email-validator-2.0.0/email_validator/validate_email.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/email_validator/validate_email.py 2023-10-22 13:30:59.000000000 +0200 @@ -1,14 +1,14 @@ from typing import Optional, Union from .exceptions_types import EmailSyntaxError, ValidatedEmail -from .syntax import validate_email_local_part, validate_email_domain_name, validate_email_domain_literal, get_length_reason -from .rfc_constants import EMAIL_MAX_LENGTH, QUOTED_LOCAL_PART_ADDR, CASE_INSENSITIVE_MAILBOX_NAMES +from .syntax import split_email, validate_email_local_part, validate_email_domain_name, validate_email_domain_literal, validate_email_length +from .rfc_constants import CASE_INSENSITIVE_MAILBOX_NAMES def validate_email( email: Union[str, bytes], - # /, # not supported in Python 3.6, 3.7 - *, + /, # prior arguments are positional-only + *, # subsequent arguments are keyword-only allow_smtputf8: Optional[bool] = None, allow_empty_local: bool = False, allow_quoted_local: Optional[bool] = None, @@ -20,9 +20,9 @@ dns_resolver: Optional[object] = None ) -> ValidatedEmail: """ - Validates an email address, raising an EmailNotValidError if the address is not valid or returning a dict of - information when the address is valid. The email argument can be a str or a bytes instance, - but if bytes it must be ASCII-only. This is the main method of this library. + Given an email address, and some options, returns a ValidatedEmail instance + with information about the address if it is valid or, if the address is not + valid, raises an EmailNotValidError. This is the main function of the module. """ # Fill in default values of arguments. @@ -52,27 +52,13 @@ except ValueError: raise EmailSyntaxError("The email address is not valid ASCII.") - # Typical email addresses have a single @-sign, but the - # awkward "quoted string" local part form (RFC 5321 4.1.2) - # allows @-signs (and escaped quotes) to appear in the local - # part if the local part is quoted. If the address is quoted, - # split it at a non-escaped @-sign and unescape the escaping. - quoted_local_part = False - m = QUOTED_LOCAL_PART_ADDR.match(email) - if m: - quoted_local_part = True - local_part, domain_part = m.groups() - - # Remove backslashes. - import re - local_part = re.sub(r"\\(.)", "\\1", local_part) - - else: - # Split at the one and only at-sign. - parts = email.split('@') - if len(parts) != 2: - raise EmailSyntaxError("The email address is not valid. It must have exactly one @-sign.") - local_part, domain_part = parts + # Split the address into the local part (before the @-sign) + # and the domain part (after the @-sign). Normally, there + # is only one @-sign. But the awkward "quoted string" local + # part form (RFC 5321 4.1.2) allows @-signs in the local + # part if the local part is quoted. + local_part, domain_part, is_quoted_local_part \ + = split_email(email) # Collect return values in this instance. ret = ValidatedEmail() @@ -85,13 +71,17 @@ local_part_info = validate_email_local_part(local_part, allow_smtputf8=allow_smtputf8, allow_empty_local=allow_empty_local, - quoted_local_part=quoted_local_part) - if quoted_local_part and not allow_quoted_local: - raise EmailSyntaxError("Quoting the part before the @-sign is not allowed here.") + quoted_local_part=is_quoted_local_part) ret.local_part = local_part_info["local_part"] ret.ascii_local_part = local_part_info["ascii_local_part"] ret.smtputf8 = local_part_info["smtputf8"] + # If a quoted local part isn't allowed but is present, now raise an exception. + # This is done after any exceptions raised by validate_email_local_part so + # that mandatory checks have highest precedence. + if is_quoted_local_part and not allow_quoted_local: + raise EmailSyntaxError("Quoting the part before the @-sign is not allowed here.") + # Some local parts are required to be case-insensitive, so we should normalize # to lowercase. # RFC 2142 @@ -108,7 +98,9 @@ elif domain_part.startswith("[") and domain_part.endswith("]"): # Parse the address in the domain literal and get back a normalized domain. - domain_part_info = validate_email_domain_literal(domain_part[1:-1], allow_domain_literal=allow_domain_literal) + domain_part_info = validate_email_domain_literal(domain_part[1:-1]) + if not allow_domain_literal: + raise EmailSyntaxError("A bracketed IP address after the @-sign is not allowed here.") ret.domain = domain_part_info["domain"] ret.ascii_domain = domain_part_info["domain"] # Domain literals are always ASCII. ret.domain_address = domain_part_info["domain_address"] @@ -132,48 +124,12 @@ else: ret.ascii_email = None - # If the email address has an ASCII representation, then we assume it may be - # transmitted in ASCII (we can't assume SMTPUTF8 will be used on all hops to - # the destination) and the length limit applies to ASCII characters (which is - # the same as octets). The number of characters in the internationalized form - # may be many fewer (because IDNA ASCII is verbose) and could be less than 254 - # Unicode characters, and of course the number of octets over the limit may - # not be the number of characters over the limit, so if the email address is - # internationalized, we can't give any simple information about why the address - # is too long. - # - # In addition, check that the UTF-8 encoding (i.e. not IDNA ASCII and not - # Unicode characters) is at most 254 octets. If the addres is transmitted using - # SMTPUTF8, then the length limit probably applies to the UTF-8 encoded octets. - # If the email address has an ASCII form that differs from its internationalized - # form, I don't think the internationalized form can be longer, and so the ASCII - # form length check would be sufficient. If there is no ASCII form, then we have - # to check the UTF-8 encoding. The UTF-8 encoding could be up to about four times - # longer than the number of characters. - # - # See the length checks on the local part and the domain. - if ret.ascii_email and len(ret.ascii_email) > EMAIL_MAX_LENGTH: - if ret.ascii_email == ret.normalized: - reason = get_length_reason(ret.ascii_email) - elif len(ret.normalized) > EMAIL_MAX_LENGTH: - # If there are more than 254 characters, then the ASCII - # form is definitely going to be too long. - reason = get_length_reason(ret.normalized, utf8=True) - else: - reason = "(when converted to IDNA ASCII)" - raise EmailSyntaxError(f"The email address is too long {reason}.") - if len(ret.normalized.encode("utf8")) > EMAIL_MAX_LENGTH: - if len(ret.normalized) > EMAIL_MAX_LENGTH: - # If there are more than 254 characters, then the UTF-8 - # encoding is definitely going to be too long. - reason = get_length_reason(ret.normalized, utf8=True) - else: - reason = "(when encoded in bytes)" - raise EmailSyntaxError(f"The email address is too long {reason}.") + # Check the length of the address. + validate_email_length(ret) if check_deliverability and not test_environment: # Validate the email address's deliverability using DNS - # and update the return dict with metadata. + # and update the returned ValidatedEmail object with metadata. if is_domain_literal: # There is nothing to check --- skip deliverability checks. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/email_validator/version.py new/python-email-validator-2.1.0/email_validator/version.py --- old/python-email-validator-2.0.0/email_validator/version.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-email-validator-2.1.0/email_validator/version.py 2023-10-22 13:30:59.000000000 +0200 @@ -0,0 +1 @@ +__version__ = "2.1.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/setup.cfg new/python-email-validator-2.1.0/setup.cfg --- old/python-email-validator-2.0.0/setup.cfg 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/setup.cfg 2023-10-22 13:30:59.000000000 +0200 @@ -1,6 +1,6 @@ [metadata] name = email_validator -version = 2.0.0.post2 +version = attr: email_validator.version.__version__ description = A robust email address syntax and deliverability validation library. long_description = file: README.md long_description_content_type = text/markdown @@ -14,11 +14,11 @@ Intended Audience :: Developers License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 Topic :: Software Development :: Libraries :: Python Modules keywords = email address validator diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/test_requirements.txt new/python-email-validator-2.1.0/test_requirements.txt --- old/python-email-validator-2.0.0/test_requirements.txt 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/test_requirements.txt 2023-10-22 13:30:59.000000000 +0200 @@ -1,5 +1,5 @@ # This file was generated by running: -# sudo docker run --rm -it --network=host python:3.7-slim /bin/bash +# sudo docker run --rm -it --network=host python:3.8-slim /bin/bash # pip install dnspython idna # from setup.cfg # pip install pytest pytest-cov coverage flake8 mypy # pip freeze @@ -7,24 +7,20 @@ # the earliest Python version we support, and some exception # messages may depend on package versions, so we pin versions # for reproducible testing.) -attrs==22.2.0 -coverage==7.2.1 -dnspython==2.3.0 -exceptiongroup==1.1.0 -flake8==5.0.4 +coverage==7.3.2 +dnspython==2.4.2 +exceptiongroup==1.1.3 +flake8==6.1.0 idna==3.4 -importlib-metadata==4.2.0 iniconfig==2.0.0 mccabe==0.7.0 -mypy==1.0.1 +mypy==1.6.1 mypy-extensions==1.0.0 -packaging==23.0 -pluggy==1.0.0 -pycodestyle==2.9.1 -pyflakes==2.5.0 -pytest==7.2.1 -pytest-cov==4.0.0 +packaging==23.2 +pluggy==1.3.0 +pycodestyle==2.11.1 +pyflakes==3.1.0 +pytest==7.4.2 +pytest-cov==4.1.0 tomli==2.0.1 -typed-ast==1.5.4 -typing_extensions==4.5.0 -zipp==3.15.0 +typing_extensions==4.8.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/tests/test_main.py new/python-email-validator-2.1.0/tests/test_main.py --- old/python-email-validator-2.0.0/tests/test_main.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/tests/test_main.py 2023-10-22 13:30:59.000000000 +0200 @@ -58,3 +58,10 @@ input_email = "testaddr中example.tld".encode("utf32") with pytest.raises(EmailSyntaxError): validate_email(input_email, check_deliverability=False) + + +def test_deprecation(): + input_email = b"testaddr@example.tld" + valid_email = validate_email(input_email, check_deliverability=False) + with pytest.deprecated_call(): + assert valid_email.email is not None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-email-validator-2.0.0/tests/test_syntax.py new/python-email-validator-2.1.0/tests/test_syntax.py --- old/python-email-validator-2.0.0/tests/test_syntax.py 2023-04-19 23:04:26.000000000 +0200 +++ new/python-email-validator-2.1.0/tests/test_syntax.py 2023-10-22 13:30:59.000000000 +0200 @@ -78,8 +78,12 @@ assert emailinfo == output assert validate_email(email_input, check_deliverability=False, allow_smtputf8=True) == output - # Check that the old way to access the normalized form still works. - assert emailinfo.email == emailinfo.normalized + # Check that the old `email` attribute to access the normalized form still works + # if the DeprecationWarning is suppressed. + import warnings + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + assert emailinfo.email == emailinfo.normalized @pytest.mark.parametrize( @@ -326,9 +330,9 @@ ('me@xn--0.tld', 'The part after the @-sign is not valid IDNA (Invalid A-label).'), ('me@yy--0.tld', 'An email address cannot have two letters followed by two dashes immediately after the @-sign or after a period, except Punycode.'), ('me@yy--0.tld', 'An email address cannot have two letters followed by two dashes immediately after the @-sign or after a period, except Punycode.'), - ('me@[127.0.0.1]', 'A bracketed IPv4 address after the @-sign is not allowed here.'), + ('me@[127.0.0.1]', 'A bracketed IP address after the @-sign is not allowed here.'), ('me@[127.0.0.999]', 'The address in brackets after the @-sign is not valid: It is not an IPv4 address (Octet 999 (> 255) not permitted in \'127.0.0.999\') or is missing an address literal tag.'), - ('me@[IPv6:::1]', 'A bracketed IPv6 address after the @-sign is not allowed here.'), + ('me@[IPv6:::1]', 'A bracketed IP address after the @-sign is not allowed here.'), ('me@[IPv6:::G]', 'The IPv6 address in brackets after the @-sign is not valid (Only hex digits permitted in \'G\' in \'::G\').'), ('me@[tag:text]', 'The part after the @-sign contains an invalid address literal tag in brackets.'), ('me@[untaggedtext]', 'The part after the @-sign in brackets is not an IPv4 address and has no address literal tag.'),