Do you know `hello@gmail.com` is not a valid format?
April 26, 2019 - [validator]
테스트 중에 우연히? 시스템에서 hello@gmail.com
이 유효하지 않은 이메일이라고 오류를 뱉길래 뭐지? 하고 관련 내용을 뜯어보고 깨달은 내용을 정리한다.
처음에 필자는 이 건 당연히 로직의 버그라고 생각을 했었다. 해당 건을 당당히 이슈로 등록하려다가 돌다리도 두들겨 보고 가자는 마음으로 일단 관련 로직을 한 번 확인해 보기로 했다. 현재 진행하는 프로젝트에서 email 검증은 class-validator 에서 제공하는 isEmail()
함수를 사용하고 있었다. 해당 함수는 validator 모듈에서 제공하는 isEmail()
함수였다.
validator 의 테스트케이스에 hello@gmail.com
를 직접 넣고 돌려 보았다.
it.only('should validate email addresses with domain specific validation', () => {
test({
validator: 'isEmail',
args: [{ domain_specific_validation: true }],
valid: [
'foo@bar.com',
'hello@gmail.com',
],
invalid: [
`${repeat('a', 31)}@gmail.com`,
'test@gmail.com',
'test.1@gmail.com',
],
});
});
역시나 아래와 같이 오류가 발생했다. 좋다! 물증 확보!
> validator@10.11.0 test /Users/mac9/project/open-src/validator.js
> mocha --require @babel/register
Validators
1) should validate email addresses with domain specific validation
0 passing (127ms)
1 failing
1) Validators
should validate email addresses with domain specific validation:
Error: validator.isEmail(hello@gmail.com, [object Object]) failed but should have passed
at /Users/mac9/project/open-src/validator.js/test/validators.js:20:15
at Array.forEach (<anonymous>)
at forEach (test/validators.js:13:19)
at Context.test (test/validators.js:107:5)
npm ERR! Test failed. See above for more details.
Process finished with exit code 1
해당 소스를 열어보았다.
// ...
export default function isEmail(str, options) {
assertString(str);
options = merge(options, default_email_options);
// ...
if (options.domain_specific_validation && (lower_domain === 'gmail.com' || lower_domain === 'googlemail.com')) {
/*
Previously we removed dots for gmail addresses before validating.
This was removed because it allows `multiple..dots@gmail.com`
to be reported as valid, but it is not.
Gmail only normalizes single dots, removing them from here is pointless,
should be done in normalizeEmail
*/
user = user.toLowerCase();
// Removing sub-address from username before gmail validation
const username = user.split('+')[0];
// Dots are not included in gmail length restriction
if (!isByteLength(username.replace('.', ''), { min: 6, max: 30 })) {
return false;
}
const user_parts = username.split('.');
for (let i = 0; i < user_parts.length; i++) {
if (!gmailUserPart.test(user_parts[i])) {
return false;
}
}
}
// ...
뭔가 있었다..
{ min: 6, max: 30 }
gmail 만의 특별한 제약이 있었던 것이다. 뜨으..;
validator 의 저 당당한 주간 다운로드 수를 보라
많은 사람들이 쓰는데는 다 이유가 있다. 고민하지 말고 validator 쓰자. 또 쓰자.