colinhacks / zod

TypeScript-first schema validation with static type inference
https://zod.dev
MIT License
33.08k stars 1.15k forks source link

Email validation broken #2396

Closed timothyarmes closed 4 months ago

timothyarmes commented 1 year ago

Hi,

zod is rejecting valid email addresses of the form a@b.c.com (note the two dots after the @).

mauricedb commented 1 year ago

Same here. And the email in question is actually used to send emails so definitely works. The actual email we are using is more like abcde.abcd+1234567890123@abcdefg.com.test-google-a.com where I replaced letters for other letters etc for privacy.

reminjp commented 1 year ago

2157 (or #2274) should solve this. but not yet merged.

cullylarson commented 1 year ago

Another example of a failing address: a@asdf.ka1.asdf.com. There's something about the number in ka1 that it doesn't like. Same with abc@wer.asd1.com and abc@wer.asd1aa.com

hkroger commented 1 year ago

Is this moving or is there a version that we can downgrade to fix this?

Dimrok commented 1 year ago

Same for first.last@physik.uni-muenchen.de.

Dimrok commented 1 year ago

To give more context, the current implementation favors speed over correctness.

// old version: too slow, didn't support unicode

// from https://stackoverflow.com/a/46181/1550155
// old version: too slow, didn't support unicode
// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
//old email regex
// const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i;
// eslint-disable-next-line
// const emailRegex =
//   /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\])|(\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\.[A-Za-z]{2,})+))$/;
// const emailRegex =
//   /^[a-zA-Z0-9\.\!\#\$\%\&\'\*\+\/\=\?\^\_\`\{\|\}\~\-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
// const emailRegex =
//   /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i;
const emailRegex =
  /^([A-Z0-9_+-]+\.?)*[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i;
// const emailRegex =
//   /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i;

For those who want correctness, a z.string().refine(...) with your chosen regex or validate.js should do the trick.

adamwdennis commented 1 year ago

When will a new release be cut with these changes? @colinhacks

AlexandreBourdeaudhui commented 1 year ago

Hey, same issue here with xxx@xxx.xxx-tech.sncf Have we any ETA for the new release ? Wanna try it 🙌

paradox37 commented 1 year ago

Just got a report from the user that his email is not accepted. Format is email@something.something-email.com. It would be nice for this to be fixed ASAP.

intellix commented 1 year ago

Two emails I'm seeing that are failing and are both valid:

xxxxxxx@students.bcsc.k12.in.us
xxxxxxx@vip.163.com

It's like it hates numbers

micmcgrorty commented 12 months ago

Apostrophes in names are also broken, so if your name is eg O'Reilly and that's in your email address it now fails Zod validation.

DavidTimms commented 11 months ago

@colinhacks I believe this issue is now fixed and the issue can be closed. All of the examples provided in this thread are successfully parsed by Zod 3.22.4.

redbmk commented 7 months ago

@DavidTimms I'm still seeing the issue with apostrophes in 3.22.4

❯ grep version node_modules/zod/package.json
  "version": "3.22.4",
❯ node
Welcome to Node.js v21.5.0.
Type ".help" for more information.
> require('zod').z.string().url().parse("O'Reilly@example.com")
Uncaught:
[
  {
    "validation": "url",
    "code": "invalid_string",
    "message": "Invalid url",
    "path": []
  }
]
    at get error [as error] (/path/to/node_modules/zod/lib/types.js:43:31)
    at ZodString.parse (/path/to/node_modules/zod/lib/types.js:143:22) {
  issues: [
    {
      validation: 'url',
      code: 'invalid_string',
      message: 'Invalid url',
      path: []
    }
  ],
  addIssue: [Function (anonymous)],
  addIssues: [Function (anonymous)],
  name: 'ZodError',
  errors: [
    {
      validation: 'url',
      code: 'invalid_string',
      message: 'Invalid url',
      path: []
    }
  ]
}
seanmacisaac commented 7 months ago

For those wanting apostrophes to work, the patch is very simple and you can see it in my PR. In our application we've applied this via patch-package. One note is that depending on how you bundle if you go the patch-package route you might need to also patch the generated files as well. If you grep for emailRegex in your node_modules/zod you can see the 4 places it shows up.

I would love to get the PR merged here and not have to have the patch, if there is something else I need to do please let me know.

willdspd commented 6 months ago

A possibly related bug: Incorrectly formatted emails with multiple TLD 'dots' are incorrectly passing validation. For example, johndoe@yahoo.co..uk passes validation, which it shouldn't due to .. between co and uk. I'm on version 3.20.5

fuzzypawzz commented 4 months ago

Danish/Swedish letters like ö or ø isn't accepted either. Those are valid to have in emails nowadays (90% sure about this). Example:
someemailwithø@gmail.com

Just want to put it out there. Lmk if I should create a new issue for this :-)

colinhacks commented 4 months ago

I'm closing this since #2157 is the current final word on this. Nearly all the issues with dots and apostrophes have been resolved in Zod 3.22 or 3.23.

@fuzzypawzz Those characters aren't allowed in Gmail which is part of the rationale behind making Zod's email validation quite strict.

Screenshot 2024-05-16 at 1 12 23 PM

fuzzypawzz commented 4 months ago

@colinhacks Sorry for my bad example. It's correct that gmail doesn't allow those letters. However there are email providers that allows those special letters, and it's an issue in Nordic enterprises - you could argue that's it is not a major issue, however we (the corp im working for currently) are not able to use the email validator from Zod, instead we would have to build our own custom validators, because some users are indeed having email addresses with ø for example.

boblitex commented 1 day ago

bob_+.'b@gmail.com also somehow passes zod validation. if I remove the last alphabet, then it doesn't pass, but adding that last 'b' makes it pass somehow