如何快速验证电子邮件地址?


338

有谁知道如何在Swift中验证电子邮件地址?我发现此代码:

- (BOOL) validEmail:(NSString*) emailString {

    if([emailString length]==0){
        return NO;
    }

    NSString *regExPattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";

    NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];

    NSLog(@"%i", regExMatches);
    if (regExMatches == 0) {
        return NO;
    } else {
        return YES;
    }
}

但我无法将其翻译为Swift。


8
翻译应该简单明了。哪一部分给您带来问题?
苏珊(Sulthan)2014年

12
不要忘了祈祷您的用户都没有新的顶级域之一。EG.coffee
马蒂亚斯鲍赫

1
@Antzi:我检查了“ someone @ gmail”,您的正则表达式返回了true。
Đông的

2
正则表达式无法验证用户是否输入了他们的电子邮件地址。唯一100%正确的方法是发送激活电子邮件。请参阅:我知道如何验证电子邮件地址,直到我阅读RFC
mouviciel

2
这是一个有趣的质量检查。 几乎可以肯定,这是整个网站上“最错误的”质量检查。 当前具有600票的#1答案(什么?!)绝对,完全,以任何可能的方式都是错误的(每行都是完全错误的,并且每个概念和想法都是错误的........ !!!)其他许多获得高度投票的答案要么是“完全错误”,“极其帽衫”,要么是简单地打乱了甚至不编译。此外,尽管此Q的性质要求“精英正则表达式工程”,但许多答案(极受好评!)以令人震惊的正则表达式工程为特色。这是一个非常有趣的质量检查!为什么??
Fattie

Answers:


769

我会使用NSPredicate

func isValidEmail(_ email: String) -> Bool {        
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
    return emailPred.evaluate(with: email)
}

对于低于3.0的Swift版本:

func isValidEmail(email: String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
    return emailPred.evaluate(with: email)
}

对于低于1.2的Swift版本:

func isValidEmail(email: String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    if let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx) {
        return emailPred.evaluateWithObject(email)
    }
    return false
}

6
会不会return emailTest.evaluateWithObject(testStr)更加简单易读?比较== true有点像Javascript。
苏珊(Sulthan)2014年

15
它不会检查是否有扩展名,a @ a已经可以了:(
CularBytes 2015年

6
这不能通过test @ test ... com进行验证
艾伦(Alan)

3
这不会检测到email。@ invalid.com或email @ .invalid.com。以下来自@alexcristea的答案
Ben Sullivan

3
这是相当有趣,............以及(1)正则表达式是完全,完全不正确(2)正则表达式(甚至什么它试图做的上下文中)有重大错误( 3)Swift是错误的(4)甚至将其放在一边,样式也是完全错误的(5)并不是所有其他内容都很重要,但它甚至没有提到您必须缓存谓词...幽默地,( 6)无论从何处复制代码,都仍然有剩余的代码(“日历”-什么?)。
Fattie

115

编辑,已针对Swift 3更新:

func validateEmail(enteredEmail:String) -> Bool {

    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluate(with: enteredEmail)

}

Swift 2的原始答案:

func validateEmail(enteredEmail:String) -> Bool {

    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluateWithObject(enteredEmail)

}

一切正常。


2
第一个带有有效的正则表达式。其他人验证aa @ aach为真
netshark1000 '16

1
@ netshark1000,只有支持,任何答案都将放在首位。:)
阿西克·阿卜杜拉

NSRegularExpression比NSPredicate使用更简单
Guillaume Laurent

1
它不处理域名后的两个点条件。试试这个答案stackoverflow.com/a/53441176/5032981
Prashant Gaikwad

@AzikAbdullah如果您输入“ abc @ gmail..com”,那么它也会生效
Nij

110

作为String课程扩展

SWIFT 4

extension String {
    func isValidEmail() -> Bool {
        // here, `try!` will always succeed because the pattern is valid
        let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
        return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: count)) != nil
    }
}

用法

if "rdfsdsfsdfsd".isValidEmail() {

}

4
countElements现在count
Zack Shapiro

