如何判断一个随机字符串是电子邮件地址还是其他内容

8
我不认为这个问题以前被问过……我肯定找不到这样的要求。
背景
有一个API返回人员的ID。通常情况下,应将ID视为区分大小写……但如果ID实际上是他们的电子邮件地址……并且您正在与该API的实现进行交互,它返回了一个混合大小写版本的电子邮件地址,则会有很多乐趣……
因此,您正在与一个实现进行交互……它会给您返回类似URL的东西作为ID,例如:
  • http://foo.bar.com/blahblahblah
你接下来可能会与另一个实现交互...该实现会返回一些不明显的ID,例如:
  • as€jlhdésdj678hjghas7t7qhjdhg£
你也可能会与一个友好的实现交互,它会返回一个漂亮的小写电子邮件地址:
  • bob.mcspam@acme.org

或者你正在与不那么出色的实现交谈,该实现返回完全等效的ID。

  • bob.mcspam@ACME.org
RFC 2821规定只有邮箱区分大小写,但是利用大小写敏感性会引起一系列的互操作问题... 我想做的是识别电子邮件字符串并强制将域名转换为小写。识别类似URI的字符串更容易,因为方案要么是http,要么是https,我只需要将域名转换为小写,这样解析起来就容易多了。
问题:如果给出一个由外部服务提供的字符串,是否有一个测试可以确定该字符串是否为电子邮件地址,以便我可以强制将域名转换为小写?
允许少量的电子邮件地址被忽略,并且没有将字符串的一部分强制转换为小写,除非它是电子邮件地址的域部分。 (不允许误判)
请注意,这个问题与thisthis略有不同,因为在那两个问题的背景下,你已经知道字符串应该是一个电子邮件地址。
在这个问题的背景下,我们不知道这个字符串是一个电子邮件地址还是其他什么... 这使得这个问题不同。

除了检查域名是否存在并且在其DNS条目中具有电子邮件服务器之外,为什么不能使用正则表达式来检查语法上合法的电子邮件地址?有很多这样的电子邮件地址。 - radai
可能是Java中验证电子邮件的重复问题 - Bernhard Barker
3
还有一个问题:什么是最好的Java电子邮件地址验证方法? - Bernhard Barker
@radai 嗯,我不想在代码路径上调用DNS查询,因为那会引入问题...特别是运行此代码的服务器可能无法验证返回的ID中的域名。因此,检查DNS条目是不可行的。 - Stephen Connolly
DNS验证是一个额外的步骤,但除了正则表达式,我真的看不出还有其他的方法。 - radai
显示剩余2条评论
5个回答

13

- 试用下面的代码,这可能对您有帮助。

public class EmailCheck {

    public static void main(String[] args){


        String email = "vivek.mitra@gmail.com";
        Pattern pattern = Pattern.compile("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}");
        Matcher mat = pattern.matcher(email);

        if(mat.matches()){

            System.out.println("Valid email address");
        }else{

            System.out.println("Not a valid email address");
        }
    }

}

- 还要看一下这个网站,它展示了另一个使用 正则表达式 进行更深层次验证的方法。 使用正则表达式进行更深层次验证


1
请注意,"ping @ pong!"@[1.2.3.4] 是一个有效的电子邮件地址,但您的代码将无法正确识别...现在它也是一个有效的电子邮件地址,不需要在 @ 后面的位小写,但这是另一个问题。使用正则表达式来识别电子邮件地址是一种反模式。 - Stephen Connolly

7
您可以使用以下方法验证电子邮件地址:
String email ="nbjvkj@kn.com"
Pattern p = Pattern.compile(".+@.+\\.[a-z]+");
Matcher m = p.matcher(email);
boolean matchFound = m.matches();
if (matchFound) {
    //your work here
}

该正则表达式匹配了@符号后面太多的内容,因为它只应该匹配有效构造的域名。 - Stephen Connolly

3

3
这个类很方便,但是文档中有这样的免责声明:“此实现不能保证捕获电子邮件地址中可能出现的所有错误。” - KayO

2
感谢 @Dukeling
private static toLowerCaseIfEmail(String string) {
    try {
        new InternetAddress(string, true);
    } catch (AddressException e) {
        return string;
    }
    if (string.trim().endsWith("]")) {
        return string;
    }
    int lastAt = string.lastIndexOf('@');
    if (lastAt == -1) {
        return string;
    }
    return string.substring(0,lastAt)+string.substring(lastAt).toLowerCase();
}

should,根据我所了解的,应该做出所需的操作。

更新

由于之前的忽略了最后一个 @ 后可能存在的 (comment) 语法... 如果我们看到它们,就应该立即退出并返回未修改的字符串。

private static toLowerCaseIfEmail(String string) {
    try {
        new InternetAddress(string, true);
    } catch (AddressException e) {
        return string;
    }
    int lastAt = string.lastIndexOf('@');
    if (lastAt == -1 
        || string.lastIndexOf(']') > lastAt
        || string.lastIndexOf(')' > lastAt) {
        return string;
    }
    return string.substring(0,lastAt)+string.substring(lastAt).toLowerCase();
}

1
这真的是答案吗? - Fahim Parkar
1
是的,因为 RFC 2821 中电子邮件规范比您想象的要奇怪得多,而使用标准 Java API 的最佳方法是让符合规范的解析器解析请求并针对路由路径地址(因此使用 endsWith("]"))退出。 - Stephen Connolly
我敢打赌@StephenConnolly发送了很多电子邮件。他知道这种痛苦。 - Tony Ennis
当然,我的尝试没有处理电子邮件地址中的注释... john."M@c"."Smith!"(coolguy)@(thefantastic)[1.2.3.4](onlythebest) 也是一个有效的电子邮件地址...但如果检查是 indexOf(']') < lastAt 而不是使用 endsWith("[") 则可以安全地忽略它,因为这将指示一个不需要小写的电子邮件地址,因为 [] 仅用于 IP 地址。 - Stephen Connolly

0
        Pattern pattern = Pattern.compile("^[A-Za-z0-9._]{1,16}+@{1}+[a-z]{1,7}\\.[a-z]{1,3}$");
        Matcher mail = pattern.matcher(your_mail);

        if (mail.find()) {
            System.out.println("True");
        } else {
            System.out.println("False");
        }

你能提供一个解释来配合你的答案吗? - robjwilkins
无法处理像myname+classifier@gmail.com这样的电子邮件地址或任何花哨的邮箱标识符,例如"name with spaces"@example.com是一个有效的电子邮件地址(即使有些愚蠢),并且不会通过您的正则表达式。 - Stephen Connolly
哦,这对我的实际Gmail电子邮件地址也失败了,因为我的邮箱标识符长达21个字符。 - Stephen Connolly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接