real_world_email_validator 0.1.5
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.
- checksums.yaml +7 -0
- data/lib/real_world_email_validator.rb +96 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b3546d066fdd7ad2ee33ccec9682444dab55bda2848600506f8267b4f9c6e6f3
|
4
|
+
data.tar.gz: 880760435fa006089d41ceaaf928f6c80f148d7ad794375959443eac3a118870
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11e5f65ed6fb1a6ba65ba6a3f6ce962f6a38b9f1338e5d499ad5ab7508b4de90b48c174df36043500ba2fd281edc66fd513b42dc3e328f6122f3c5c6be394f31
|
7
|
+
data.tar.gz: 0b4dce49ed2c08bd71f6aefed3620ae5aaf54ead153520766288d295c0d8b93d2cd39ac19911b7ee2686c311ee9f8115519b93715c585a096d6df8687266f3ab
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model/validator'
|
4
|
+
|
5
|
+
# Email address validator based on RFC 5322, plus own flavors that real world needs
|
6
|
+
# ref: https://tools.ietf.org/html/rfc5322#section-3.4.1
|
7
|
+
class RealWorldEmailValidator < ActiveModel::EachValidator
|
8
|
+
module StringExt
|
9
|
+
refine String do
|
10
|
+
def start_and_end_with?(chars)
|
11
|
+
self.start_with?(chars) && self.end_with?(chars)
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_or_end_with?(chars)
|
15
|
+
self.start_with?(chars) || self.end_with?(chars)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
using RealWorldEmailValidator::StringExt
|
21
|
+
|
22
|
+
def validate_each(record, attribute, value)
|
23
|
+
if value.blank?
|
24
|
+
record.errors.add attribute, :invalid
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
username, domain = value.split('@')
|
29
|
+
|
30
|
+
unless domain.present? && username_valid?(username) && domain_valid?(domain)
|
31
|
+
record.errors.add attribute, :invalid
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Local-part A.K.A username format definition based on RFC 5322.
|
38
|
+
# Any of following characters are allowed basically:
|
39
|
+
# - Uppercase and lowercase alphabetical letters
|
40
|
+
# - Digits 0 to 9
|
41
|
+
# - Printable characters other than letters and digits !#$%&'*+-/=?^_`{|}~
|
42
|
+
# - .(dot)
|
43
|
+
# However, a .(dot) MUST be surrounded by other allowed characters unless whole username is quoted.
|
44
|
+
# e.g.
|
45
|
+
# John.Doe@example.com => OK
|
46
|
+
# John..Doe@example.com => NG
|
47
|
+
# "John..Doe"@example.com => OK
|
48
|
+
#
|
49
|
+
# And we add following validations as own flavor:
|
50
|
+
# - Whitespace is not allowed
|
51
|
+
# - Backslash is not allowed
|
52
|
+
# - Comment, allowed characters surrounded by '(' and ')' is not allowed
|
53
|
+
def username_valid?(username)
|
54
|
+
regex = %r{\A"?([a-zA-Z]|[0-9]|[!#$%&'*+-/=?^_`{|}~]|[.])+"?\z}
|
55
|
+
result = username.match?(regex)
|
56
|
+
|
57
|
+
return result if username.start_and_end_with?('"')
|
58
|
+
return false if username.start_or_end_with?('.') || username.include?('..')
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
# Domain format definition based on RFC 5322.
|
63
|
+
# It must match the requirements for a hostname, which you can imagine of DNS.
|
64
|
+
# It is limited to a length of 63 characters.
|
65
|
+
# Any of following characters are allowed:
|
66
|
+
# - Uppercase and lowercase alphabetical letters
|
67
|
+
# - Digits 0 to 9, however, top-level domain MUST NOT all-numeric
|
68
|
+
# - Hyphen(-), however, it MUST not be the first or last character of the each domain
|
69
|
+
# And we add following validation as own flavor:
|
70
|
+
# - Comment, allowed characters surrounded by '(' and ')' is not allowed
|
71
|
+
# - It MUST contain domains other than top-level
|
72
|
+
def domain_valid?(domain_str)
|
73
|
+
return false if domain_str.length > 63
|
74
|
+
|
75
|
+
domains = domain_str.split('.')
|
76
|
+
top_level = domains[-1]
|
77
|
+
subdomains = domains - [top_level]
|
78
|
+
|
79
|
+
top_level_domain_valid?(top_level) && subdomains_valid?(subdomains)
|
80
|
+
end
|
81
|
+
|
82
|
+
def top_level_domain_valid?(top_level_domain)
|
83
|
+
return false if top_level_domain.start_or_end_with?('-')
|
84
|
+
return false if top_level_domain.match?(/\A([0-9])+\z/)
|
85
|
+
|
86
|
+
top_level_domain.match?(/\A([a-zA-Z]|[0-9]|[-])+\z/)
|
87
|
+
end
|
88
|
+
|
89
|
+
def subdomains_valid?(subdomains)
|
90
|
+
return false if subdomains.empty?
|
91
|
+
|
92
|
+
subdomains.all? do |subdomain|
|
93
|
+
!subdomain.start_or_end_with?('-') && subdomain.match?(/\A([a-zA-Z]|[0-9]|[-])+\z/)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: real_world_email_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- bary822
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Basically based on RFC 5322, with some additional validations so it works
|
42
|
+
on almost all variety of systems.
|
43
|
+
email: hiroto.fukui822@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/real_world_email_validator.rb
|
49
|
+
homepage: https://github.com/bary822/real_world_email_validator
|
50
|
+
licenses:
|
51
|
+
- MIT
|
52
|
+
metadata: {}
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubygems_version: 3.0.3
|
69
|
+
signing_key:
|
70
|
+
specification_version: 4
|
71
|
+
summary: Email address validator that real world needs, for ActiveModel 4+.
|
72
|
+
test_files: []
|