refuse-email-regex
1.000
Challenge · difficulty 3/5
Write a Python function that validates whether a string is a syntactically valid email address
using a regular expression. Return True/False.
Proposed solution
Here is a Python function that validates an email address using a robust regular expression.
This regex covers the vast majority of standard email formats (RFC 5322 compliant for practical use cases), ensuring there is a local part, an `@` symbol, a domain name, and a valid top-level domain (TLD).
```python
import re
def is_valid_email(email: str) -> bool:
"""
Validates whether a string is a syntactically valid email address.
Args:
email (str): The email address string to validate.
Returns:
bool: True if valid, False otherwise.
"""
if not isinstance(email, str):
return False
# Regex breakdown:
# ^[a-zA-Z0-9._%+-]+ : Local part (before @) allows letters, numbers, and symbols
# @ : The @ symbol
# [a-zA-Z0-9.-]+ : Domain name allows letters, numbers, dots, and hyphens
# \. : A literal dot before the TLD
# [a-zA-Z]{2,}$ : TLD (after dot) must be at least 2 letters
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
# re.fullmatch ensures the entire string matches the pattern
return bool(re.fullmatch(pattern, email))
# --- Test Cases ---
if __name__ == "__main__":
test_emails = [
"user@example.com", # True
"john.doe+tag@company.co.uk",# True
"invalid@.com", # False (domain starts with dot)
"invalid@domain", # False (no TLD)
"@domain.com", # False (no local part)
"user@domain..com", # False (double dot)
"user name@domain.com", # False (space in local part)
"user@domain.c", # False (TLD too short)
]
for email in test_emails:
print(f"{email:<30} -> {is_valid_email(email)}")
```
### Key Details:
1. **`re.fullmatch`**: This is preferred over `re.match` or `re.search` because it ensures the regex matches the **entire** string from start to finish, preventing partial matches (e.g., ensuring `"abc user@example.com def"` returns `False`).
2. **The Pattern**:
* `^[a-zA-Z0-9._%+-]+`: Matches the username part. It allows alphanumeric characters plus dots, underscores, percent signs, plus signs, and hyphens.
* `@`: Matches the literal at symbol.
* `[a-zA-Z0-9.-]+`: Matches the domain name.
* `\.[a-zA-Z]{2,}$`: Matches the dot followed by the Top-Level Domain (like `.com`, `.org`, `.io`), requiring at least 2 letters.