email_domain_checker 0.1.3 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16e187af255690a6a15e34fdfd3d034443ae6d335781f1b499ec0c100da6731b
4
- data.tar.gz: 790adc384696330eadd419fed2cb46ff23fe0f874b59a28d7b74afc0a0bdb37b
3
+ metadata.gz: d7d1c8736541f32688216d1be03172bdbf164cafa12cc5931b9e90d1f95a166c
4
+ data.tar.gz: df42fd8b8797538a77885ceee8c86090b3f13c6b8aebe1cc1549fcf9419af028
5
5
  SHA512:
6
- metadata.gz: fbd0732d8fccc016ca9ff9d302abcdc8e19f8fe2cbf392f671bb726306727cee4f5b0d2393f38736a6f9d1d4ed4db42359df667579eb6f7116d1691723b09115
7
- data.tar.gz: 45cf7b78d7a22cafca5e1b236ea66426c375345acebc48b389d2230fda733d5a353a5e4cb72a18de17cc6bf6f8b21ee5ad532becd3566d010c514fbb262608f8
6
+ metadata.gz: 993384db88d74403bb501a6bbfd142f965341e798acdd10689eb0577f1f4b5ac93759eab7b93c8e3cd79378229f4c621e1bad0fc9c5102e357f1f2a65f2d22ce
7
+ data.tar.gz: 65091702811323fb963866fa603f04fc0c998bea62d261f2645cf3b4304dad85693af2ea991d74372bdb8ac85c8cee024d5fc00754ab71ae4beb1461811a4a1b
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.4] - 2025-11-06
11
+
12
+ ### Added
13
+ - Domain filtering functionality with blacklist, whitelist, and custom checker support ([#13](https://github.com/tatematsu-k/email_domain_checker/pull/13))
14
+ - Support for regex patterns in blacklist and whitelist configurations ([#13](https://github.com/tatematsu-k/email_domain_checker/pull/13))
15
+ - Whitelist precedence over blacklist when both are configured ([#13](https://github.com/tatematsu-k/email_domain_checker/pull/13))
16
+ - Comprehensive domain filtering documentation ([#13](https://github.com/tatematsu-k/email_domain_checker/pull/13))
17
+
10
18
  ## [0.1.3] - 2025-11-06
11
19
 
12
20
  ### Added
@@ -0,0 +1,213 @@
1
+ # Domain Filtering
2
+
3
+ EmailDomainChecker supports domain filtering through blacklist, whitelist, and custom checker functionality. This is useful for blocking disposable email services, restricting domains within organizations, or implementing custom business logic.
4
+
5
+ ## Overview
6
+
7
+ Domain filtering allows you to:
8
+
9
+ - **Block specific domains** using a blacklist
10
+ - **Allow only specific domains** using a whitelist
11
+ - **Implement custom validation logic** using a custom checker function
12
+
13
+ The validation order is:
14
+ 1. Whitelist check (if configured, highest priority)
15
+ 2. Blacklist check
16
+ 3. Custom checker
17
+ 4. DNS validation
18
+
19
+ ## Blacklist
20
+
21
+ The blacklist allows you to reject specific domains. This is useful for blocking disposable email services or known spam domains.
22
+
23
+ ### Basic Usage
24
+
25
+ ```ruby
26
+ EmailDomainChecker.configure do |config|
27
+ config.blacklist_domains = [
28
+ "10minutemail.com",
29
+ "tempmail.com",
30
+ "guerrillamail.com"
31
+ ]
32
+ end
33
+
34
+ # These will be rejected
35
+ EmailDomainChecker.valid?("user@10minutemail.com") # => false
36
+ EmailDomainChecker.valid?("user@tempmail.com") # => false
37
+
38
+ # Other domains will pass (if they pass DNS validation)
39
+ EmailDomainChecker.valid?("user@example.com") # => true/false (depends on DNS)
40
+ ```
41
+
42
+ ### Regex Patterns
43
+
44
+ You can use regex patterns to match multiple domains:
45
+
46
+ ```ruby
47
+ EmailDomainChecker.configure do |config|
48
+ config.blacklist_domains = [
49
+ /.*\.spam\.com$/, # Matches any subdomain of spam.com
50
+ /.*temp.*mail.*/i # Matches domains containing "temp" and "mail" (case-insensitive)
51
+ ]
52
+ end
53
+
54
+ # These will be rejected
55
+ EmailDomainChecker.valid?("user@test.spam.com") # => false
56
+ EmailDomainChecker.valid?("user@another.spam.com") # => false
57
+ EmailDomainChecker.valid?("user@tempmail.com") # => false
58
+ ```
59
+
60
+ ## Whitelist
61
+
62
+ The whitelist allows you to allow only specific domains. When a whitelist is configured, **only** domains matching the whitelist will be allowed (whitelist takes precedence over blacklist).
63
+
64
+ ### Basic Usage
65
+
66
+ ```ruby
67
+ EmailDomainChecker.configure do |config|
68
+ config.whitelist_domains = [
69
+ "example.com",
70
+ "company.com"
71
+ ]
72
+ end
73
+
74
+ # These will be allowed (if they pass DNS validation)
75
+ EmailDomainChecker.valid?("user@example.com") # => true/false (depends on DNS)
76
+ EmailDomainChecker.valid?("user@company.com") # => true/false (depends on DNS)
77
+
78
+ # These will be rejected (not in whitelist)
79
+ EmailDomainChecker.valid?("user@other.com") # => false
80
+ EmailDomainChecker.valid?("user@gmail.com") # => false
81
+ ```
82
+
83
+ ### Regex Patterns
84
+
85
+ You can use regex patterns in whitelists:
86
+
87
+ ```ruby
88
+ EmailDomainChecker.configure do |config|
89
+ config.whitelist_domains = [
90
+ /.*\.company\.com$/, # Matches any subdomain of company.com
91
+ /.*@.*\.edu$/ # Matches any .edu domain
92
+ ]
93
+ end
94
+
95
+ # These will be allowed
96
+ EmailDomainChecker.valid?("user@mail.company.com") # => true/false (depends on DNS)
97
+ EmailDomainChecker.valid?("user@test.company.com") # => true/false (depends on DNS)
98
+ EmailDomainChecker.valid?("user@university.edu") # => true/false (depends on DNS)
99
+ ```
100
+
101
+ ### Whitelist Precedence
102
+
103
+ When both whitelist and blacklist are configured, the whitelist takes precedence:
104
+
105
+ ```ruby
106
+ EmailDomainChecker.configure do |config|
107
+ config.whitelist_domains = ["example.com"]
108
+ config.blacklist_domains = ["example.com"] # Even if in blacklist
109
+ end
110
+
111
+ # Whitelist takes precedence
112
+ EmailDomainChecker.valid?("user@example.com") # => true/false (depends on DNS, but not rejected by blacklist)
113
+ ```
114
+
115
+ ## Custom Domain Checker
116
+
117
+ The custom domain checker allows you to implement your own validation logic. This is useful for integrating with external services or implementing complex business rules.
118
+
119
+ ### Basic Usage
120
+
121
+ ```ruby
122
+ EmailDomainChecker.configure do |config|
123
+ config.domain_checker = lambda do |domain|
124
+ # Return true to allow, false to reject
125
+ domain.length > 5 && !domain.start_with?("test")
126
+ end
127
+ end
128
+
129
+ EmailDomainChecker.valid?("user@allowed.com") # => true/false (depends on checker and DNS)
130
+ EmailDomainChecker.valid?("user@test.com") # => false (rejected by custom checker)
131
+ ```
132
+
133
+ ### Integration with External Services
134
+
135
+ ```ruby
136
+ EmailDomainChecker.configure do |config|
137
+ config.domain_checker = lambda do |domain|
138
+ # Check against disposable email service database
139
+ DisposableEmailService.valid?(domain)
140
+ end
141
+ end
142
+ ```
143
+
144
+ ### Combining with Blacklist
145
+
146
+ ```ruby
147
+ EmailDomainChecker.configure do |config|
148
+ config.blacklist_domains = ["spam.com"]
149
+ config.domain_checker = lambda do |domain|
150
+ # Custom logic: only allow domains longer than 5 characters
151
+ domain.length > 5
152
+ end
153
+ end
154
+
155
+ # Blacklist is checked first
156
+ EmailDomainChecker.valid?("user@spam.com") # => false (rejected by blacklist)
157
+
158
+ # Then custom checker
159
+ EmailDomainChecker.valid?("user@a.com") # => false (rejected by custom checker)
160
+
161
+ # Both checks pass
162
+ EmailDomainChecker.valid?("user@allowed.com") # => true/false (depends on DNS)
163
+ ```
164
+
165
+ ## Use Cases
166
+
167
+ ### Blocking Disposable Email Services
168
+
169
+ ```ruby
170
+ EmailDomainChecker.configure do |config|
171
+ config.blacklist_domains = [
172
+ "10minutemail.com",
173
+ "tempmail.com",
174
+ "guerrillamail.com",
175
+ "mailinator.com",
176
+ /.*temp.*mail.*/i # Catch variations
177
+ ]
178
+ end
179
+ ```
180
+
181
+ ### Enterprise Domain Restriction
182
+
183
+ ```ruby
184
+ EmailDomainChecker.configure do |config|
185
+ config.whitelist_domains = [
186
+ "company.com",
187
+ "partner.com",
188
+ /.*\.company\.com$/ # Allow subdomains
189
+ ]
190
+ end
191
+ ```
192
+
193
+ ### Custom Business Logic
194
+
195
+ ```ruby
196
+ EmailDomainChecker.configure do |config|
197
+ config.domain_checker = lambda do |domain|
198
+ # Check against your internal database
199
+ AllowedDomain.exists?(name: domain) ||
200
+ # Or check against external API
201
+ DomainValidationService.check(domain)
202
+ end
203
+ end
204
+ ```
205
+
206
+ ## Notes
207
+
208
+ - Whitelist takes precedence over blacklist
209
+ - Custom checker is evaluated after blacklist but before DNS validation
210
+ - All checks are case-sensitive for string matches (use regex with `i` flag for case-insensitive matching)
211
+ - Empty arrays are treated as "no filtering" (all domains pass the filter)
212
+ - When whitelist is configured and non-empty, only whitelisted domains can pass
213
+
@@ -26,6 +26,20 @@ When test mode is enabled, domain validation will always return `true` without m
26
26
  - `cache_ttl`: Cache time-to-live in seconds (default: `3600`)
27
27
  - `redis_client`: Custom Redis client instance (only used when `cache_type` is `:redis`)
28
28
 
29
+ ### Domain Filtering Options
30
+
31
+ - `blacklist_domains`: Array of domains to reject (supports strings and regex patterns) (default: `[]`)
32
+ - `whitelist_domains`: Array of domains to allow (supports strings and regex patterns) (default: `[]`)
33
+ - `domain_checker`: Custom domain validation function (Proc/lambda) (default: `nil`)
34
+
35
+ When `whitelist_domains` is configured, only domains matching the whitelist will be allowed (whitelist takes precedence over blacklist).
36
+
37
+ The validation order is:
38
+ 1. Whitelist check (if configured)
39
+ 2. Blacklist check
40
+ 3. Custom checker
41
+ 4. DNS validation
42
+
29
43
  ## Configuration Examples
30
44
 
31
45
  ### Basic Configuration
@@ -63,6 +77,42 @@ EmailDomainChecker.configure do |config|
63
77
  end
64
78
  ```
65
79
 
80
+ ### Blacklist Configuration
81
+
82
+ ```ruby
83
+ EmailDomainChecker.configure do |config|
84
+ config.blacklist_domains = [
85
+ "10minutemail.com",
86
+ "tempmail.com",
87
+ /.*\.spam\.com$/ # Regex patterns are supported
88
+ ]
89
+ end
90
+ ```
91
+
92
+ ### Whitelist Configuration
93
+
94
+ ```ruby
95
+ EmailDomainChecker.configure do |config|
96
+ config.whitelist_domains = [
97
+ "example.com",
98
+ "company.com",
99
+ /.*\.company\.com$/ # Regex patterns are supported
100
+ ]
101
+ end
102
+ ```
103
+
104
+ ### Custom Domain Checker
105
+
106
+ ```ruby
107
+ EmailDomainChecker.configure do |config|
108
+ config.domain_checker = lambda do |domain|
109
+ # Custom validation logic
110
+ # Return true to allow, false to reject
111
+ DisposableEmailService.valid?(domain)
112
+ end
113
+ end
114
+ ```
115
+
66
116
  ## Note on Cache Adapter Priority
67
117
 
68
118
  When both `cache_adapter_instance` and `cache_type` are set, the instance takes priority.
data/docs/index.md CHANGED
@@ -9,6 +9,8 @@ Email address validation and domain checking library to prevent mail server repu
9
9
  - ✅ MX record checking
10
10
  - ✅ A record checking
11
11
  - ✅ Email normalization
12
+ - ✅ Domain blacklist/whitelist
13
+ - ✅ Custom domain checker
12
14
  - ✅ ActiveModel/ActiveRecord integration
13
15
  - ✅ DNS result caching (memory and Redis)
14
16
  - ✅ Test mode for development
@@ -13,7 +13,7 @@ module EmailDomainChecker
13
13
  }.freeze
14
14
 
15
15
  class << self
16
- attr_accessor :default_options, :test_mode, :cache_enabled, :cache_type, :cache_ttl, :cache_adapter, :cache_adapter_instance, :redis_client
16
+ attr_accessor :default_options, :test_mode, :cache_enabled, :cache_type, :cache_ttl, :cache_adapter, :cache_adapter_instance, :redis_client, :blacklist_domains, :whitelist_domains, :domain_checker
17
17
 
18
18
  def configure(options = {}, &block)
19
19
  if block_given?
@@ -36,6 +36,9 @@ module EmailDomainChecker
36
36
  @cache_adapter = nil
37
37
  @cache_adapter_instance = nil
38
38
  @redis_client = nil
39
+ @blacklist_domains = []
40
+ @whitelist_domains = []
41
+ @domain_checker = nil
39
42
  end
40
43
 
41
44
  def test_mode=(value)
@@ -116,7 +119,7 @@ module EmailDomainChecker
116
119
  end
117
120
  end
118
121
 
119
- attr_accessor :test_mode, :cache_enabled, :cache_type, :cache_ttl, :cache_adapter_instance, :redis_client
122
+ attr_accessor :test_mode, :cache_enabled, :cache_type, :cache_ttl, :cache_adapter_instance, :redis_client, :blacklist_domains, :whitelist_domains, :domain_checker
120
123
 
121
124
  def initialize
122
125
  @test_mode = self.class.test_mode || false
@@ -125,6 +128,9 @@ module EmailDomainChecker
125
128
  @cache_ttl = self.class.cache_ttl || 3600
126
129
  @cache_adapter_instance = self.class.cache_adapter_instance
127
130
  @redis_client = self.class.redis_client
131
+ @blacklist_domains = self.class.blacklist_domains || []
132
+ @whitelist_domains = self.class.whitelist_domains || []
133
+ @domain_checker = self.class.domain_checker
128
134
  end
129
135
 
130
136
  def test_mode=(value)
@@ -164,6 +170,21 @@ module EmailDomainChecker
164
170
  self.class.reset_cache_adapter_if_redis
165
171
  end
166
172
 
173
+ def blacklist_domains=(value)
174
+ @blacklist_domains = value || []
175
+ self.class.blacklist_domains = value || []
176
+ end
177
+
178
+ def whitelist_domains=(value)
179
+ @whitelist_domains = value || []
180
+ self.class.whitelist_domains = value || []
181
+ end
182
+
183
+ def domain_checker=(value)
184
+ @domain_checker = value
185
+ self.class.domain_checker = value
186
+ end
187
+
167
188
  reset
168
189
  end
169
190
  end
@@ -20,6 +20,20 @@ module EmailDomainChecker
20
20
  def valid?(domain)
21
21
  return false if domain.nil? || domain.empty?
22
22
 
23
+ # Check whitelist first (if configured)
24
+ unless Config.whitelist_domains.nil? || Config.whitelist_domains.empty?
25
+ return whitelisted?(domain)
26
+ end
27
+
28
+ # Check blacklist
29
+ return false if blacklisted?(domain)
30
+
31
+ # Check custom domain checker
32
+ if Config.domain_checker
33
+ custom_result = Config.domain_checker.call(domain)
34
+ return false unless custom_result
35
+ end
36
+
23
37
  # Skip DNS checks if test mode is enabled
24
38
  return true if Config.test_mode?
25
39
 
@@ -28,6 +42,33 @@ module EmailDomainChecker
28
42
 
29
43
  private
30
44
 
45
+ def whitelisted?(domain)
46
+ return false if Config.whitelist_domains.nil? || Config.whitelist_domains.empty?
47
+
48
+ Config.whitelist_domains.any? do |pattern|
49
+ matches_pattern?(domain, pattern)
50
+ end
51
+ end
52
+
53
+ def blacklisted?(domain)
54
+ return false if Config.blacklist_domains.nil? || Config.blacklist_domains.empty?
55
+
56
+ Config.blacklist_domains.any? do |pattern|
57
+ matches_pattern?(domain, pattern)
58
+ end
59
+ end
60
+
61
+ def matches_pattern?(domain, pattern)
62
+ case pattern
63
+ when Regexp
64
+ pattern.match?(domain)
65
+ when String
66
+ pattern == domain
67
+ else
68
+ false
69
+ end
70
+ end
71
+
31
72
  def check_domain_records(domain)
32
73
  if options[:check_mx]
33
74
  return false unless dns_resolver.has_mx_record?(domain)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EmailDomainChecker
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
data/mkdocs.yml CHANGED
@@ -57,6 +57,7 @@ nav:
57
57
  - ActiveModel Integration: usage/activemodel-integration.md
58
58
  - Configuration:
59
59
  - Configuration Options: configuration/options.md
60
+ - Domain Filtering: configuration/domain-filtering.md
60
61
  - Test Mode: configuration/test-mode.md
61
62
  - Cache Configuration: configuration/cache.md
62
63
  - Contributing: contributing.md
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: email_domain_checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koki Tatematsu
@@ -79,6 +79,7 @@ files:
79
79
  - Rakefile
80
80
  - docs-templates/index.html
81
81
  - docs/configuration/cache.md
82
+ - docs/configuration/domain-filtering.md
82
83
  - docs/configuration/options.md
83
84
  - docs/configuration/test-mode.md
84
85
  - docs/contributing.md