IsEmail: примеры (JAVA)
isEmail(CharSequence email): booleanОписание функции isEmail
isEmail представляет собой логическую проверку, предназначенную для определения, соответствует ли входная строка формату адреса электронной почты. В Java это не встроенный метод стандартной библиотеки, а концепт, который реализуется несколькими способами: регулярными выражениями, библиотеками вроде Apache Commons Validator, Jakarta Mail или собственными утилитными методами.
Типичная сигнатура и поведение:
boolean isEmail(String email) - простая проверка на соответствие общему синтаксису. При входном значении null возможны варианты поведения: возвращение false или бросание IllegalArgumentException, в зависимости от реализации.
Расширенная сигнатура с опциями:
boolean isEmail(String email, EmailOptions options), где EmailOptions - объект с настройками. Возможные параметры:
- allowInternational (boolean) - разрешить Unicode в локальной части и в домене (IDN). При false применяется Punycode для доменов.
- allowQuotedLocal (boolean) - разрешить кавыченую локальную часть, например: "user name"@example.com.
- allowDomainLiteral (boolean) - разрешить домены в квадратных скобках типа user@[192.168.0.1].
- allowTopLevelDomain (boolean) - разрешить адреса без точки в домене (иногда используется для локальных сетей).
- requireMX (boolean) - выполнить DNS-проверку на наличие MX-записи; требует сетевого доступа и может бросать исключения при сетевых ошибках.
- strict (boolean) - включить строгую валидацию по RFC 5322; строгая валидация обычно сложнее и может отклонять многие практические адреса.
Возвращаемые значения:
- true - строка валидна как e-mail в рамках выбранных опций.
- false - строка не соответствует правилам.
Побочные эффекты и исключения:
- Некоторые реализации могут бросать
IllegalArgumentExceptionдля недопустимых входных данных илиNamingException/ собственные исключения при DNS-проверке. - Проверка, включающая сетевые запросы, может быть медленнее и небезопасна для вызовов в потоках обслуживания запросов без таймаута.
Короткие примеры использования isEmail
Пример 1. Простая проверка через регулярное выражение (упрощенная, практическая):
public class EmailUtil {
private static final String SIMPLE_EMAIL = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
public static boolean isEmail(String email) {
if (email == null) return false;
return email.matches(SIMPLE_EMAIL);
}
public static void main(String[] args) {
System.out.println(isEmail("user@example.com"));
System.out.println(isEmail("user.name+tag@sub.example.co"));
System.out.println(isEmail("invalid@localhost"));
}
}
true true false
Пример 2. Использование Apache Commons Validator:
import org.apache.commons.validator.routines.EmailValidator;
public class Demo {
public static void main(String[] args) {
EmailValidator validator = EmailValidator.getInstance();
System.out.println(validator.isValid("user@example.com"));
System.out.println(validator.isValid("user@[192.168.0.1]"));
}
}
true true
Пример 3. Проверка через Jakarta Mail (бросает исключение при невалидности):
import jakarta.mail.internet.InternetAddress;
public class MailCheck {
public static boolean isEmail(String email) {
try {
InternetAddress addr = new InternetAddress(email, true);
addr.validate();
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String[] args) {
System.out.println(isEmail("quoted\"@example.com"));
System.out.println(isEmail("plainaddress"));
}
}
false false
Похожие функции в Java и особенности
- Apache Commons EmailValidator - готовая реализация с настройками, надежная для большинства задач. Предпочтительна при отсутствии необходимости сетевой проверки и при желании не писать свою регулярку.
- Jakarta Mail (InternetAddress) - более строгая проверка синтаксиса, учитывающая много тонкостей RFC. Предпочтительна, если нужна совместимость с почтовыми стандартами и возможна зависимость от почтовой библиотеки.
- Регулярные выражения (java.util.regex.Pattern) - гибкие, но легко сделать либо слишком строгую, либо слишком слабую проверку. Подходят, когда нужны кастомные правила.
- javax.validation.constraints.Email - аннотация Bean Validation (Hibernate Validator). Удобна для валидации полей DTO в приложениях с валидацией на уровне модели.
Выбор основывается на простоте, точности и дополнительных требованиях: для быстрой практической проверки - регулярка или Commons; для совместимости с RFC - Jakarta Mail; для интеграции с валидацией модели - аннотация Bean Validation.
Альтернативы в других языках и отличия
PHP:
$emails = ["user@example.com", "bad@localhost"];
foreach ($emails as $e) {
var_dump(filter_var($e, FILTER_VALIDATE_EMAIL) !== false);
}
bool(true) bool(false)
Отличие: встроенная фильтрация удобна и стандартна, но не покрывает все требования RFC и не делает DNS-проверок.
JavaScript:
const validator = require('validator');
console.log(validator.isEmail('user@example.com'));
console.log(/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test('user@example.com'));
true true
Отличие: в Node экосистема предоставляет модуль validator с гибкими опциями; браузерные regex работают локально.
Python:
from email.utils import parseaddr
print(bool(parseaddr('user@example.com')[1]))
# Или с пакетом validate_email
# from validate_email import validate_email
# print(validate_email('user@example.com'))
True
Отличие: стандартный parseaddr парсит, но не валидирует строго; внешние пакеты обеспечивают более строгую проверку и возможную MX-проверку.
SQL (PostgreSQL):
SELECT 'user@example.com' ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$';
t
Отличие: проверка на уровне БД удобна для целостности данных, но выражения могут быть тяжелыми и не учитывать всех кейсов.
C#:
using System.Net.Mail;
bool IsEmail(string s) {
try { var m = new MailAddress(s); return true; }
catch { return false; }
}
Console.WriteLine(IsEmail("user@example.com"));
True
Отличие: встроенный MailAddress делает простую и практическую проверку, похожую по духу на Jakarta Mail.
Go:
package main
import (
"fmt"
"net/mail"
)
func main() {
_, err := mail.ParseAddress("user@example.com")
fmt.Println(err == nil)
}
true
Отличие: net/mail предоставляет стандартный парсер; для строгой проверки может потребоваться дополнительная логика.
Kotlin:
fun isEmail(s: String?) = s?.matches(Regex("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) ?: false
println(isEmail("user@example.com"))
true
Отличие: Kotlin использует те же Java-библиотеки или regex, плюс удобные расширения.
Типичные ошибки при использовании isEmail
- Слишком простая регулярка - пропускает некорректные адреса или отвергает допустимые. Пример: отвергается адрес с дефисом в TLD или с новым TLD длиной 1-символной в специальных доменах.
- Null-значения - отсутствие проверки на
nullприводит к NPE. Пример:
public boolean isEmail(String s) {
return s.matches("^.+@.+$"); // NPE если s == null
}
// Вызов: isEmail(null) -> java.lang.NullPointerException
Exception in thread "main" java.lang.NullPointerException
at ...
- Перепроверка после нормализации - если перед проверкой выполняется IDN.toASCII для доменов, нужно проверять результат нормализации, иначе возможны пустые или некорректные строки.
- Сетевые проверки без таймаута - DNS или SMTP проверки могут блокировать приложение. Пример: вызов requireMX без таймаута.
- Ожидание абсолютной точности - даже строгая проверка синтаксиса не гарантирует существование почтового ящика.
Изменения и эволюция
В Java как языке не появилось встроенной функции isEmail, но экосистема развивалась:
- Jakarta Mail заменил javax.mail после переноса пакета; поведение InternetAddress осталось схожим, но потребовалось обновление зависимостей и импортов.
- Поддержка международных адресов (RFC 6530 и последующие) подтолкнула библиотеки к добавлению опций для Unicode в локальной части и к использованию Punycode для доменов.
- Apache Commons Validator обновлялся с учётом практических случаев и расширяемости, но полная совместимость с RFC 5322 по-прежнему сложна.
Рекомендуется следить за версиями библиотек и их билдами для корректной поддержки новых правил и IDN.
Расширенные и редкие примеры использования
Пример A. Нормализация IDN и проверка с DNS MX:
import java.net.IDN;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;
public class Advanced {
public static boolean isEmailWithMx(String email) {
if (email == null || !email.contains("@")) return false;
String[] parts = email.split("@", 2);
String domain = parts[1];
try {
String ascii = IDN.toASCII(domain);
Hashtable env = new Hashtable<>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
DirContext ctx = new InitialDirContext(env);
javax.naming.directory.Attributes attrs = ctx.getAttributes(ascii, new String[]{"MX"});
return attrs.get("MX") != null;
} catch (Exception e) {
return false;
}
}
public static void main(String[] args) {
System.out.println(isEmailWithMx("user@пример.рф"));
}
}
false
Комментарий: пример сочетает IDN.toASCII и вызов DNS через JNDI. DNS-запросы требуют сетевого доступа и могут возвращать непредсказуемый результат.
Пример B. Асинхронная проверка в веб-приложении (псевдокод):
// Используется ExecutorService для выполнения проверки с таймаутом
Future f = executor.submit(() -> isEmailWithMx(email));
try {
boolean ok = f.get(3, TimeUnit.SECONDS);
} catch (TimeoutException te) {
// считаем невалидным или откладываем проверку
}
(зависит от выполнения задачи, возможен TimeoutException)
Пример C. Интеграция с Bean Validation (кастомный валидатор):
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Constraint(validatedBy = EmailConstraintValidator.class)
public @interface ValidEmail {
String message() default "Неверный email";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class EmailConstraintValidator implements ConstraintValidator {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value == null || EmailUtil.isEmail(value);
}
}
// Использование в DTO
public class UserDto {
@ValidEmail
private String email;
}
(валидация происходит при запуске Bean Validation, результат зависит от входных данных)
Пример D. Проверка через SMTP (проверка пользователя на стороне почтового сервера) - демонстрация рисков:
// Описательно: попытка установить соединение с mx-сервером и выполнить EHLO + RCPT TO
// Часто запрещается и может считаться спам-активностью
(не рекомендуется выполнять без разрешения; результаты зависят от политики сервера)
Пример E. Кастомные правила для корпоративной политики:
// Внутренняя компания позволяет только домены вида @company.local или @partner.com
public static boolean isCompanyEmail(String s) {
return s != null && (s.endsWith("@company.local") || s.endsWith("@partner.com"));
}
true/false в зависимости от входа
Комментарий: расширенные сценарии показывают, что помимо синтаксиса часто требуется нормализация, проверка домена и учёт политик безопасности и конфиденциальности. Сетевые проверки делают валидацию более точной, но добавляют риски и задержки.