杰瑞科技汇

Java中email正则表达式如何正确编写?

  1. 一个推荐的、实用的正则表达式
  2. 完整的 Java 代码示例
  3. 对正则表达式的详细解释
  4. 内置的 javax.mail 方法(更简单)
  5. 正则表达式验证的局限性

推荐的实用正则表达式

一个既不过于严格(会拒绝合法邮件),也不过于宽松(会接受非法邮件)的正则表达式是最佳选择,这个正则表达式基于 RFC 5322 标准,但做了一些简化,足以应对 99.9% 的日常场景。

Java中email正则表达式如何正确编写?-图1
(图片来源网络,侵删)
^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$

为什么推荐这个?

  • 它允许常见的特殊字符,如 , &, , , _
  • 它允许 出现在用户名和域名部分(但不能是第一个或最后一个,也不能连续)。
  • 它强制要求顶级域名(如 .com, .org, .io)的长度在 2 到 7 个字符之间,这涵盖了所有现有的国家代码(.cn, .uk)和通用顶级域名(.com, .info)。

完整的 Java 代码示例

下面是一个完整的 Java 类,展示了如何使用上面的正则表达式来验证电子邮件。

import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class EmailValidator {
    // 预编译正则表达式,提高性能(如果这个方法会被频繁调用)
    private static final String EMAIL_REGEX = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
    private static final Pattern pattern = Pattern.compile(EMAIL_REGEX);
    /**
     * 验证电子邮件地址是否有效
     * @param email 要验证的电子邮件字符串
     * @return 如果有效则返回 true,否则返回 false
     */
    public static boolean isValid(String email) {
        // 如果输入为 null 或空字符串,直接返回 false
        if (email == null || email.isEmpty()) {
            return false;
        }
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }
    public static void main(String[] args) {
        // --- 测试用例 ---
        String[] validEmails = {
            "user@example.com",
            "user.name@example.com",
            "user-name@example.com",
            "user_name@example.com",
            "user+name@example.com",
            "user@sub.domain.co.uk",
            "user123@example.io",
            "test.email+alias@example.com"
        };
        String[] invalidEmails = {
            "plainaddress",           // 缺少 @ 和域名
            "@missing-local.com",     // 缺少本地部分
            "user@.com",              // 域名以点开头
            "user@domain.",           // 域名以点结尾
            "user..name@example.com", // 本地部分有连续的点
            "user@domain.c",          // 顶级域名太短
            "user@domain.com.",       // 顶级域名后有多余的点
            "user@-example.com",      // 域名部分以连字符开头
            "user@example..com",      // 域名部分有连续的点
            "user@domain.12"         // 顶级域名不是字母
        };
        System.out.println("--- 测试有效的电子邮件 ---");
        for (String email : validEmails) {
            System.out.printf("%-30s -> %b%n", email, isValid(email));
        }
        System.out.println("\n--- 测试无效的电子邮件 ---");
        for (String email : invalidEmails) {
            System.out.printf("%-30s -> %b%n", email, isValid(email));
        }
    }
}

代码解释:

  1. EMAIL_REGEX: 定义了我们上面推荐的正则表达式字符串。
  2. Pattern.compile(): 这是一个性能优化。Pattern 类代表一个编译后的正则表达式,将它编译一次并重用,比每次验证时都重新编译要高效得多,尤其是在循环或高频调用的场景下。
  3. pattern.matcher(email): 创建一个 Matcher 对象,该对象将使用编译好的模式去匹配输入的 email 字符串。
  4. matcher.matches(): 尝试将整个输入字符串与模式进行匹配,如果整个字符串完全匹配模式,则返回 true,否则返回 false,注意它和 matcher.find() 的区别,后者只查找子串的匹配。

正则表达式详解

让我们来分解这个正则表达式 ^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$