25
xxx @ yyy返回true吗?
卡伦SUN

1
与Cullen SU​​N相同,foo @ bar返回true。
雷米·维林(RémyVirin)

3
没有.tld的user @ host也是一个有效的电子邮件地址,例如root @ localhost
星期三

1
请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

64

如果您正在寻找一种干净且简单的解决方案,请查看https://github.com/nsagora/validation-components

它包含一个电子邮件验证谓词,可轻松集成到您的代码中:

let email = "test@example.com"
let rule = EmailValidationPredicate()
let isValidEmail = rule.evaluate(with: email)

引擎盖后面使用的是RFC 5322 reg ex(http://emailregex.com):

let regex = "(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}" +
    "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" +
    "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\p{L}0-9](?:[a-" +
    "z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-9])?|\\[(?:(?:25[0-5" +
    "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" +
    "9][0-9]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" +
    "-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"

3
哇,不知道emailregex.com。太棒了!
塞缪尔(Samuel Ev)2016年

2
最后,一个过滤器email。@。email.com
Ben Sullivan

它与确切-abcd@abcd.com一起工作。它不是有效的abc @ abc
Anil Gupta,

啊,终于..:d
Ümañgßürmån

39

这是合理的解决方案:

“合理的解决方案”

在许多海量应用中使用和测试了多年。

1-避免了许多可怕的正则表达式错误您在这些建议中经常看到

2- 不会让愚蠢的电子邮件,如“X @ X”,这被认为是在一定的RFC有效的,但完全傻了,无法使用电子邮件,并支持人员会立即拒绝,并全部邮件服务(mailchimp,google,aws等)只是拒绝。如果(由于某种原因)您需要一个允许诸如“ x @ x”之类的字符串的解决方案,请使用另一种解决方案。

3-代码是 非常非常容易理解

4-它是KISS,可靠,并且在具有大量用户的商业应用程序上经过测试,可以销毁

5-从技术角度讲,谓词是全球性的,正如Apple所说的那样(请注意没有此含义的代码建议)

let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
let __emailRegex = __firstpart + "@" + __serverpart + "[A-Za-z]{2,8}"
let __emailPredicate = NSPredicate(format: "SELF MATCHES %@", __emailRegex)

extension String {
    func isEmail() -> Bool {
        return __emailPredicate.evaluate(with: self)
    }
}

extension UITextField {
    func isEmail() -> Bool {
        return self.text!.isEmail()
    }
}

就这么简单。

说明:

在下面的描述中,“ OC”表示普通字符-字母或数字。

__firstpart ...必须以OC 开头和结尾。对于中间的字符,您可以使用某些字符(例如下划线),但开始和结束必须为OC。(然而,这是确定只生一个OC,就是这样,例如:j@blah.com)

__serverpart ...您有诸如“等等”之类的部分。其中重复。(因此,mail.city.fcu.edu类型。)这些部分必须以OC 开头和结尾,但是在中间,您也可以使用破折号 “-”。(如果您想允许其他不寻常的字符(可能是下划线),则只需在破折号前添加。)可以将一个部分仅仅是一个 OC。(与joe@w.campus.edu中的一样)您最多可以有五个部分,您必须有一个。最后是TLD(例如.com)是严格2〜8在尺寸。显然,只需更改您的支持部门首选的“ 8”即可。


重要!

您必须将谓词保持为全局,不要每次都构建它。

请注意,这是Apple在文档中提及整个问题的第一件事

当您看到不缓存谓词的建议时,这非常令人惊讶。


1
它是否支持新的顶级域名(如.engineer)?
罗马

嗨,@ Roman-注意,其中明确指出“最后,TLD(.com等)严格是2到8个字母。” 这样就好了。您可以将“ 8”更改为您喜欢的值。(目前,在许多大公司中,客户服务将只是拒绝所有长TLD只是一个骗局-但无论如何,这是您的决定,使用“ 8”或您喜欢的任何值。)
Fattie

2
关于第(4)点:您是如何与许多用户进行测试的?您是否跟踪了用户,因为正则表达式确实阻止了他们使用其电子邮件地址,所以无法注册商业应用程序?唯一的“合理”应该是规范(RFC)规定的内容,或者如果无法实现,则应该放宽一些,但涵盖规范中的所有内容。如果不允许用户输入x @ x,则他们将输入将通过您/任何正则表达式的垃圾@ example.com。
thetrutz '18

@thetrutz,您好,“ garbage@example.com”是完全正常的电子邮件地址。RFC包含理论上的惯用语,例如“ x @ x”。您或我曾经为之工作的任何实际商业客户都会说“禁止这些”。(注意,在任何现实世界的大型企业,也有很大的更多的比我的粗线条限制在这里,因为我在上面罗马注释更不用说了。)你最后一句是混淆了-当然是“非正常运作的电子邮件”将传递任何本地测试?你什么意思?显然,只有通过“确认您的电子邮件”系统才能最终验证电子邮件。
Fattie

在Swift中,需要优化每个流程,因为我们通常在服务器端使用此语言。
Nicolas Manzini

25

这是正确答案的两个最受好评的答案的融合:使用谓词的String扩展,因此您可以调用string.isEmail

    extension String {
        var isEmail: Bool {
           let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,20}"            
           let emailTest  = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
           return emailTest.evaluateWithObject(self)
        }
    }

