如何提取文本中的电子邮件/邮箱string列表或testingstring是否是正确的电子邮件地址?

鉴于一些任意文本,我想提取所有电子邮件地址和“邮箱说明符”(例如"Fred Smith" <fred@me.com> )。 我看着NSDataDetector,但它不处理电子邮件地址。

解决这个问题的方法是获得一个非常好的algorithm,它可以检测尽可能多的有效地址,并拒绝不合适的地址。 可能最好的解决scheme是使用lex和yacc构造的parsing器,但使用正则expression式存在合理的解决scheme。

看到这个网站既是一个经过testing的正则expression式列表,也是对这个问题和可能的解决scheme的更深入的讨论。

上面的网站上显示的正则expression式是PHP的格式,并具有前导和尾随的“/”标记,以及“标志”表示不区分大小写等(见本网站获取更多信息),所以这些需要剥离在Objective-C项目中使用expression式之前。 另外,任何锚都需要剥离,因为我们想要多个地址不只一个(即'^'和'$')。

NSRegularExpression是在这里使用的类。 我发现有用的是将正则expression式存储在我的项目中的一个文件,所以你不必担心逃避所有的反斜杠和引号。 然后代码将expression式读入一个string,并创build该对象,如下所示:

 NSString *fullPath = [[NSBundle mainBundle] pathForResource:self.regex ofType:@"txt"]; NSString *pattern = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:NULL]; __autoreleasing NSError *error = nil; reg = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; // some patterns may not need NSRegularExpressionCaseInsensitive assert(reg && !error); 

一旦你有一个初始化的expression式,你用它来返回一个范围列表,每个范围是一个地址:

 NSArray *ret = [reg matchesInString:str options:0 range:NSMakeRange(0, [str length])]; 

但是,我们知道所有的电子邮件地址都包含一个'@',所以在处理之前validationstring是否至less有一个是值得的。 此外,由于文本可能包含行和/或回车符,因此您可能需要先删除这些文本。 将它们完全剥离可能更好,因为某些邮件程序可能在地址的某个内部点处分割了一条线。

一旦你有地址范围的列表,那么大部分的工作就完成了 – 如果你想要的只是地址。 然而,通常地址是以“邮箱说明符”格式表示的,其中地址前面加上了一个名字,地址后面加上了“<”和“>”,这个格式在RFC5322的 3.4节中有介绍。

要从“邮箱说明符”中恢复名称,请检查地址是否包含“<”和“>”,如果是,则查找“<”之前的string,忽略空格(直到find第一个字符)。 大多数名字将用双引号包起来(通常的做法),但实际上可以是使用反斜杠转义的裸体字母数字string,以包含空格或其他特殊字符(如''')。

这种相同的技术可以用于实时validation – 比如当文本string变成有效的电子邮件地址时启用提交button。 在这种情况下,您可以评估每个用户更改的string,并启用/禁用“提交”button。

如果所有这些看起来像很多代码工作,你可以在github上抓取一个开源项目。

编辑1:为更快,但不太严谨,方法请参阅由CodaFi的评论。

编辑2:看起来“mailto:URL的内容可能相当复杂,github项目只处理最简单的,并且不对地址解码,这将在未来的更新中解决。

EDIT3:项目被更新完全处理“mailto:”对象,并返回cc,bcc,subject和body,所有URLdecoded。