email_domain_checker 0.1.2 → 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: 9482f21ae74333979292271bf830aa22164a859388ba73b29a090118185ac797
4
- data.tar.gz: 12fa14a045d73af82ff4d179c55d9f7c425ec25a1bc171d3328e60f5045f92de
3
+ metadata.gz: d7d1c8736541f32688216d1be03172bdbf164cafa12cc5931b9e90d1f95a166c
4
+ data.tar.gz: df42fd8b8797538a77885ceee8c86090b3f13c6b8aebe1cc1549fcf9419af028
5
5
  SHA512:
6
- metadata.gz: ab00a7b94993e50f3e5e8c4b7d7fa74c270a77778c4bd7c5796f84420fe1ffb0c929ec3efa4999d573ba38325e431cca20359e55dcfe68d4b73f67367f57a92d
7
- data.tar.gz: 7a1f651e88f540389f8d213e381a37047c96370d3ff2bb1b4bd8a3655045ac9bb9cf749695ca8c774d2cca38050028e11468f181c883ff6b391abaf57f1d544a
6
+ metadata.gz: 993384db88d74403bb501a6bbfd142f965341e798acdd10689eb0577f1f4b5ac93759eab7b93c8e3cd79378229f4c621e1bad0fc9c5102e357f1f2a65f2d22ce
7
+ data.tar.gz: 65091702811323fb963866fa603f04fc0c998bea62d261f2645cf3b4304dad85693af2ea991d74372bdb8ac85c8cee024d5fc00754ab71ae4beb1461811a4a1b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
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
+
18
+ ## [0.1.3] - 2025-11-06
19
+
20
+ ### Added
21
+ - DNS validation result caching functionality with memory and Redis adapters, custom adapter support, and Rails-style `cache.with` method ([#7](https://github.com/tatematsu-k/email_domain_checker/pull/7))
22
+
23
+ ### Documentation
24
+ - Added comprehensive documentation site with MkDocs including installation guide, usage examples, configuration options, and ActiveModel integration documentation
25
+
8
26
  ## [0.1.2] - 2025-11-05
9
27
 
10
28
  ### Added
data/README.md CHANGED
@@ -18,9 +18,7 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install email_domain_checker
20
20
 
21
- ## Usage
22
-
23
- ### Module-level convenience methods
21
+ ## Quick Start
24
22
 
25
23
  ```ruby
26
24
  require 'email_domain_checker'
@@ -28,137 +26,54 @@ require 'email_domain_checker'
28
26
  # Quick validation
29
27
  EmailDomainChecker.valid?("user@example.com", validate_domain: false) # => true
30
28
 
31
- # Format validation only
32
- EmailDomainChecker.format_valid?("user@example.com") # => true
33
-
34
- # Domain validation only
29
+ # Domain validation with MX records
35
30
  EmailDomainChecker.domain_valid?("user@example.com", check_mx: true) # => true/false
36
31
 
37
32
  # Normalize email
38
33
  EmailDomainChecker.normalize("User@Example.COM") # => "user@example.com"
39
-
40
- # Configure default options globally
41
- EmailDomainChecker.configure(timeout: 10, check_mx: true)
42
-
43
- # Enable test mode (skips DNS checks)
44
- EmailDomainChecker.configure do |config|
45
- config.test_mode = true
46
- end
47
34
  ```
48
35
 
49
- ### Using Checker class
50
-
51
- ```ruby
52
- require 'email_domain_checker'
53
-
54
- # Basic validation
55
- checker = EmailDomainChecker::Checker.new("user@example.com")
56
- if checker.valid?
57
- puts "Valid email with valid domain"
58
- end
36
+ ## Documentation
59
37
 
60
- # Check format only
61
- checker = EmailDomainChecker::Checker.new("user@example.com", validate_domain: false)
62
- checker.format_valid? # => true
38
+ 📖 **[Full Documentation](https://tatematsu-k.github.io/email_domain_checker/latest/)** - Complete usage guide, API reference, and examples
63
39
 
64
- # Check domain with MX records
65
- checker = EmailDomainChecker::Checker.new("user@example.com", check_mx: true)
66
- checker.domain_valid? # => true if MX records exist
40
+ ## Features
67
41
 
68
- # Get normalized email
69
- checker = EmailDomainChecker::Checker.new("User@Example.COM")
70
- checker.normalized_email # => "user@example.com"
42
+ - Email format validation
43
+ - Domain existence validation
44
+ - MX record checking
45
+ - ✅ A record checking
46
+ - ✅ Email normalization
47
+ - ✅ ActiveModel/ActiveRecord integration
48
+ - ✅ DNS result caching (memory and Redis)
49
+ - ✅ Test mode for development
71
50
 
72
- # Get canonical email
73
- checker = EmailDomainChecker::Checker.new("user.name+tag@gmail.com")
74
- checker.canonical_email # => "username@gmail.com"
75
-
76
- # Get redacted email (for privacy)
77
- checker = EmailDomainChecker::Checker.new("user@example.com")
78
- checker.redacted_email # => "{hash}@example.com"
79
- ```
80
-
81
- ### ActiveModel/ActiveRecord Integration
82
-
83
- When ActiveModel is available, you can use the `DomainCheckValidator` for easy validation and normalization in your models:
84
-
85
- ```ruby
86
- class User < ActiveRecord::Base
87
- validates :email, domain_check: { check_mx: true, timeout: 3 }, normalize: true
88
- end
89
- ```
90
-
91
- #### Options
92
-
93
- - `domain_check`: Hash of options for domain validation
94
- - `check_mx`: Check MX records (default: `true`)
95
- - `check_a`: Check A records (default: `false`)
96
- - `timeout`: DNS query timeout in seconds (default: `5`)
97
- - `validate_format`: Validate email format (default: `true`)
98
- - `validate_domain`: Validate domain (default: `true`)
99
- - `normalize`: Normalize email before validation (default: `false`)
100
- - `message`: Custom error message
51
+ ## Development
101
52
 
102
- #### Examples
53
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
103
54
 
104
- ```ruby
105
- # Basic validation with domain check
106
- class User < ActiveRecord::Base
107
- validates :email, domain_check: { check_mx: true, timeout: 3 }
108
- end
109
-
110
- # Format validation only (skip domain check)
111
- class User < ActiveRecord::Base
112
- validates :email, domain_check: { validate_domain: false }
113
- end
114
-
115
- # With automatic normalization
116
- class User < ActiveRecord::Base
117
- validates :email, domain_check: { check_mx: true }, normalize: true
118
- end
119
-
120
- # With custom error message
121
- class User < ActiveRecord::Base
122
- validates :email, domain_check: { check_mx: true }, message: "Invalid email address"
123
- end
124
- ```
55
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
125
56
 
126
- ### Configuration Options
57
+ ### Building Documentation Locally
127
58
 
128
- - `validate_format`: Validate email format using email_address gem (default: true)
129
- - `validate_domain`: Validate domain existence (default: true)
130
- - `check_mx`: Check MX records for domain (default: true)
131
- - `check_a`: Check A records for domain (default: false)
132
- - `timeout`: DNS lookup timeout in seconds (default: 5)
133
- - `test_mode`: Skip DNS checks (useful for testing with dummy data) (default: false)
59
+ To build and preview the documentation locally:
134
60
 
135
- ### Test Mode
61
+ ```bash
62
+ # Install Python dependencies
63
+ pip install -r requirements.txt
136
64
 
137
- When writing tests, you may want to skip DNS checks to avoid external requests. Enable test mode to skip all DNS validations (MX and A record checks):
65
+ # Start development server (with live reload)
66
+ mkdocs serve
138
67
 
139
- ```ruby
140
- # In spec_helper.rb or test_helper.rb
141
- EmailDomainChecker.configure do |config|
142
- config.test_mode = true
143
- end
144
-
145
- # Or in a before block
146
- before do
147
- EmailDomainChecker::Config.test_mode = true
148
- end
68
+ # Build static site
69
+ mkdocs build
149
70
  ```
150
71
 
151
- When test mode is enabled, domain validation will always return `true` without making any DNS requests, allowing you to use dummy email addresses in your tests without external dependencies.
152
-
153
- ## Development
154
-
155
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
156
-
157
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
72
+ The documentation will be available at `http://127.0.0.1:8000` when using `mkdocs serve`. The built files will be in the `site/` directory when using `mkdocs build`.
158
73
 
159
74
  ## Contributing
160
75
 
161
- Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/email_domain_checker.
76
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tatematsu-k/email_domain_checker.
162
77
 
163
78
  ## License
164
79
 
@@ -0,0 +1,165 @@
1
+ # Cache Configuration
2
+
3
+ DNS validation results are cached by default using in-memory storage to improve performance when validating the same domains multiple times. The cache supports both in-memory storage (default) and Redis (optional).
4
+
5
+ !!! note "Production Recommendation"
6
+ While memory cache is enabled by default and works well for development and small applications, we recommend using Redis cache in production environments for better scalability, persistence across application restarts, and shared cache across multiple application instances.
7
+
8
+ ## Memory Cache (Default - Enabled by Default)
9
+
10
+ Cache is enabled by default - no configuration needed. Just use EmailDomainChecker normally and DNS results will be cached.
11
+
12
+ ### Customize Cache TTL
13
+
14
+ ```ruby
15
+ EmailDomainChecker.configure do |config|
16
+ config.cache_ttl = 1800 # Cache entries expire after 30 minutes
17
+ end
18
+ ```
19
+
20
+ ### Disable Cache
21
+
22
+ ```ruby
23
+ EmailDomainChecker.configure do |config|
24
+ config.cache_enabled = false
25
+ end
26
+ ```
27
+
28
+ ## Redis Cache (Recommended for Production)
29
+
30
+ For production environments, Redis cache is recommended for the following reasons:
31
+
32
+ - **Persistence**: Cache survives application restarts
33
+ - **Scalability**: Shared cache across multiple application instances
34
+ - **Performance**: Better memory management for large-scale applications
35
+ - **Reliability**: Handles cache eviction and expiration more efficiently
36
+
37
+ ### Setup
38
+
39
+ First, add the `redis` gem to your Gemfile:
40
+
41
+ ```ruby
42
+ gem 'redis'
43
+ ```
44
+
45
+ Then configure:
46
+
47
+ ```ruby
48
+ # Enable Redis cache
49
+ EmailDomainChecker.configure do |config|
50
+ config.cache_enabled = true
51
+ config.cache_type = :redis
52
+ config.cache_ttl = 3600
53
+ config.redis_client = Redis.new(url: "redis://localhost:6379")
54
+ end
55
+ ```
56
+
57
+ !!! tip "Fallback Behavior"
58
+ If Redis is not available, the gem will automatically fall back to memory cache.
59
+
60
+ ## Cache Management
61
+
62
+ ### Clear All Cache
63
+
64
+ ```ruby
65
+ # Clear all cached DNS validation results
66
+ EmailDomainChecker.clear_cache
67
+ ```
68
+
69
+ ### Clear Cache for Specific Domain
70
+
71
+ ```ruby
72
+ # Clear cache for a specific domain
73
+ EmailDomainChecker.clear_cache_for_domain("example.com")
74
+ ```
75
+
76
+ ### Cache Keys
77
+
78
+ Cache keys are automatically managed by the gem:
79
+
80
+ - MX records: `mx:example.com`
81
+ - A records: `a:example.com`
82
+
83
+ ## Using `with` Method (Rails-style Cache Interface)
84
+
85
+ The cache adapters support a Rails-like `with` method (similar to `Rails.cache.fetch`) for convenient cache access. Cache is enabled by default, so you can use it immediately:
86
+
87
+ ```ruby
88
+ # Method 1: Direct access via EmailDomainChecker.cache (recommended)
89
+ result = EmailDomainChecker.cache.with("my_key", ttl: 3600) do
90
+ # This block executes only when cache misses
91
+ expensive_computation
92
+ end
93
+
94
+ # Method 2: Using convenience method
95
+ result = EmailDomainChecker.with_cache("my_key", ttl: 3600) do
96
+ expensive_computation
97
+ end
98
+
99
+ # Force cache refresh
100
+ result = EmailDomainChecker.cache.with("my_key", force: true) do
101
+ # This block always executes
102
+ updated_computation
103
+ end
104
+
105
+ # Or using convenience method
106
+ result = EmailDomainChecker.with_cache("my_key", force: true) do
107
+ updated_computation
108
+ end
109
+ ```
110
+
111
+ ## Custom Cache Adapter
112
+
113
+ You can implement your own cache adapter by inheriting from `EmailDomainChecker::Cache::BaseAdapter`:
114
+
115
+ ```ruby
116
+ # Define a custom cache adapter
117
+ class MyCustomCacheAdapter < EmailDomainChecker::Cache::BaseAdapter
118
+ def initialize
119
+ @store = {} # Your custom storage
120
+ end
121
+
122
+ def get(key)
123
+ # Your custom get logic
124
+ @store[key]
125
+ end
126
+
127
+ def set(key, value, ttl: nil)
128
+ # Your custom set logic
129
+ @store[key] = value
130
+ end
131
+
132
+ def delete(key)
133
+ # Your custom delete logic
134
+ @store.delete(key)
135
+ end
136
+
137
+ def clear
138
+ # Your custom clear logic
139
+ @store.clear
140
+ end
141
+ end
142
+ ```
143
+
144
+ ### Using Custom Adapter Instance
145
+
146
+ ```ruby
147
+ # Use custom adapter instance
148
+ EmailDomainChecker.configure do |config|
149
+ config.cache_enabled = true
150
+ config.cache_adapter_instance = MyCustomCacheAdapter.new
151
+ end
152
+ ```
153
+
154
+ ### Using Custom Adapter Class
155
+
156
+ ```ruby
157
+ # Or use custom adapter class (will be instantiated automatically)
158
+ EmailDomainChecker.configure do |config|
159
+ config.cache_enabled = true
160
+ config.cache_type = MyCustomCacheAdapter
161
+ end
162
+ ```
163
+
164
+ !!! note "Priority"
165
+ When both `cache_adapter_instance` and `cache_type` are set, the instance takes priority.
@@ -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
+