19

Swift 5中最简单的方法

extension String {
    var isValidEmail: Bool {
        NSPredicate(format: "SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}").evaluate(with: self)
    }
}

"kenmueller0@gmail.com".isValidEmail

返回...

true

2
重复重复的答案有什么意义?不依赖于任何Swift 5功能
Rommex

17

我建议使用它作为String的扩展:

extension String {    
    public var isEmail: Bool {
        let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)

        let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length))

        return (firstMatch?.range.location != NSNotFound && firstMatch?.url?.scheme == "mailto")
    }

    public var length: Int {
        return self.characters.count
    }
}

并使用它:

if "hodor@gameofthrones.com".isEmail { // true
    print("Hold the Door")
}

1
请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

更新Swift 4:扩展字符串{公共var isEmail:布尔{让dataDetector =尝试?NSDataDetector(类型:NSTextCheckingResult.CheckingType.link.rawValue)让firstMatch = dataDetector? range.location!= NSNotFound && firstMatch?.url?.scheme ==“ mailto”)}
Duan Nguyen

15

这是Swift 2.0-2.2的更新版本

 var isEmail: Bool {
    do {
        let regex = try NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
        return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
    } catch {
        return false
    }
}

8
foo @ bar返回true吗?
雷米·维林(RémyVirin)

2
验证aa @ aach为真
netshark1000,2016年

4
那是因为RFC验证了这些电子邮件地址为true;)
dulgan

请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

不缓存谓词确实是错误的/很糟糕的。这是苹果公司在doco问题中所说的第一句话。页面上大多数答案都犯了一个明显的错误。
Fattie

9

这里有很多正确的答案,但是许多“ regex”不完整,可能会发生诸如“ name @ domain”之类的电子邮件产生有效的电子邮件,但事实并非如此。这里是完整的解决方案:

extension String {

    var isEmailValid: Bool {
        do {
            let regex = try NSRegularExpression(pattern: "(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", options: .CaseInsensitive)
            return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
        } catch {
            return false
        }
    }
}

不能正常工作,它使您可以在域后添加空格。
Juan Boero

请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

@Fattie争辩您的声明。您的评论非常无用,建议改进,提出解决方案。说完全错误是很愚蠢的,而且是一种紧密的心态
Andrea.Ferrando

“这里有很多正确答案”,这句话显然是错误的:) :)
Fattie

8

这是一种基于的方法rangeOfString

class func isValidEmail(testStr:String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let range = testStr.rangeOfString(emailRegEx, options:.RegularExpressionSearch)
    let result = range != nil ? true : false
    return result
}

注意:更新的TLD长度。

这是根据RFC 5322定义的电子邮件正则表达式,请注意,最好不要使用它,因为它仅检查电子邮件地址的基本语法,而不检查是否存在顶级域。

