Visitar URL original
Version 2.3 breaks a ton of pydantic models and rules · Issue #160 · JoshData/python-email-validator · GitHub
Skip to content

Version 2.3 breaks a ton of pydantic models and rules #160

Description

@canardoFR

This decision will result into a nightmare:
• The library no longer checks that the local part is at most 64 characters because a more careful reading of RFC 5321 indicates the limit is optional and such email addresses have been found in the wild. However the check can be restored using a new strict=True parameter, and the overall 254 character email address length limit is still in place.

All the articles I found on the Internet specifies: 64 before @ and 255 after, with an overall size limited to 254.

Refering to RFC 5321, it reads:
4.5.3.1. Size Limits and Minimums

There are several objects that have required minimum/maximum sizes.
Every implementation MUST be able to receive objects of at least
these sizes. Objects larger than these sizes SHOULD be avoided when
possible. However, some Internet mail constructs such as encoded
X.400 addresses (RFC 2156 [35]) will often require larger objects.
Clients MAY attempt to transmit these, but MUST be prepared for a
server to reject them if they cannot be handled by it. To the
maximum extent possible, implementation techniques that impose no
limits on the length of these objects should be used.

Extensions to SMTP may involve the use of characters that occupy more
than a single octet each. This section therefore specifies lengths
in octets where absolute lengths, rather than character counts, are
intended.

4.5.3.1.1. Local-part

The maximum total length of a user name or other local-part is 64
octets.

4.5.3.1.2. Domain

The maximum total length of a domain name or number is 255 octets.

I do not see any hint about optional.

Also, as a backward compatibility, it would have been better to make the strict parameter a lazy or compat parameter which defaults to True and not False....

Please advice.

Activity

  1. asrenzo commented on Sep 2, 2025

    @asrenzo

    Hi,

    Moreover forcing to use strict=True breaks other existing implementations which rely on localpart being less than 64 (for example pydantic email field).

    I guess reversing the logic would offer both possibilities without breaking anything. Aka strict=True being the default value.

    Updating this way will cause a lot of pain for everyone whereas "issue" is only reported by a single user (see #158).

  2. JoshData commented on Sep 2, 2025

    @JoshData
    Owner

    I do not see any hint about optional.

    It's this:

    "Objects larger than these sizes SHOULD [note: not MUST] be avoided when possible. ... Clients MAY attempt to transmit these,"

  3. asrenzo commented on Sep 2, 2025

    @asrenzo

    4.5.3.1.1 says : The maximum total length of a user name or other local-part is 64 octets.

  4. canardoFR commented on Sep 3, 2025

    @canardoFR
    Author

    Dear Josh,

    as a matter of fact, there are lots of SHALL, SHOULD and MUST.

    Making a breaking change (because it is a beaking change) with no backward compatibility is a nightmare.

    The fact that it's not "optional" also makes the following statement even more relevant than before: MUST be prepared for a
    server to reject them if they cannot be handled by it

    So basically, this change MAY break all message sending with a bounce feature because the local-part may now exceed 64 caracters. ==> a usual return-path mail for bounce feature is written bounce+this-was-the-original_mail=of-my-customer-domain@sending-domain.com
    We filtered out the bounce mail to comply with 64 caracters based on pydantic/email-validator validation feature, now it does not fire, and thus we encounter problems in our mailing system.

    This change should have been made the other way around by:

    • adding a strict paramater
    • set this parameter by default to True
    • for those needing to bypass the local-part length check the ability to pass strict=False

    In the pydantic library, several model for mail adresses rely on email-validator. As such, this change makes software systems/parts incompatible if one uses version 2.3.0 and the other 2.2.0

    Best regards,
    Alain R.

  5. JoshData commented on Sep 3, 2025

    @JoshData
    Owner

    I'm sorry for the inconvenience of having to add ", strict=True" to your calls?

    I have more important things to worry about than convenience.

  6. asrenzo commented on Sep 3, 2025

    @asrenzo

    Hi,

    What is the benefit of merging a feature that may break a lot of things ?

    Imagine a complex architecture in which a first level of apps uses email-validator 2.3 whereas the emailing service is still running with version 2.2. Then allowed emails in front apps will send unacceptable emails deep into the system.

    Your choice of introducing a breaking change requires each and every service or app to update at the same time. This is barely possible.

    If you change your default value from False to True, everything is fine for everyone, and updates may be rolled independently.

    If you don't want to roll back or change False to True, that's your choice. I have no problem with it.

    But if you want to stay with this decision, then you cannot ignore that a minor version update must be compatible with prior versions and is forbidden from introducing breaking changes. This is a matter of fact.

    uv, poetry and other package managers rely on this standard. You cannot ignore it.

    That's my point of view.

  7. JoshData commented on Sep 3, 2025

    @JoshData
    Owner

    "Forbidden", ha. Ok

  8. asrenzo commented on Sep 3, 2025

    @asrenzo

    Forbidden may be way too rude, but using semver notation implies conforming to world wilde accepted rules.
    I guess you already know this website : https://semver.org/

    Here a small abstract of what you can read there.

    1. MAJOR version when you make incompatible API changes
    2. MINOR version when you add functionality in a backward compatible manner
    3. PATCH version when you make backward compatible bug fixes

    That's all.

    I won't argue anymore about this. I will freeze version for now and look for something else.

    Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions