Skip to content

Commit

Permalink
fix: add email validation
Browse files Browse the repository at this point in the history
  • Loading branch information
spaenleh committed Nov 11, 2024
1 parent d9bfc38 commit 884ab65
Show file tree
Hide file tree
Showing 10 changed files with 1,050 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,7 @@ export {
type ChatBotMessage,
GPTVersion,
} from './chatbot/chatbot.js';

export { isEmail } from './validation/isEmail.js';
export { isFQDN } from './validation/isFQDN.js';
export { isIP } from './validation/isIP.js';
40 changes: 40 additions & 0 deletions src/validation/isByteLength.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe } from 'vitest';

import { isByteLength } from './isByteLength.js';
import { testFunc } from './testUtils.js';

describe('isByteLength', () => {
testFunc(
'only min for "%s"',
isByteLength,
{ min: 2 },
{
valid: ['abc', 'de', 'abcd', 'gmail'],
invalid: ['', 'a'],
},
);
testFunc(
'min and max for "%s"',
isByteLength,
{ min: 2, max: 3 },
{ valid: ['abc', 'de', 'g'], invalid: ['', 'a', 'abcd', 'gm'] },
);
testFunc(
'only max for "%s"',
isByteLength,
{ max: 3 },
{
valid: ['abc', 'de', 'g', 'a', ''],
invalid: ['abcd', 'gm'],
},
);
testFunc(
'only max for "%s"',
isByteLength,
{ max: 0 },
{
valid: [''],
invalid: ['g', 'a'],
},
);
});
11 changes: 11 additions & 0 deletions src/validation/isByteLength.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function isByteLength(
str: string,
options?: Partial<{ min: number; max: number }>,
) {
const min = options?.min ?? 0;
const len = encodeURI(str).split(/%..|./).length - 1;
if (typeof options?.max === 'undefined') {
return len >= min;
}
return len >= min && len <= options.max;
}
322 changes: 322 additions & 0 deletions src/validation/isEmail.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
import { describe } from 'vitest';

import { isEmail } from './isEmail.js';
import { testFunc } from './testUtils.js';

