A robust email address syntax and deliverability validation library for Python.
npx @tessl/cli install tessl/pypi-email-validator@2.3.00
# Email Validator
1
2
A robust email address syntax and deliverability validation library for Python 3.8+. This library validates that a string is of the form `name@example.com` and optionally checks that the domain name is set up to receive email, providing friendly error messages and normalized email addresses.
3
4
## Package Information
5
6
- **Package Name**: email-validator
7
- **Language**: Python
8
- **Installation**: `pip install email-validator`
9
10
## Core Imports
11
12
```python
13
from email_validator import validate_email, EmailNotValidError
14
```
15
16
Import validation exceptions:
17
18
```python
19
from email_validator import EmailSyntaxError, EmailUndeliverableError
20
```
21
22
Import helper functions and types:
23
24
```python
25
from email_validator import ValidatedEmail, caching_resolver, __version__
26
```
27
28
## Basic Usage
29
30
```python
31
from email_validator import validate_email, EmailNotValidError
32
33
email = "user@example.com"
34
35
try:
36
# Validate email address with deliverability checking
37
validated_email = validate_email(email)
38
39
# Use the normalized form for storage/comparison
40
normalized = validated_email.normalized
41
print(f"Valid email: {normalized}")
42
43
# Access additional information
44
print(f"Local part: {validated_email.local_part}")
45
print(f"Domain: {validated_email.domain}")
46
print(f"ASCII email: {validated_email.ascii_email}")
47
48
except EmailNotValidError as e:
49
print(f"Invalid email: {e}")
50
```
51
52
## Architecture
53
54
The email-validator library provides a single main validation function that performs comprehensive email address validation in multiple stages:
55
56
1. **Input Processing**: Handles both string and bytes input, converting to Unicode as needed
57
2. **Syntax Parsing**: Splits email into display name, local part, and domain components
58
3. **Local Part Validation**: Validates local part syntax with support for internationalization and quoted strings
59
4. **Domain Validation**: Validates domain syntax supporting both domain names and IP literals
60
5. **Deliverability Checking**: Optional DNS-based validation to verify domain can receive email
61
6. **Normalization**: Returns normalized forms suitable for storage and comparison
62
63
## Capabilities
64
65
### Email Validation
66
67
Core email validation functionality that validates email address syntax and optionally checks deliverability.
68
69
```python { .api }
70
def validate_email(
71
email: Union[str, bytes],
72
/, # prior arguments are positional-only
73
*, # subsequent arguments are keyword-only
74
allow_smtputf8: Optional[bool] = None,
75
allow_empty_local: Optional[bool] = None,
76
allow_quoted_local: Optional[bool] = None,
77
allow_domain_literal: Optional[bool] = None,
78
allow_display_name: Optional[bool] = None,
79
strict: Optional[bool] = None,
80
check_deliverability: Optional[bool] = None,
81
test_environment: Optional[bool] = None,
82
globally_deliverable: Optional[bool] = None,
83
timeout: Optional[int] = None,
84
dns_resolver: Optional[object] = None
85
) -> ValidatedEmail:
86
"""
87
Validate an email address and return normalized information.
88
89
Parameters:
90
- email: Email address to validate (str or bytes)
91
- allow_smtputf8: Allow internationalized email addresses (default: True)
92
- allow_empty_local: Allow empty local part like @example.com (default: False)
93
- allow_quoted_local: Allow quoted local parts with special characters (default: False)
94
- allow_domain_literal: Allow bracketed IP addresses in domain (default: False)
95
- allow_display_name: Allow display name format like "Name <email>" (default: False)
96
- strict: Enable additional syntax checks like length limits (default: False)
97
- check_deliverability: Perform DNS checks on domain (default: True)
98
- test_environment: Allow test domains and disable DNS checks (default: False)
99
- globally_deliverable: Require globally routable domains (default: True)
100
- timeout: DNS query timeout in seconds (default: 15)
101
- dns_resolver: Custom DNS resolver instance (default: None)
102
103
Returns:
104
ValidatedEmail: Object containing normalized email and metadata
105
106
Raises:
107
EmailSyntaxError: Email syntax is invalid
108
EmailUndeliverableError: Domain fails deliverability checks
109
"""
110
```
111
112
### Command-Line Interface
113
114
The email-validator package provides a command-line interface for testing and batch validation of email addresses.
115
116
```python { .api }
117
def main(dns_resolver: Optional[object] = None) -> None:
118
"""
119
Command-line interface for email validation.
120
121
Usage:
122
python -m email_validator user@example.com
123
python -m email_validator < email_list.txt
124
125
Environment Variables:
126
ALLOW_SMTPUTF8, ALLOW_EMPTY_LOCAL, ALLOW_QUOTED_LOCAL,
127
ALLOW_DOMAIN_LITERAL, ALLOW_DISPLAY_NAME, GLOBALLY_DELIVERABLE,
128
CHECK_DELIVERABILITY, TEST_ENVIRONMENT, DEFAULT_TIMEOUT
129
"""
130
```
131
132
### DNS Resolver Utilities
133
134
Helper function for creating cached DNS resolvers for improved performance when validating many email addresses.
135
136
```python { .api }
137
def caching_resolver(
138
*,
139
timeout: Optional[int] = None,
140
cache: Optional[object] = None,
141
dns_resolver: Optional[object] = None
142
) -> object:
143
"""
144
Create a DNS resolver with caching for improved performance.
145
146
Parameters:
147
- timeout: DNS query timeout in seconds (default: 15)
148
- cache: Cache instance to use (default: LRUCache)
149
- dns_resolver: Base resolver to configure (default: system resolver)
150
151
Returns:
152
dns.resolver.Resolver: Configured resolver with caching
153
"""
154
```
155
156
## Types
157
158
```python { .api }
159
class ValidatedEmail:
160
"""
161
Result object containing normalized email address and validation metadata.
162
"""
163
164
# Core email components
165
original: str # Original input email address
166
normalized: str # Normalized email address (recommended for use)
167
local_part: str # Local part after normalization
168
domain: str # Domain part after normalization
169
170
# ASCII representations
171
ascii_email: Optional[str] # ASCII-only form if available
172
ascii_local_part: Optional[str] # ASCII-only local part if available
173
ascii_domain: str # ASCII-only domain part
174
175
# Metadata
176
smtputf8: bool # True if SMTPUTF8 extension required
177
display_name: Optional[str] # Display name if present
178
domain_address: Optional[object] # IPv4Address/IPv6Address for domain literals
179
180
# Deliverability information (if checked)
181
mx: Optional[List[Tuple[int, str]]] # MX records as (priority, domain) tuples
182
mx_fallback_type: Optional[str] # Fallback record type ('A' or 'AAAA')
183
spf: Optional[str] # SPF record if found during deliverability check
184
185
def as_dict(self) -> Dict[str, Any]:
186
"""Convert to dictionary representation."""
187
188
def __repr__(self) -> str:
189
"""String representation showing normalized email."""
190
```
191
192
## Exceptions
193
194
```python { .api }
195
class EmailNotValidError(ValueError):
196
"""
197
Base exception for all email validation failures.
198
Contains human-readable error message explaining why validation failed.
199
"""
200
201
class EmailSyntaxError(EmailNotValidError):
202
"""
203
Exception raised when email address has invalid syntax.
204
Includes detailed explanation of syntax problems.
205
"""
206
207
class EmailUndeliverableError(EmailNotValidError):
208
"""
209
Exception raised when email domain fails deliverability checks.
210
Indicates DNS resolution problems or undeliverable domains.
211
"""
212
```
213
214
## Configuration Constants
215
216
Global configuration constants that set default behavior for all validation calls:
217
218
```python { .api }
219
# Validation behavior defaults
220
ALLOW_SMTPUTF8: bool = True # Allow internationalized addresses
221
ALLOW_EMPTY_LOCAL: bool = False # Allow empty local parts
222
ALLOW_QUOTED_LOCAL: bool = False # Allow quoted local parts
223
ALLOW_DOMAIN_LITERAL: bool = False # Allow IP address domains
224
ALLOW_DISPLAY_NAME: bool = False # Allow display name format
225
STRICT: bool = False # Enable strict validation mode
226
227
# Deliverability defaults
228
CHECK_DELIVERABILITY: bool = True # Perform DNS deliverability checks
229
GLOBALLY_DELIVERABLE: bool = True # Require globally routable domains
230
TEST_ENVIRONMENT: bool = False # Enable test environment mode
231
DEFAULT_TIMEOUT: int = 15 # DNS query timeout in seconds
232
233
# Special domain handling
234
SPECIAL_USE_DOMAIN_NAMES: List[str] # List of rejected special-use domains
235
236
# Version information
237
__version__: str # Package version string
238
```
239
240
## Usage Examples
241
242
### Basic Email Validation
243
244
```python
245
from email_validator import validate_email, EmailNotValidError
246
247
def validate_user_email(email_input):
248
try:
249
result = validate_email(email_input)
250
return result.normalized
251
except EmailNotValidError as e:
252
print(f"Invalid email: {e}")
253
return None
254
255
# Usage
256
email = validate_user_email("user@example.com")
257
if email:
258
print(f"Validated email: {email}")
259
```
260
261
### Registration Form Validation
262
263
```python
264
from email_validator import validate_email, EmailNotValidError
265
266
def validate_registration_email(email):
267
"""Validate email for new user registration with deliverability checking."""
268
try:
269
result = validate_email(
270
email,
271
check_deliverability=True, # Check DNS for registration
272
allow_quoted_local=False, # Reject confusing quoted formats
273
allow_display_name=False # Reject display name format
274
)
275
return result.normalized
276
except EmailNotValidError as e:
277
raise ValueError(f"Please enter a valid email address: {e}")
278
```
279
280
### Login Form Validation
281
282
```python
283
from email_validator import validate_email, EmailSyntaxError
284
285
def validate_login_email(email):
286
"""Validate email for login with minimal checks for performance."""
287
try:
288
result = validate_email(
289
email,
290
check_deliverability=False # Skip DNS checks for login
291
)
292
return result.normalized
293
except EmailSyntaxError as e:
294
raise ValueError("Invalid email format")
295
```
296
297
### Batch Validation with Caching
298
299
```python
300
from email_validator import validate_email, caching_resolver, EmailNotValidError
301
302
def validate_email_list(email_list):
303
"""Validate multiple emails efficiently using cached DNS resolver."""
304
# Create cached resolver for better performance
305
resolver = caching_resolver(timeout=10)
306
307
validated_emails = []
308
for email in email_list:
309
try:
310
result = validate_email(email, dns_resolver=resolver)
311
validated_emails.append(result.normalized)
312
except EmailNotValidError as e:
313
print(f"Skipping invalid email {email}: {e}")
314
315
return validated_emails
316
```
317
318
### International Email Support
319
320
```python
321
from email_validator import validate_email, EmailNotValidError
322
323
def validate_international_email(email):
324
"""Validate international email addresses with full Unicode support."""
325
try:
326
result = validate_email(
327
email,
328
allow_smtputf8=True, # Allow international characters
329
globally_deliverable=True # Ensure globally routable
330
)
331
332
print(f"Normalized: {result.normalized}")
333
print(f"ASCII form: {result.ascii_email}")
334
print(f"Requires SMTPUTF8: {result.smtputf8}")
335
336
return result.normalized
337
except EmailNotValidError as e:
338
print(f"Invalid international email: {e}")
339
return None
340
341
# Examples
342
validate_international_email("用户@example.com") # Chinese characters
343
validate_international_email("user@測試.com") # International domain
344
```
345
346
### Custom Configuration
347
348
```python
349
import email_validator
350
from email_validator import validate_email
351
352
# Modify global defaults
353
email_validator.CHECK_DELIVERABILITY = False # Disable DNS checks globally
354
email_validator.ALLOW_QUOTED_LOCAL = True # Allow quoted formats globally
355
356
# Allow test domains for development
357
email_validator.SPECIAL_USE_DOMAIN_NAMES.remove("test")
358
359
# Now all validation calls use these defaults
360
result = validate_email("developer@test") # Would normally be rejected
361
```
362
363
### Error Handling Patterns
364
365
```python
366
from email_validator import (
367
validate_email,
368
EmailNotValidError,
369
EmailSyntaxError,
370
EmailUndeliverableError
371
)
372
373
def comprehensive_email_validation(email):
374
"""Demonstrate different error handling approaches."""
375
try:
376
result = validate_email(email)
377
return {
378
'valid': True,
379
'normalized': result.normalized,
380
'metadata': {
381
'local_part': result.local_part,
382
'domain': result.domain,
383
'smtputf8': result.smtputf8,
384
'mx_records': getattr(result, 'mx', None)
385
}
386
}
387
except EmailSyntaxError as e:
388
return {
389
'valid': False,
390
'error_type': 'syntax',
391
'message': str(e)
392
}
393
except EmailUndeliverableError as e:
394
return {
395
'valid': False,
396
'error_type': 'deliverability',
397
'message': str(e)
398
}
399
except EmailNotValidError as e:
400
return {
401
'valid': False,
402
'error_type': 'general',
403
'message': str(e)
404
}
405
```