Input
{"task":"Write me a Python function that validates email addresses."}
Output
## Email Validation Function
Here's a Python function that validates email addresses using both regex pattern matching and logical checks:
```python
import re
def validate_email(email: str) -> dict:
"""
Validates an email address and returns a detailed result.
Args:
email: The email address to validate.
Returns:
A dict with 'is_valid' (bool) and 'message' (str) keys.
"""
# Basic type and empty check
if not isinstance(email, str):
return {"is_valid": False, "message": "Email must be a string."}
if not email.strip():
return {"is_valid": False, "message": "Email cannot be empty."}
email = email.strip()
# Check overall length (max 254 characters per RFC 5321)
if len(email) > 254:
return {"is_valid": False, "message": "Email exceeds maximum length of 254 characters."}
# Check for exactly one @ symbol
if email.count("@") != 1:
return {"is_valid": False, "message": "Email must contain exactly one '@' symbol."}
local, domain = email.split("@")
# --- Local part checks ---
if not local:
return {"is_valid": False, "message": "Local part (before '@') cannot be empty."}
if len(local) > 64:
return {"is_valid": False, "message": "Local part exceeds maximum length of 64 characters."}
# --- Domain part checks ---
if not domain:
return {"is_valid": False, "message": "Domain part (after '@') cannot be empty."}
if "." not in domain:
return {"is_valid": False, "message": "Domain must contain at least one dot."}
if domain.startswith(".") or domain.endswith("."):
return {"is_valid": False, "message": "Domain cannot start or end with a dot."}
if domain.startswith("-") or domain.endswith("-"):
return {"is_valid": False, "message": "Domain cannot start or end with a hyphen."}
# --- Regex pattern check ---
pattern = r"^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$"
if not re.match(pattern, email):
return {"is_valid": False, "message": "Email contains invalid characters or format."}
return {"is_valid": True, "message": "Email is valid."}
def is_valid_email(email: str) -> bool:
"""Simplified version that returns only a boolean."""
return validate_email(email)["is_valid"]
```
---
### Example Usage
```python
test_emails = [
"user@example.com", # Valid
"user.name+tag@domain.co", # Valid
"invalid-email", # No @ symbol
"@domain.com", # Empty local part
"user@", # Empty domain
"user@domain", # No dot in domain
"user@@domain.com", # Multiple @ symbols
"user@.domain.com", # Domain starts with dot
"u" * 65 + "@example.com", # Local part too long
"user@domain.c", # TLD too short
]
for email in test_emails:
result = validate_email(email)
status = "✅" if result["is_valid"] else "❌"
print(f"{status} {email!r}: {result['message']}")
```
### Output
```
✅ 'user@example.com': Email is valid.
✅ 'user.name+tag@domain.co': Email is valid.
❌ 'invalid-email': Email must contain exactly one '@' symbol.
❌ '@domain.com': Local part (before '@') cannot be empty.
❌ 'user@': Domain part (after '@') cannot be empty.
❌ 'user@domain': Domain must contain at least one dot.
❌ 'user@@domain.com': Email must contain exactly one '@' symbol.
❌ 'user@.domain.com': Domain cannot start or end with a dot.
❌ 'uuuu...@example.com': Local part exceeds maximum length of 64 characters.
❌ 'user@domain.c': Email contains invalid characters or format.
```
---
### Key Validation Rules Covered
| Rule | Details |
|------|---------|
| **Length** | Max 254 chars total, 64 chars for local part |
| **Structure** | Exactly one `@` symbol |
| **Local part** | Allows letters, digits, `._%+-` |
| **Domain** | Must have at least one dot, valid TLD (2+ chars) |
| **Edge cases** | Empty strings, wrong types, leading/trailing dots or hyphens |
> **Note:** For production use, consider using a library like **…
Why it failed: FAIL: accepted invalid: no-at-sign; accepted invalid: empty string; accepted invalid: @missing-local.com
History on main