(?:[a-z0-9!#$%&'* + / =?^ _`{|}〜-] +(?:\。[a-z0-9!#$%&'* + / =?^ _`{|}〜-] +)*
  | “(?:[\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21 \ x23- \ x5b \ x5d- \ x7f]
      | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f])*“)
@(?:(?:[a-z0-9](?:[a-z0-9-] * [a-z0-9])?\。)+ [a-z0-9](?:[ a-z0-9-] * [a-z0-9])?
  | \ [(?:( ?: 25 [0-5] | 2 [0-4] [0-9] | [01]?[0-9] [0-9]?)\。){3}
       (?:25 [0-5] | 2 [0-4] [0-9] | [01]?[0-9] [0-9]?| [a-z0-9-] * [a- z0-9]:
          (?:[\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21- \ x5a \ x53- \ x7f]
          | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f])+)
     \])

Regular-Expressions.info有关电子邮件RegExs更全面的信息。

请注意,没有像Objective-C或Swift这样的语言必须进行转义。


1
您使用的emailRegEx完全是错误的。它仅允许2至4个字符长的TLD,而.engineer存在类似的域。
Antzi 2015年

可以理解,我不是捍卫自己的答案,而是捍卫编辑的水平。如上添加评论,不赞成投票,指向一个更好的答案,添加您自己的答案。实质上改变答案是不合适的。为了完整性,我添加了扩散性RegEx。
zaph 2015年

为什么哦,为什么不删除答案呢? 有什么可能的理由将其保留在这里?
Fattie

7

我更喜欢使用扩展名。此外,此URL http://emailregex.com可以帮助您测试正则表达式是否正确。实际上,该站点为某些编程语言提供了不同的实现。我分享了Swift 3的实现。

extension String {
    func validateEmail() -> Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
        return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
    }
}

有一些问题..您可能会遇到,例如..blah @ .abc,那里有一个怪异的点
Fattie

5

对于Swift 2.1:可以正常使用电子邮件foo @ bar

extension String {
    func isValidEmail() -> Bool {
        do {
            let regex = try NSRegularExpression(pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}", options: .CaseInsensitive)
            return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
        } catch {
                return false
        }
    }
}

1
这对我来说似乎很好。据我了解,您甚至可以省略'AZ'(大写字母),因为您仍然可以选择设置
.CaseInsensitive

请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

5

使用Swift 4.2

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$", options: .caseInsensitive)
        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
    }
    func isValidName() -> Bool{
        let regex = try? NSRegularExpression(pattern: "^[\\p{L}\\.]{2,30}(?: [\\p{L}\\.]{2,30}){0,2}$", options: .caseInsensitive)

        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
    } }

和二手

if (textField.text?.isValidEmail())! 
    {
      // bla bla
    }
else 
    {

    }

4

这是@Fattie的合理解决方案”的新版本,已在Swift 4.1的新文件中进行了测试String+Email.swift

import Foundation

extension String {
    private static let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
    private static let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
    private static let __emailRegex = __firstpart + "@" + __serverpart + "[A-Za-z]{2,6}"

    public var isEmail: Bool {
        let predicate = NSPredicate(format: "SELF MATCHES %@", type(of:self).__emailRegex)
        return predicate.evaluate(with: self)
    }
}

所以它的用法很简单:

let str = "mail@domain.com"
if str.isEmail {
    print("\(str) is a valid e-mail address")
} else {
    print("\(str) is not a valid e-mail address")
}

我只是不喜欢funcString对象上添加a ,因为电子邮件地址是对象固有的(或不是)。因此,根据我的理解,Bool属性比a更好func


2

创建简单的扩展名:

extension NSRegularExpression {

    convenience init(pattern: String) {
        try! self.init(pattern: pattern, options: [])
    }
}

extension String {

    var isValidEmail: Bool {
        return isMatching(expression: NSRegularExpression(pattern: "^[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"))
    }

    //MARK: - Private

    private func isMatching(expression: NSRegularExpression) -> Bool {
        return expression.numberOfMatches(in: self, range: NSRange(location: 0, length: characters.count)) > 0
    }
}

例:

