@email-utils/validator-syntax 0.0.1-9 → 1.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts DELETED
@@ -1,342 +0,0 @@
1
- // VALID EMAIL
2
- // Attempting to follow rules from https://en.wikipedia.org/wiki/Email_address.
3
- // Checks if the email is valid.
4
- import * as tlds from 'tlds/index.json'
5
- class EmailSyntaxValidator {
6
- defaultConfig: EmailValidatorConfig = {
7
- local: {
8
- alphaUpper: true,
9
- alphaLower: true,
10
- numeric: true,
11
- period: true,
12
- printable: true,
13
- quote: true,
14
- hyphen: true,
15
- spaces: true,
16
- },
17
- domain: {
18
- alphaUpper: true,
19
- alphaLower: true,
20
- numeric: true,
21
- period: true,
22
- hyphen: true,
23
- tld: true,
24
- localhost: false,
25
- charsBeforeDot: 1, // -1 means don't check.
26
- charsAfterDot: 2, // -1 means don't check.
27
- },
28
- }
29
- config: EmailValidatorConfig = this.defaultConfig
30
- chars = {
31
- alphaLower: 'abcdefghijklmnopqrstuvwxyz',
32
- alphaUpper: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
33
- numeric: '0123456789',
34
- dot: ',',
35
- printable: "!#$%&'*+/=?^_`{|}~",
36
- space: ' ',
37
- quote: '"',
38
- hyphen: '-',
39
- period: '.',
40
- }
41
- email = ''
42
- originalEmail = ''
43
-
44
- constructor(configParam: EmailValidatorParam = {} as EmailValidatorParam) {
45
- let key: keyof EmailValidatorConfig
46
-
47
- for (key in configParam) {
48
- const configGroup = configParam[key]
49
- for (const subKey in configGroup) {
50
- const subKeyType = subKey as keyof typeof configGroup
51
- this.config[key][subKeyType] = configGroup[subKeyType]
52
- }
53
- }
54
- }
55
- private gatherChars(
56
- charConfig: LocalValidateConfig | DomainValidateConfig
57
- ): string[] {
58
- let characters = ''
59
-
60
- if (charConfig.alphaUpper === true) {
61
- characters += this.chars.alphaUpper
62
- }
63
- if (charConfig.alphaLower === true) {
64
- characters += this.chars.alphaLower
65
- }
66
- if (charConfig.numeric === true) {
67
- characters += this.chars.numeric
68
- }
69
-
70
- if (charConfig.hyphen === true) {
71
- characters += this.chars.hyphen
72
- }
73
- if ('printable' in charConfig && charConfig.printable === true) {
74
- characters += this.chars.printable
75
- }
76
-
77
- if ('spaces' in charConfig && charConfig.spaces === true) {
78
- characters += this.chars.space
79
- }
80
-
81
- if ('quote' in charConfig && charConfig.quote === true) {
82
- characters += this.chars.quote
83
- }
84
-
85
- if (charConfig.period === true) {
86
- characters += this.chars.period
87
- }
88
-
89
- return characters.split('')
90
- }
91
- private validateGeneral(): boolean {
92
- // Confirm that there is an at symbol and it isn't the first character.
93
- const atSymbolIndex = this.email.indexOf('@')
94
- if (atSymbolIndex < 1) {
95
- return false
96
- }
97
-
98
- return true
99
- }
100
- private validateChars(chars: string[], charsToValidate: string[]): boolean {
101
- let quoteOpen = false
102
- for (let l = 0; l < charsToValidate.length; l++) {
103
- const letter = charsToValidate[l]
104
- if (this.config.local.quote) {
105
- if (letter === '"') {
106
- quoteOpen = !quoteOpen
107
-
108
- if (l !== 0 && l !== charsToValidate.length - 1) {
109
- if (quoteOpen && !(charsToValidate[l - 1] === '.')) {
110
- return false
111
- } else if (!quoteOpen && !(charsToValidate[l + 1] === '.')) {
112
- return false
113
- }
114
- }
115
- }
116
- }
117
-
118
- const letterInAllowed = chars.indexOf(letter) !== -1
119
-
120
- if (!letterInAllowed) {
121
- return false
122
- }
123
- }
124
-
125
- return true
126
- }
127
- private validateLocal(): boolean {
128
- const validChars = this.gatherChars(this.config.local)
129
- let localLetters = this.email.slice(0, this.email.indexOf('@')).split('')
130
-
131
- if (this.config.local.printable) {
132
- const percentInLocalIndex = localLetters.indexOf('%')
133
-
134
- if (percentInLocalIndex !== -1) {
135
- localLetters = localLetters.slice(0, percentInLocalIndex)
136
- }
137
-
138
- const bangInLocalIndex = localLetters.indexOf('!')
139
-
140
- if (bangInLocalIndex !== -1) {
141
- localLetters = localLetters.slice(bangInLocalIndex)
142
- }
143
- }
144
-
145
- // Validate local length
146
- if (localLetters.length > 64) {
147
- return false
148
- }
149
-
150
- const charsValid = this.validateChars(validChars, localLetters)
151
-
152
- if (!charsValid) {
153
- return false
154
- }
155
-
156
- // Make sure there are not two periods together.
157
- const indexOfDoublePeriods = this.email.indexOf('..')
158
-
159
- if (indexOfDoublePeriods !== -1) {
160
- // If double periods before at symbol it's invalid.
161
- const atSymbolIndex = this.email.indexOf('@')
162
- if (indexOfDoublePeriods > atSymbolIndex) {
163
- return false
164
- }
165
-
166
- // If double period is not within quotes.
167
- const indexOfFirstQuoteInLocal = localLetters.indexOf('"')
168
- const indexOfLastQuoteInLocal =
169
- localLetters.length -
170
- `${localLetters}`.split('').reverse().join('').indexOf('"') -
171
- 1
172
-
173
- if (indexOfFirstQuoteInLocal < 0 || indexOfLastQuoteInLocal < 0) {
174
- return false
175
- }
176
-
177
- if (
178
- indexOfFirstQuoteInLocal >= indexOfDoublePeriods ||
179
- indexOfDoublePeriods >= indexOfLastQuoteInLocal
180
- ) {
181
- return false
182
- }
183
- }
184
-
185
- // Confirm that there is no spaces that are not surrounded by quotes.
186
- const indexOfSpace = localLetters.indexOf(' ')
187
-
188
- if (
189
- indexOfSpace !== -1 &&
190
- (localLetters[indexOfSpace + 1] !== '"' ||
191
- localLetters[indexOfSpace - 1] !== '"')
192
- ) {
193
- return false
194
- }
195
-
196
- return true
197
- }
198
- private validateDomainParts(domain: string): boolean {
199
- const dotIndex = domain.lastIndexOf('.')
200
-
201
- if (dotIndex === -1 && this.config.domain.localhost === false) {
202
- return false
203
- }
204
-
205
- if (dotIndex !== -1) {
206
- if (this.config.domain.charsBeforeDot !== -1) {
207
- if (dotIndex <= this.config.domain.charsBeforeDot) {
208
- return false
209
- }
210
- }
211
-
212
- if (this.config.domain.charsAfterDot !== -1) {
213
- if (dotIndex === domain.length - this.config.domain.charsAfterDot) {
214
- return false
215
- }
216
- }
217
-
218
- if (this.config.domain.tld) {
219
- const tld = domain.slice(dotIndex + 1)
220
-
221
- let tldExists = false
222
-
223
- for (let t = 0; t < tlds.length; t++) {
224
- const currentTld = tlds[t]
225
-
226
- if (tld.toLowerCase() === currentTld) {
227
- tldExists = true
228
- }
229
-
230
- if (tldExists) {
231
- break
232
- }
233
- }
234
-
235
- if (!tldExists) {
236
- return false
237
- }
238
- }
239
- }
240
-
241
- return true
242
- }
243
- private validateDomain(): boolean {
244
- // Confirm that there is a dot at least 1 character after the at and 2 characters before the end.
245
- const domain = this.email.slice(this.email.indexOf('@') + 1)
246
-
247
- const domainPartsValid = this.validateDomainParts(domain)
248
-
249
- if (!domainPartsValid) {
250
- return false
251
- }
252
-
253
- const validChars = this.gatherChars(this.config.domain)
254
- const domainLetters = domain.split('')
255
-
256
- if (this.config.local.printable) {
257
- const localLetters = this.email
258
- .slice(0, this.email.indexOf('@'))
259
- .split('')
260
-
261
- const percentInLocalIndex = localLetters.indexOf('%')
262
-
263
- if (percentInLocalIndex !== -1) {
264
- const relayDomain = localLetters.slice(percentInLocalIndex + 1)
265
-
266
- const relayDomainPartsValid = this.validateDomainParts(
267
- relayDomain.join('')
268
- )
269
-
270
- if (!relayDomainPartsValid) {
271
- return false
272
- }
273
-
274
- const charsValid = this.validateChars(validChars, relayDomain)
275
-
276
- if (!charsValid) {
277
- return false
278
- }
279
- }
280
-
281
- const bangInLocalIndex = localLetters.indexOf('!')
282
-
283
- if (bangInLocalIndex !== -1) {
284
- const relayDomain = localLetters.slice(0, bangInLocalIndex)
285
-
286
- const relayDomainPartsValid = this.validateDomainParts(
287
- relayDomain.join('')
288
- )
289
-
290
- if (!relayDomainPartsValid) {
291
- return false
292
- }
293
-
294
- const charsValid = this.validateChars(validChars, relayDomain)
295
-
296
- if (!charsValid) {
297
- return false
298
- }
299
- }
300
- }
301
-
302
- const charsValid = this.validateChars(validChars, domainLetters)
303
-
304
- if (!charsValid) {
305
- return false
306
- }
307
-
308
- return true
309
- }
310
-
311
- public async validate(email: string): Promise<boolean> {
312
- if (typeof email !== 'string') {
313
- console.error('Email not a string.', email)
314
- return false
315
- } else if (!email) {
316
- console.error('Email not provided.', email)
317
- return false
318
- }
319
-
320
- this.email = email
321
- // Need to add support for special local chars that are properly quoted.
322
- // Need to add support for quotes in ().
323
- const generalValid = this.validateGeneral()
324
- if (!generalValid) {
325
- return false
326
- }
327
-
328
- const localValid = this.validateLocal()
329
- if (!localValid) {
330
- return false
331
- }
332
-
333
- const domainValid = this.validateDomain()
334
- if (!domainValid) {
335
- return false
336
- }
337
-
338
- return true
339
- }
340
- }
341
-
342
- export default EmailSyntaxValidator