-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
80 lines (68 loc) · 2.74 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const domains = require('./domains.json')
const popularDomains = require('./popular-domains.json')
const levenstein = require('./utils')
// Source of the email regexp :
// https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression/201378#201378
// eslint-disable-next-line
const emailReg = /(?:[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])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-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 maxDistance = 3
const defaultOptions = {
whitelist: [],
blacklist: [],
allowFreemail: false,
allowDisposable: false
}
class EmailValidation {
constructor (options = {}) {
this.setOptions(options)
}
check (email) {
const result = {
email,
domain: null,
valid: false,
errors: [],
typo: null
}
if (!email || !emailReg.test(email) || !email.split('@')) {
result.errors.push('invalid')
return result
}
result.email = email.trim().toLowerCase()
result.domain = result.email.split('@').pop()
const type = this.domains[result.domain]
if (type) {
type === 'disposable' && !this.options.allowDisposable && result.errors.push(type)
type === 'freemail' && !this.options.allowFreemail && result.errors.push(type)
type === 'blacklist' && result.errors.push(type)
} else {
let smallestDistance = result.domain.length
for (const domain of popularDomains) {
const distance = levenstein(domain, result.domain)
if (distance > 0 && distance < maxDistance && distance < smallestDistance) {
smallestDistance = distance
const prefix = result.email.split('@').shift()
result.typo = `${prefix}@${domain}`
}
}
}
if (!result.errors.length) result.valid = true
return result
}
whitelist (domain) {
domain = domain.includes('@') ? domain.split('@').pop() : domain
this.domains[domain.trim().toLowerCase()] = 'whitelist'
}
blacklist (domain) {
domain = domain.includes('@') ? domain.split('@').pop() : domain
this.domains[domain.trim().toLowerCase()] = 'blacklist'
}
setOptions (options) {
this.options = Object.assign({}, defaultOptions, options)
this.domains = Object.assign({}, domains,
this.options.whitelist.reduce((o, d) => { o[d] = 'whitelist'; return o }, {}),
this.options.blacklist.reduce((o, d) => { o[d] = 'blacklist'; return o }, {})
)
}
}
module.exports = EmailValidation