"b@bb.pl".isValidEmail //true
"b@bb".isValidEmail //false

您可以将以下扩展名扩展到所需的任何内容:isValidPhoneNumberisValidPassword等等。


请注意,NSRange应该使用length属性String utf16.count而不是characters.count
Leo Dabus

模式是完全错误的
Fattie

2

Swift 4.2和Xcode 10.1中

//Email validation
func isValidEmail(email: String) -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    var valid = NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email)
    if valid {
        valid = !email.contains("Invalid email id")
    }
    return valid
}

//Use like this....
let emailTrimmedString = emailTF.text?.trimmingCharacters(in: .whitespaces)
if isValidEmail(email: emailTrimmedString!) == false {
   SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter valid email")
}

如果要使用SharedClass。

//This is SharedClass
import UIKit
class SharedClass: NSObject {

static let sharedInstance = SharedClass()

//Email validation
func isValidEmail(email: String) -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    var valid = NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email)
    if valid {
        valid = !email.contains("Invalid email id")
    }
    return valid
}

private override init() {

}
}

并像这样调用函数。

if SharedClass.sharedInstance. isValidEmail(email: emailTrimmedString!) == false {
   SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter correct email")
   //Your code here
} else {
   //Code here
}

1

我制作了一个用于输入验证的库,其中一个“模块”使您可以轻松验证一堆东西。

例如,验证电子邮件:

let emailTrial = Trial.Email
let trial = emailTrial.trial()

if(trial(evidence: "test@test.com")) {
   //email is valid
}

SwiftCop是图书馆...希望对您有所帮助!


1

这是Swift 3中的扩展

extension String {
    func isValidEmail() -> Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
    }
}

像这样使用它:

if yourEmailString.isValidEmail() {
    //code for valid email address
} else {
    //code for not valid email address
}

更改为使用alexcristea的答案中的Regex,这是一个完美的解决方案。
ittgung

0

由于现在有太多奇怪的顶级域名,所以我不再检查顶级域名的长度...

这是我使用的:

extension String {

    func isEmail() -> Bool {
        let emailRegEx = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
        return NSPredicate(format:"SELF MATCHES %@", emailRegEx).evaluateWithObject(self)
    } 
}

0

似乎也可以工作...

let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

func validate(email: String) -> Bool {
    let matches = email.rangeOfString(regex, options: .RegularExpressionSearch)
    if let _ = matches {
        return true
    }
    return false
}

0

更新了对Swift 2.2的答案@Arsonik答案,比其他提供的解决方案使用的详细代码更少:

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
        return regex?.firstMatchInString(self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
    }
}

abcd @ a与此正则表达式一起传递。您应该修复它。
Gunhan '17

请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus

0

@JeffersonBe的答案很接近,但是返回true的字符串是否是“我们想要的不是”包含某人某人的电子邮件。以下是String的扩展,该扩展运行良好(并允许测试有效的phoneNumber和其他数据检测器来启动。

/// Helper for various data detector matches.
/// Returns `true` iff the `String` matches the data detector type for the complete string.
func matchesDataDetector(type: NSTextCheckingResult.CheckingType, scheme: String? = nil) -> Bool {
    let dataDetector = try? NSDataDetector(types: type.rawValue)
    guard let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length)) else {
        return false
    }
    return firstMatch.range.location != NSNotFound
        // make sure the entire string is an email, not just contains an email
        && firstMatch.range.location == 0
        && firstMatch.range.length == length
        // make sure the link type matches if link scheme
        && (type != .link || scheme == nil || firstMatch.url?.scheme == scheme)
}
/// `true` iff the `String` is an email address in the proper form.
var isEmail: Bool {
    return matchesDataDetector(type: .link, scheme: "mailto")
}
/// `true` iff the `String` is a phone number in the proper form.
var isPhoneNumber: Bool {
    return matchesDataDetector(type: .phoneNumber)
}
/// number of characters in the `String` (required for above).
var length: Int {
    return self.characters.count
}

请注意,NSRange长度属性应使用String utf16.count代替character.count
Leo Dabus

0

对于Swift 3

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
    }
}

