bouncevalidator 0.0.1
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/LICENSE +21 -0
- package/README.md +483 -0
- package/dist/bin/cli.js +2229 -0
- package/dist/index.d.mts +398 -0
- package/dist/index.d.ts +398 -0
- package/dist/index.js +2105 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2041 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 HyScaler(R) - NetTantra Technologies (India) Private Limited
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
# BounceValidator
|
|
2
|
+
|
|
3
|
+
A completely local email validation service for Node.js. An alternative to cloud-based services like ZeroBounce, Bouncify, and Debounce - with zero external API dependencies.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **100% Local** - No external API calls, all validation happens on your machine
|
|
8
|
+
- **Syntax Validation** - RFC 5322 compliant email format validation
|
|
9
|
+
- **DNS/MX Verification** - Verifies domain has valid mail exchange records
|
|
10
|
+
- **SMTP Verification** - Connects to mail servers to verify mailbox existence
|
|
11
|
+
- **Disposable Email Detection** - Identifies temporary/throwaway email addresses
|
|
12
|
+
- **Role Account Detection** - Flags role-based emails (admin@, support@, etc.)
|
|
13
|
+
- **Free Provider Detection** - Identifies emails from free providers (Gmail, Yahoo, etc.)
|
|
14
|
+
- **Typo Suggestions** - Suggests corrections for common domain typos
|
|
15
|
+
- **Catch-All Detection** - Identifies domains that accept all addresses
|
|
16
|
+
- **Bulk Validation** - Process multiple emails with configurable concurrency
|
|
17
|
+
- **DNS Caching** - Improves performance for repeated lookups
|
|
18
|
+
- **CLI & Programmatic API** - Use from command line or as a library
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install bouncevalidator
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or with yarn:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
yarn add bouncevalidator
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### Programmatic Usage
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { validate } from 'bouncevalidator';
|
|
38
|
+
|
|
39
|
+
const result = await validate('user@example.com');
|
|
40
|
+
|
|
41
|
+
console.log(result.isReachable); // 'safe', 'invalid', 'risky', or 'unknown'
|
|
42
|
+
console.log(result.syntax.isValidSyntax); // true/false
|
|
43
|
+
console.log(result.mx.acceptsMail); // true/false
|
|
44
|
+
console.log(result.smtp.isDeliverable); // true/false
|
|
45
|
+
console.log(result.misc.isDisposable); // true/false
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### CLI Usage
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Validate a single email
|
|
52
|
+
npx bouncevalidator user@example.com
|
|
53
|
+
|
|
54
|
+
# Validate with pretty output
|
|
55
|
+
npx bouncevalidator -p user@example.com
|
|
56
|
+
|
|
57
|
+
# Quick validation (skip SMTP)
|
|
58
|
+
npx bouncevalidator -q user@example.com
|
|
59
|
+
|
|
60
|
+
# Validate from file
|
|
61
|
+
npx bouncevalidator -f emails.txt -o results.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API Reference
|
|
65
|
+
|
|
66
|
+
### `validate(email, options?)`
|
|
67
|
+
|
|
68
|
+
Validates a single email address through the full verification pipeline.
|
|
69
|
+
|
|
70
|
+
**Parameters:**
|
|
71
|
+
- `email` (string) - The email address to validate
|
|
72
|
+
- `options` (ValidationOptions) - Optional configuration
|
|
73
|
+
|
|
74
|
+
**Returns:** `Promise<ValidationResult>`
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { validate } from 'bouncevalidator';
|
|
78
|
+
|
|
79
|
+
const result = await validate('user@gmail.com', {
|
|
80
|
+
smtpTimeout: 15000,
|
|
81
|
+
checkGravatar: true
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `validateBulk(emails, options?)`
|
|
86
|
+
|
|
87
|
+
Validates multiple email addresses with configurable concurrency.
|
|
88
|
+
|
|
89
|
+
**Parameters:**
|
|
90
|
+
- `emails` (string[]) - Array of email addresses
|
|
91
|
+
- `options` (BulkValidationOptions) - Optional configuration
|
|
92
|
+
|
|
93
|
+
**Returns:** `Promise<ValidationResult[]>`
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { validateBulk } from 'bouncevalidator';
|
|
97
|
+
|
|
98
|
+
const results = await validateBulk([
|
|
99
|
+
'user1@example.com',
|
|
100
|
+
'user2@example.com',
|
|
101
|
+
'user3@example.com'
|
|
102
|
+
], {
|
|
103
|
+
concurrency: 10,
|
|
104
|
+
onProgress: (completed, total, result) => {
|
|
105
|
+
console.log(`${completed}/${total}: ${result.input} - ${result.isReachable}`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `validateQuick(email)`
|
|
111
|
+
|
|
112
|
+
Quick validation that only checks syntax and MX records (skips SMTP verification).
|
|
113
|
+
|
|
114
|
+
**Parameters:**
|
|
115
|
+
- `email` (string) - The email address to validate
|
|
116
|
+
|
|
117
|
+
**Returns:** `Promise<ValidationResult>`
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { validateQuick } from 'bouncevalidator';
|
|
121
|
+
|
|
122
|
+
const result = await validateQuick('user@example.com');
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Individual Validators
|
|
126
|
+
|
|
127
|
+
You can use individual validators for more control:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import {
|
|
131
|
+
validateSyntax,
|
|
132
|
+
verifyMx,
|
|
133
|
+
verifySmtp,
|
|
134
|
+
checkMisc,
|
|
135
|
+
checkDisposable,
|
|
136
|
+
checkRoleAccount,
|
|
137
|
+
checkFreeProvider
|
|
138
|
+
} from 'bouncevalidator';
|
|
139
|
+
|
|
140
|
+
// Syntax validation only
|
|
141
|
+
const syntax = validateSyntax('user@example.com');
|
|
142
|
+
|
|
143
|
+
// MX verification only
|
|
144
|
+
const mx = await verifyMx('example.com');
|
|
145
|
+
|
|
146
|
+
// Check if domain is disposable
|
|
147
|
+
const isDisposable = checkDisposable('tempmail.com');
|
|
148
|
+
|
|
149
|
+
// Check if email is role-based
|
|
150
|
+
const isRole = checkRoleAccount('admin');
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Utility Functions
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import {
|
|
157
|
+
normalizeEmail,
|
|
158
|
+
extractParts,
|
|
159
|
+
getSuggestion,
|
|
160
|
+
getEmailSuggestion
|
|
161
|
+
} from 'bouncevalidator';
|
|
162
|
+
|
|
163
|
+
// Normalize email
|
|
164
|
+
const normalized = normalizeEmail('User@GMAIL.com'); // 'user@gmail.com'
|
|
165
|
+
|
|
166
|
+
// Extract parts
|
|
167
|
+
const parts = extractParts('user@example.com');
|
|
168
|
+
// { username: 'user', domain: 'example.com' }
|
|
169
|
+
|
|
170
|
+
// Get domain typo suggestion
|
|
171
|
+
const suggestion = getSuggestion('gmial.com'); // 'gmail.com'
|
|
172
|
+
|
|
173
|
+
// Get full email suggestion
|
|
174
|
+
const emailSuggestion = getEmailSuggestion('user@gmial.com');
|
|
175
|
+
// 'user@gmail.com'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Configuration Options
|
|
179
|
+
|
|
180
|
+
### ValidationOptions
|
|
181
|
+
|
|
182
|
+
| Option | Type | Default | Description |
|
|
183
|
+
|--------|------|---------|-------------|
|
|
184
|
+
| `smtpTimeout` | number | 10000 | SMTP connection timeout in milliseconds |
|
|
185
|
+
| `verifySmtp` | boolean | true | Whether to perform SMTP verification |
|
|
186
|
+
| `checkDisposable` | boolean | true | Check for disposable email domains |
|
|
187
|
+
| `checkRoleAccount` | boolean | true | Check for role-based accounts |
|
|
188
|
+
| `checkFreeProvider` | boolean | true | Check for free email providers |
|
|
189
|
+
| `checkGravatar` | boolean | false | Check for Gravatar existence |
|
|
190
|
+
| `heloHost` | string | hostname | Custom HELO/EHLO hostname |
|
|
191
|
+
| `senderAddress` | string | '' | Custom MAIL FROM address |
|
|
192
|
+
| `dnsCacheTtl` | number | 300000 | DNS cache TTL in milliseconds |
|
|
193
|
+
| `useDnsCache` | boolean | true | Whether to use DNS caching |
|
|
194
|
+
| `detectCatchAll` | boolean | true | Detect catch-all domains |
|
|
195
|
+
|
|
196
|
+
### BulkValidationOptions
|
|
197
|
+
|
|
198
|
+
Extends ValidationOptions with:
|
|
199
|
+
|
|
200
|
+
| Option | Type | Default | Description |
|
|
201
|
+
|--------|------|---------|-------------|
|
|
202
|
+
| `concurrency` | number | 5 | Maximum concurrent validations |
|
|
203
|
+
| `delayBetween` | number | 0 | Delay between batches in milliseconds |
|
|
204
|
+
| `onProgress` | function | - | Progress callback function |
|
|
205
|
+
|
|
206
|
+
## ValidationResult Structure
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
interface ValidationResult {
|
|
210
|
+
input: string; // Original email input
|
|
211
|
+
isReachable: Reachability; // 'safe' | 'invalid' | 'risky' | 'unknown'
|
|
212
|
+
|
|
213
|
+
syntax: {
|
|
214
|
+
address: string; // Original address
|
|
215
|
+
domain: string; // Domain part
|
|
216
|
+
username: string; // Local part
|
|
217
|
+
isValidSyntax: boolean; // Syntax validity
|
|
218
|
+
normalizedEmail: string; // Normalized version
|
|
219
|
+
suggestion: string | null; // Typo suggestion
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
mx: {
|
|
223
|
+
acceptsMail: boolean; // Has valid MX records
|
|
224
|
+
records: string[]; // List of MX hostnames
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
smtp: {
|
|
228
|
+
canConnectSmtp: boolean; // Could connect to server
|
|
229
|
+
isDeliverable: boolean; // Mailbox exists
|
|
230
|
+
isCatchAll: boolean; // Domain is catch-all
|
|
231
|
+
error: {
|
|
232
|
+
type: string; // Error type
|
|
233
|
+
message: string; // Error message
|
|
234
|
+
} | null;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
misc: {
|
|
238
|
+
isDisposable: boolean; // Disposable domain
|
|
239
|
+
isRoleAccount: boolean; // Role-based account
|
|
240
|
+
isFreeProvider: boolean; // Free email provider
|
|
241
|
+
gravatarUrl: string | null; // Gravatar URL if exists
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Reachability Status
|
|
247
|
+
|
|
248
|
+
| Status | Description |
|
|
249
|
+
|--------|-------------|
|
|
250
|
+
| `safe` | Email is verified to exist and can receive mail |
|
|
251
|
+
| `invalid` | Email has invalid syntax, domain doesn't exist, or mailbox not found |
|
|
252
|
+
| `risky` | Email might be valid but couldn't be verified (catch-all, greylisted, etc.) |
|
|
253
|
+
| `unknown` | Verification was inconclusive due to server issues |
|
|
254
|
+
|
|
255
|
+
## CLI Reference
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
bouncevalidator - Local email validation service
|
|
259
|
+
|
|
260
|
+
USAGE:
|
|
261
|
+
bouncevalidator [OPTIONS] <email>...
|
|
262
|
+
bouncevalidator -f <file> [OPTIONS]
|
|
263
|
+
|
|
264
|
+
ARGUMENTS:
|
|
265
|
+
<email>... Email addresses to validate
|
|
266
|
+
|
|
267
|
+
OPTIONS:
|
|
268
|
+
-h, --help Show help message
|
|
269
|
+
-v, --version Show version number
|
|
270
|
+
-f, --file <path> Read emails from file (one per line)
|
|
271
|
+
-o, --output <path> Write results to file
|
|
272
|
+
-q, --quick Quick mode (skip SMTP verification)
|
|
273
|
+
-p, --pretty Pretty print JSON output
|
|
274
|
+
--verbose Show detailed progress
|
|
275
|
+
|
|
276
|
+
VALIDATION OPTIONS:
|
|
277
|
+
-t, --timeout <ms> SMTP timeout (default: 10000)
|
|
278
|
+
-c, --concurrency <n> Max concurrent validations (default: 5)
|
|
279
|
+
--no-smtp Skip SMTP verification
|
|
280
|
+
--no-disposable Skip disposable email check
|
|
281
|
+
--no-role Skip role account check
|
|
282
|
+
--no-free-provider Skip free provider check
|
|
283
|
+
--gravatar Check for Gravatar
|
|
284
|
+
|
|
285
|
+
EXIT CODES:
|
|
286
|
+
0 All emails are valid (safe)
|
|
287
|
+
1 One or more emails are invalid
|
|
288
|
+
2 One or more emails are risky or unknown
|
|
289
|
+
3 Error occurred during validation
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Examples
|
|
293
|
+
|
|
294
|
+
### Basic Validation
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { validate } from 'bouncevalidator';
|
|
298
|
+
|
|
299
|
+
async function checkEmail(email: string) {
|
|
300
|
+
const result = await validate(email);
|
|
301
|
+
|
|
302
|
+
if (result.isReachable === 'safe') {
|
|
303
|
+
console.log('Email is valid and deliverable');
|
|
304
|
+
} else if (result.isReachable === 'invalid') {
|
|
305
|
+
console.log('Email is invalid:', result.smtp.error?.message);
|
|
306
|
+
} else {
|
|
307
|
+
console.log('Email status uncertain:', result.isReachable);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Bulk Validation with Progress
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { validateBulk } from 'bouncevalidator';
|
|
316
|
+
import fs from 'fs';
|
|
317
|
+
|
|
318
|
+
async function validateEmailList(filePath: string) {
|
|
319
|
+
const emails = fs.readFileSync(filePath, 'utf-8')
|
|
320
|
+
.split('\n')
|
|
321
|
+
.map(e => e.trim())
|
|
322
|
+
.filter(e => e.length > 0);
|
|
323
|
+
|
|
324
|
+
const results = await validateBulk(emails, {
|
|
325
|
+
concurrency: 10,
|
|
326
|
+
onProgress: (completed, total, result) => {
|
|
327
|
+
const pct = Math.round((completed / total) * 100);
|
|
328
|
+
process.stdout.write(`\r[${pct}%] Validating emails...`);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const valid = results.filter(r => r.isReachable === 'safe');
|
|
333
|
+
const invalid = results.filter(r => r.isReachable === 'invalid');
|
|
334
|
+
|
|
335
|
+
console.log(`\nValid: ${valid.length}, Invalid: ${invalid.length}`);
|
|
336
|
+
|
|
337
|
+
return results;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Custom Validation Pipeline
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
import {
|
|
345
|
+
validateSyntax,
|
|
346
|
+
verifyMx,
|
|
347
|
+
checkDisposable,
|
|
348
|
+
checkRoleAccount
|
|
349
|
+
} from 'bouncevalidator';
|
|
350
|
+
|
|
351
|
+
async function customValidation(email: string) {
|
|
352
|
+
// Step 1: Check syntax
|
|
353
|
+
const syntax = validateSyntax(email);
|
|
354
|
+
if (!syntax.isValidSyntax) {
|
|
355
|
+
return { valid: false, reason: 'Invalid syntax' };
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Step 2: Check if disposable
|
|
359
|
+
if (checkDisposable(syntax.domain)) {
|
|
360
|
+
return { valid: false, reason: 'Disposable email' };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Step 3: Check if role account
|
|
364
|
+
if (checkRoleAccount(syntax.username)) {
|
|
365
|
+
return { valid: false, reason: 'Role-based account' };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Step 4: Verify MX records
|
|
369
|
+
const mx = await verifyMx(syntax.domain);
|
|
370
|
+
if (!mx.acceptsMail) {
|
|
371
|
+
return { valid: false, reason: 'Domain does not accept mail' };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return { valid: true, domain: syntax.domain, mx: mx.records };
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Express.js Integration
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import express from 'express';
|
|
382
|
+
import { validate, validateBulk } from 'bouncevalidator';
|
|
383
|
+
|
|
384
|
+
const app = express();
|
|
385
|
+
app.use(express.json());
|
|
386
|
+
|
|
387
|
+
// Single email validation endpoint
|
|
388
|
+
app.post('/api/validate', async (req, res) => {
|
|
389
|
+
const { email } = req.body;
|
|
390
|
+
|
|
391
|
+
if (!email) {
|
|
392
|
+
return res.status(400).json({ error: 'Email is required' });
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const result = await validate(email);
|
|
397
|
+
res.json(result);
|
|
398
|
+
} catch (err) {
|
|
399
|
+
res.status(500).json({ error: 'Validation failed' });
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// Bulk validation endpoint
|
|
404
|
+
app.post('/api/validate/bulk', async (req, res) => {
|
|
405
|
+
const { emails } = req.body;
|
|
406
|
+
|
|
407
|
+
if (!Array.isArray(emails)) {
|
|
408
|
+
return res.status(400).json({ error: 'Emails array is required' });
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
try {
|
|
412
|
+
const results = await validateBulk(emails, { concurrency: 5 });
|
|
413
|
+
res.json(results);
|
|
414
|
+
} catch (err) {
|
|
415
|
+
res.status(500).json({ error: 'Validation failed' });
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
app.listen(3000);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
## How It Works
|
|
423
|
+
|
|
424
|
+
### 1. Syntax Validation
|
|
425
|
+
|
|
426
|
+
The first step validates the email format against RFC 5322 standards:
|
|
427
|
+
- Checks for valid characters in local and domain parts
|
|
428
|
+
- Validates domain structure and TLD
|
|
429
|
+
- Enforces length limits (254 chars total, 64 chars local part)
|
|
430
|
+
|
|
431
|
+
### 2. DNS/MX Verification
|
|
432
|
+
|
|
433
|
+
Next, we query DNS to verify the domain can receive email:
|
|
434
|
+
- Looks up MX (Mail Exchange) records
|
|
435
|
+
- Falls back to A/AAAA records if no MX exists (per RFC 5321)
|
|
436
|
+
- Detects null MX records (RFC 7505)
|
|
437
|
+
- Caches results for performance
|
|
438
|
+
|
|
439
|
+
### 3. SMTP Verification
|
|
440
|
+
|
|
441
|
+
The most reliable check - we connect to the mail server:
|
|
442
|
+
1. Connect to the highest priority MX host
|
|
443
|
+
2. Send EHLO/HELO greeting
|
|
444
|
+
3. Initiate MAIL FROM command
|
|
445
|
+
4. Send RCPT TO with the target email
|
|
446
|
+
5. Interpret the server's response
|
|
447
|
+
|
|
448
|
+
Response codes:
|
|
449
|
+
- 250: Mailbox exists
|
|
450
|
+
- 550: Mailbox not found
|
|
451
|
+
- 450/451: Greylisted or temporary failure
|
|
452
|
+
- 552: Mailbox disabled
|
|
453
|
+
|
|
454
|
+
### 4. Additional Checks
|
|
455
|
+
|
|
456
|
+
Finally, we perform supplementary checks:
|
|
457
|
+
- **Disposable detection**: Compares domain against 500+ known disposable email services
|
|
458
|
+
- **Role account detection**: Checks for common role-based prefixes (admin, support, info, etc.)
|
|
459
|
+
- **Free provider detection**: Identifies free email services (Gmail, Yahoo, Outlook, etc.)
|
|
460
|
+
- **Catch-all detection**: Tests if domain accepts any random address
|
|
461
|
+
|
|
462
|
+
## Limitations
|
|
463
|
+
|
|
464
|
+
- **SMTP verification may be blocked**: Some mail servers block or rate-limit SMTP verification attempts
|
|
465
|
+
- **Greylisting**: Some servers use greylisting which causes temporary rejections
|
|
466
|
+
- **Catch-all domains**: Cannot definitively verify addresses on catch-all domains
|
|
467
|
+
- **Network dependent**: Requires network access for DNS and SMTP operations
|
|
468
|
+
- **No DMARC/SPF checks**: Does not validate sending reputation
|
|
469
|
+
|
|
470
|
+
## Performance Tips
|
|
471
|
+
|
|
472
|
+
1. **Use DNS caching**: Enabled by default, reduces repeated DNS lookups
|
|
473
|
+
2. **Adjust concurrency**: Higher concurrency for bulk operations, but be mindful of rate limits
|
|
474
|
+
3. **Use quick mode**: Skip SMTP verification when you only need syntax/MX validation
|
|
475
|
+
4. **Batch operations**: Use `validateBulk` instead of multiple `validate` calls
|
|
476
|
+
|
|
477
|
+
## Contributing
|
|
478
|
+
|
|
479
|
+
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
480
|
+
|
|
481
|
+
## License
|
|
482
|
+
|
|
483
|
+
MIT
|