Java中email正则表达式如何正确编写?-图2
(图片来源网络,侵删)
部分 解释
^ 匹配字符串的开始,确保模式从头开始匹配。
[a-zA-Z0-9_+&*-]+ 本地部分 (Local Part)
[...]: 定义一个字符集。
a-zA-Z: 任意大小写字母。
0-9: 任意数字。
_+&*-: 下划线、加号、与号、星号、连字符。
: 匹配前一个字符集 一次或多次
(?:\\.[a-zA-Z0-9_+&*-]+)* 本地部分的点号和后续字符
: 一个非捕获分组,用于将多个部分组合在一起,但不创建反向引用。
\\.: 匹配一个字面量的点号,在 Java 字符串中,反斜杠 \ 是转义字符,所以需要写成 \\ 来表示一个 \
[a-zA-Z0-9_+&*-]+: 和上面一样的字符集,匹配一次或多次。
: 匹配前面的分组 零次或多次
整体:这部分允许用户名中出现 ,first.last
匹配 "@" 符号,这是电子邮件地址的必需部分。
(?:[a-zA-Z0-9-]+\\.)+ 域名部分 (Domain Part)
[a-zA-Z0-9-]+: 匹配一个或多个字母、数字或连字符(域名的标签)。
\\.: 匹配一个点号。
: 匹配前面的 分组 一次或多次
整体:这会匹配类似 sub.domain. 这样的结构,确保至少有一个点。
[a-zA-Z]{2,7} 顶级域名
[a-zA-Z]: 只能是字母。
{2,7}: 匹配前面的字符集 2 到 7 次,这覆盖了 .com, .org, .cn, .info, .technology 等。
匹配字符串的结束,确保模式匹配到字符串的末尾。

内置的 javax.mail 方法(更简单)

如果你的项目已经引入了 JavaMail API(在 Spring Boot 项目中通常作为依赖),你可以使用它内置的 InternetAddress 类来验证电子邮件格式,这种方法更可靠,因为它是由 JavaMail 专家维护的。

Maven 依赖:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version> <!-- 使用最新稳定版本 -->
</dependency>

Java 代码:

import javax.mail.internet.InternetAddress;
import javax.mail.internet.AddressException;
public class EmailValidatorWithJavaMail {
    public static boolean isValid(String email) {
        if (email == null || email.isEmpty()) {
            return false;
        }
        boolean result = true;
        try {
            InternetAddress emailAddr = new InternetAddress(email);
            emailAddr.validate(); // 如果地址无效,会抛出 AddressException
        } catch (AddressException ex) {
            result = false;
        }
        return result;
    }
    public static void main(String[] args) {
        String email = "test@example.com";
        System.out.println("Is '" + email + "' valid? " + isValid(email)); // true
        String invalidEmail = "test@example";
        System.out.println("Is '" + invalidEmail + "' valid? " + isValid(invalidEmail)); // false
    }
}

优点:

Java中email正则表达式如何正确编写?-图3
(图片来源网络,侵删)
  • 更权威: 基于成熟的邮件处理库。
  • 代码简洁: 只需几行代码。

缺点:

  • 增加依赖: 需要引入 javax.mail 库,对于一个非常简单的验证功能来说可能有些“重”。

正则表达式验证的局限性

最重要的一点:正则表达式可以验证电子邮件的 格式,但不能验证它是否 真实存在且有效

nonexistent-user@this-domain-does-not-exist.com 会被上面的正则表达式判定为“有效”,因为它格式正确,但实际上这个邮箱地址可能并不存在。

要真正验证一个邮箱地址是否存在,唯一可靠的方法是:

  1. 发送一封验证邮件,邮件中包含一个验证链接。
  2. 用户点击链接后,才确认邮箱地址有效。

这是所有注册流程的标准做法。

方法 优点 缺点 适用场景
自定义正则表达式 - 无需外部依赖
- 高度可控,可根据需求调整
- 可能不够严谨,会漏掉或误判一些边缘情况
- 维护正则表达式本身有成本
项目中需要一个轻量级的、客户端或服务端的格式校验。
javax.mail - 权威、可靠
- 代码非常简洁
- 引入了外部依赖 项目中已经使用了 JavaMail API,或者需要一个比自定义正则更可靠的格式校验。
发送验证邮件 - 唯一能验证邮箱真实存在的方法 - 实现复杂
- 用户体验差(需要用户操作)
用户注册、重要通知等必须确保邮箱真实有效的核心业务流程。

对于大多数后端 API 的请求参数校验,推荐使用自定义正则表达式,因为它轻量且足够,对于注册流程,必须结合发送验证邮件的机制。

分享:
扫描分享到社交APP
上一篇
下一篇