describe('isEmail', () => {
testFunc(
'Default options',
isEmail,
{},
{
valid: [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'hans.m端[email protected]',
'hans@m端ller.com',
'test|123@m端ller.com',
'[email protected]',
'[email protected]',
'"foobar"@example.com',
'" foo m端ller "@example.com',
'"foo\\@bar"@example.com',
`${'a'.repeat(64)}@${'a'.repeat(63)}.com`,
`${'a'.repeat(31)}@gmail.com`,
'[email protected]',
'[email protected]',
'[email protected]',
],
invalid: [
'foobar@my_sarisari_store.typepad.com',
'invalidemail@',
'invalid.com',
'@invalid.com',
'[email protected].',
'foo@_bar.com',
'somename@gmail.com',
'[email protected].',
'[email protected]',
'gmailgmailgmailgmailgmail@gmail.com',
`${'a'.repeat(64)}@${'a'.repeat(251)}.com`,
`${'a'.repeat(65)}@${'a'.repeat(250)}.com`,
`${'a'.repeat(64)}@${'a'.repeat(64)}.com`,
`${'a'.repeat(64)}@${'a'.repeat(63)}.${'a'.repeat(63)}.${'a'.repeat(63)}.${'a'.repeat(58)}.com`,
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected] m',
'[email protected]',
'test123+invalid! [email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'wrong()[]",:;<>@@gmail.com',
'"wrong()[]",:;<>@@gmail.com',
'[email protected]�',
'[email protected]©',
'nbsp [email protected]',
'nbsp_test@te st.com',
'[email protected] m',
'"[email protected]',
'"foo"[email protected]',
'foo"bar"@gmail.com',
],
},
);

testFunc(
'Domain specific validation',
isEmail,
{ domainSpecificValidation: true },
{
valid: [
'[email protected]',
'[email protected]',
'[email protected]',
`${'a'.repeat(30)}@gmail.com`,
],
invalid: [
`${'a'.repeat(31)}@gmail.com`,
'[email protected]',
'[email protected]',
'[email protected]',
],
},
);

testFunc(
'Allow underscores',
isEmail,
{ allowUnderscores: true },
{ valid: ['foobar@my_sarisari_store.typepad.com'] },
);

testFunc(
'Allow UTF8 part',
isEmail,
{ allowUtf8LocalPart: false },
{
valid: [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'hans@m端ller.com',
'test|123@m端ller.com',
'[email protected]',
'[email protected]',
'"foobar"@example.com',
'"foo\\@bar"@example.com',
'" foo bar "@example.com',
],
invalid: [
'invalidemail@',
'invalid.com',
'@invalid.com',
'[email protected].',
'[email protected].',
'somename@gmail.com',
'hans.m端[email protected]',
'[email protected]',
'tü[email protected]',
'nbsp [email protected]',
],
},
);

testFunc(
'Allow display name',
isEmail,
{ allowDisplayName: true },
{
valid: [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'hans.m端[email protected]',
'hans@m端ller.com',
'test|123@m端ller.com',
'[email protected]',
'[email protected]',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <hans.m端[email protected]>',
'Some Name <hans@m端ller.com>',
'Some Name <test|123@m端ller.com>',
'Some Name <[email protected]>',
// eslint-disable-next-line quotes
"'Foo Bar, Esq'<[email protected]>",
'Some Name <[email protected]>',
'Some Middle Name <[email protected]>',
'Name <[email protected]>',
'Name<[email protected]>',
'Some Name <[email protected]>',
'Name🍓With🍑Emoji🚴‍♀️🏆<[email protected]>',
'🍇🍗🍑<[email protected]>',
'"<displayNameInBrackets>"<[email protected]>',
'"\\"quotes\\""<[email protected]>',
'"name;"<[email protected]>',
'"name;" <[email protected]>',
],
invalid: [
'invalidemail@',
'invalid.com',
'@invalid.com',
'[email protected].',
'[email protected].',
'Some Name <invalidemail@>',
'Some Name <invalid.com>',
'Some Name <@invalid.com>',
'Some Name <[email protected].>',
'Some Name <[email protected].>',
'Some Name [email protected].>',
'Some Name <[email protected].',
'Some Name < [email protected] >',
'Name [email protected]',
'Some Name <[email protected]>',
'Some Name<emoji_in_address🍈@aftership.com>',
'invisibleCharacter\u001F<[email protected]>',
'<displayNameInBrackets><[email protected]>',
'\\"quotes\\"<[email protected]>',
'""quotes""<[email protected]>',
'name;<[email protected]>',
' <[email protected]>',
'" "<[email protected]>',
],
},
);

testFunc(
'Require display name',
isEmail,
{ requireDisplayName: true },
{
valid: [
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Name <hans.m端[email protected]>',
'Some Name <hans@m端ller.com>',
'Some Name <test|123@m端ller.com>',
'Some Name <[email protected]>',
'Some Name <[email protected]>',
'Some Middle Name <[email protected]>',
'Name <[email protected]>',
'Name<[email protected]>',
],
invalid: [
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
'hans.m端[email protected]',
'hans@m端ller.com',
'test|123@m端ller.com',
'[email protected]',
'invalidemail@',
'invalid.com',
'@invalid.com',
'[email protected].',
'[email protected].',
'Some Name <invalidemail@>',
'Some Name <invalid.com>',
'Some Name <@invalid.com>',
'Some Name <[email protected].>',
'Some Name <[email protected].>',
'Some Name [email protected].>',
'Some Name <[email protected].',
'Some Name < [email protected] >',
'Name [email protected]',
],
},
);

testFunc(
'Allow Ip Domain',
isEmail,
{ allowIpDomain: true },
{
valid: ['email@[123.123.123.123]', '[email protected]'],
invalid: [
'[email protected]',
'[email protected]',
'email@[266.266.266.266]',
],
},
);

testFunc(
'Blacklisted chars',
isEmail,
{ blacklistedChars: 'abc"' },
{
valid: ['[email protected]'],
invalid: [
'[email protected]',
'"foobr"@example.com',
'" foo m端ller "@example.com',
'"foo@br"@example.com',
],
},
);

testFunc(
'Ignore Max length allowed',
isEmail,
{ ignoreMaxLength: true },

{
valid: [
'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@example.com',
],
},
);

testFunc(
'Ignore Max length disallowed',
isEmail,
{ ignoreMaxLength: false },
{
invalid: [
'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@example.com',
'Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX@Deleted-user-id-19430-Team-5051deleted-user-id-19430-team-5051XXXXXX.com',
],
},
);

testFunc(
'Blacklist host',
isEmail,
{ hostBlacklist: ['gmail.com', 'foo.bar.com'] },
{
valid: ['[email protected]'],
invalid: ['[email protected]', '[email protected]'],
},
);

testFunc(
'Whitelist host',
isEmail,
{ hostWhitelist: ['gmail.com', 'foo.bar.com'] },
{
valid: ['[email protected]', '[email protected]'],
invalid: ['[email protected]', '[email protected]', '[email protected]'],
},
);
});
Loading

0 comments on commit 884ab65

Please sign in to comment.