请注意,NSRange长度属性应使用String utf16.count代替character.count
Leo Dabus

0

我对响应列表的唯一补充是,对于Linux,NSRegularExpression它不存在,实际上RegularExpression

    func isEmail() -> Bool {

    let patternNormal = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"

    #if os(Linux)
        let regex = try? RegularExpression(pattern: patternNormal, options: .caseInsensitive)
    #else
        let regex = try? NSRegularExpression(pattern: patternNormal, options: .caseInsensitive)
    #endif

    return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil

这样可以在macOS和Ubuntu上成功编译。


请注意,NSRange长度属性应使用String utf16.count代替character.count
Leo Dabus

0

最佳解决方案,效果最佳

斯威夫特4.x

 extension String {

        func validateAsEmail() -> Bool {
            let emailRegEx = "(?:[a-zA-Z0-9!#$%\\&‘*+/=?\\^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%\\&'*+/=?\\^_`{|}" +
                "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" +
                "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-" +
                "z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5" +
                "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" +
                "9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" +
            "-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"

            let emailTest = NSPredicate(format:"SELF MATCHES[c] %@", emailRegEx)
            return emailTest.evaluate(with: self)
        }
    }

0

我喜欢创建扩展

   extension String {

func isValidateEmail() -> Bool {
    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluate(with: self)
}

}

用法:

if emailid.text!.isValidateEmail() == false(){
 //do what ever you want if string is not matched.

}

0

迅捷5

 func isValidEmailAddress(emailAddressString: String) -> Bool {

 var returnValue = true
 let emailRegEx = "[A-Z0-9a-z.-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,3}"

 do {
        let regex = try NSRegularExpression(pattern: emailRegEx)
        let nsString = emailAddressString as NSString
        let results = regex.matches(in: emailAddressString, range: NSRange(location: 0, length: nsString.length))

        if results.count == 0
        {
            returnValue = false
        }

    } catch let error as NSError {
        print("invalid regex: \(error.localizedDescription)")
        returnValue = false
    }

    return  returnValue
}

然后:

let validEmail = isValidEmailAddress(emailAddressString: "your@email.com")
print(validEmail)

0

完美的正则表达式,例如Google电子邮件

"^[A-Z0-9a-z][a-zA-Z0-9_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

2
谁投票支持我的答案,请检查您的知识。我已经在许多代码中应用了此正则表达式,而我的朋友正在使用该正则表达式,它的效果很好。
ami rt

我想我可以回答:您的正则表达式很简单,与RFC不匹配。例如,电子邮件的第一部分可以包含引号甚至空格!看看haacked.com/archive/2007/08/21/...
Hugal31

1
抱歉,兄弟,我认为您应该检查Google电子邮件验证,没有办法在电子邮件的第一部分中添加空格,如果我的正则表达式错误,那么为什么没有人发布可编写和完善的正则表达式。
ami rt

根据RFC 5322,“ Hello world!” @ example.com是有效的电子邮件。实际上,制作有效的正则表达式几乎是不可能的。并非每个邮件提供商都会坚持使用Google电子邮件验证。
Hugal31

1
那就是我想听的,这就是为什么我在粗体标题中提到正则表达式就像Google一样的原因。谢谢
ami rt

-1

或者,您可以扩展UITextField的可选文本:

如何使用:

if  emailTextField.text.isEmailValid() {
      print("email is valid")
}else{
      print("wrong email address")
}

延期:

extension Optional where Wrapped == String {
    func isEmailValid() -> Bool{
        guard let email = self else { return false }
        let emailPattern = "[A-Za-z-0-9.-_]+@[A-Za-z0-9]+\\.[A-Za-z]{2,3}"
        do{
            let regex = try NSRegularExpression(pattern: emailPattern, options: .caseInsensitive)
            let foundPatters = regex.numberOfMatches(in: email, options: .anchored, range: NSRange(location: 0, length: email.count))
            if foundPatters > 0 {
                return true
            }
        }catch{
            //error
        }
        return false
    }
}

请注意,NSRange长度属性应使用String utf16.count而不是character.count
Leo Dabus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.