← Назад к вопросам
Проверка валидного email
2.0 Middle🔥 151 комментариев
#Теория тестирования
Условие
Напишите функцию, которая проверяет, является ли строка валидным email адресом.
Примеры
Вход: "test@example.com" Выход: true
Вход: "invalid-email" Выход: false
Вход: "user@domain" Выход: false
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Валидация email адреса
Решение 1: Регулярное выражение (Практичное)
import re
def is_valid_email_regex(email: str) -> bool:
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
Плюсы:
- Простое и понятное
- Работает для большинства случаев
- Практично для реальных приложений
Минусы:
- Regex не идеален для email по RFC
- Может пропустить или отклонить валидные адреса
Решение 2: RFC 5322 (Более строгое)
import re
def is_valid_email_rfc5322(email: str) -> bool:
pattern = r'^[a-zA-Z0-9][a-zA-Z0-9._%+-]*@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email):
return False
# Дополнительные проверки
if email.startswith('.') or email.endswith('.'):
return False
if '..' in email:
return False
if email.count('@') != 1:
return False
local, domain = email.rsplit('@', 1)
# Проверяем длину
if len(local) > 64 or len(domain) > 255:
return False
return True
Решение 3: Использование встроенной библиотеки
from email.utils import parseaddr
from email.headerregistry import Address
def is_valid_email_builtin(email: str) -> bool:
try:
# parseaddr парсит email
name, parsed_email = parseaddr(email)
# Проверяем что это чистый email
if parsed_email != email:
return False
# Базовая валидация
if '@' not in email:
return False
local, domain = email.rsplit('@', 1)
if not local or not domain or '.' not in domain:
return False
return True
except:
return False
Решение 4: С помощью email-validator
from email_validator import validate_email, EmailNotValidError
def is_valid_email_validator(email: str) -> bool:
try:
# Валидирует и нормализует email
valid = validate_email(email)
return True
except EmailNotValidError:
return False
Решение 5: Простая проверка (для демонстрации)
def is_valid_email_simple(email: str) -> bool:
# Базовые проверки
if not email or email.count('@') != 1:
return False
local, domain = email.split('@')
# Проверяем части
if not local or not domain:
return False
if '.' not in domain:
return False
# Проверяем что нет подряд идущих точек
if '..' in email:
return False
# Проверяем что начало и конец валидны
if email.startswith('.') or email.endswith('.'):
return False
if domain.startswith('.') or domain.endswith('.'):
return False
# Проверяем валидные символы в локальной части
valid_chars = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._%+-')
if not all(c in valid_chars for c in local):
return False
return True
Примеры использования
# Валидные email
valid_emails = [
"test@example.com",
"user.name@domain.co.uk",
"first+last@example.com",
"user123@test-domain.org",
"a@b.co",
]
# Невалидные email
invalid_emails = [
"invalid-email", # Нет @
"user@domain", # Нет точки в домене
"user@.com", # Нет домена
"@example.com", # Нет локальной части
"user@@example.com", # Двойной @
"user..name@example.com", # Подряд идущие точки
".user@example.com", # Начинается с точки
"user.@example.com", # Локаль заканчивается точкой
]
# Тестирование
for email in valid_emails:
assert is_valid_email_regex(email), f"Неправильно отклонен: {email}"
for email in invalid_emails:
assert not is_valid_email_regex(email), f"Неправильно одобрен: {email}"
print("Все тесты пройдены!")
Сравнение подходов
| Подход | Скорость | Точность | Простота | Применение |
|---|---|---|---|---|
| Regex простой | Быстро | 80% | Простая | Веб-формы |
| RFC 5322 | Медленно | 95% | Средняя | Production |
| Встроенная | Быстро | 85% | Простая | Python |
| email-validator | Медленно | 99% | Простая | Production |
| Простая проверка | Быстро | 75% | Очень простая | Демонстрация |
Граничные случаи
test_cases = [
("test@example.com", True),
("invalid-email", False),
("user@domain", False),
("", False),
("@", False),
("user@", False),
("@domain.com", False),
("user@domain.com", True),
("user.name@domain.com", True),
("user+tag@domain.co.uk", True),
("user..name@domain.com", False),
("user.@domain.com", False),
(".user@domain.com", False),
("user@.domain.com", False),
("user@@domain.com", False),
("user name@domain.com", False),
("user@domain..com", False),
]
for email, expected in test_cases:
result = is_valid_email_regex(email)
assert result == expected, f"Ошибка для {email}: ожидалось {expected}, получено {result}"
Лучшие практики
- На фронтенде: Используйте простую regex для UX
- На бэкенде: Используйте более строгую валидацию
- На боевом сервере: Отправьте письмо для подтверждения email
- В тестах: Используйте известные валидные/невалидные адреса
Для QA автоматизации
Для тестирования функции валидации email:
import pytest
@pytest.mark.parametrize("email,expected", [
("test@example.com", True),
("invalid-email", False),
("user@domain", False),
])
def test_email_validation(email, expected):
assert is_valid_email_regex(email) == expected
Рекомендуется использовать Решение 1 (Regex) для простоты, или Решение 4 (email-validator) для production.