Làm thế nào để xác nhận một địa chỉ e-mail nhanh chóng?


338

Có ai biết làm thế nào để xác thực một địa chỉ email trong Swift không? Tôi tìm thấy mã này:

- (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;
    }
}

nhưng tôi không thể dịch nó sang Swift.


8
dịch nên đơn giản. phần nào mang lại cho bạn vấn đề?
Sulthan

12
Đừng quên cầu nguyện rằng không ai trong số những người dùng của bạn có một trong những tên miền cấp cao mới. Ví dụ:.coffee
Matthias Bauch

1
@Antzi: Tôi đã kiểm tra với "someone @ gmail" và regex của bạn trở lại đúng.
Đông An

2
Regexes không hoạt động để xác nhận rằng người dùng đã nhập địa chỉ email của họ. Cách duy nhất đúng 100% là gửi e-mail kích hoạt. Xem: Tôi đã biết cách xác thực địa chỉ email cho đến khi tôi đọc RFC
mouviciel

2
Đây là một QA hấp dẫn. Nó gần như chắc chắn là QA "sai nhất" trên toàn bộ trang web. Câu trả lời số 1 hiện tại với 600 phiếu (cái gì?!) Là hoàn toàn, hoàn toàn, sai theo mọi cách có thể (mọi dòng riêng lẻ là hoàn toàn sai, và mọi khái niệm và ý tưởng đều sai ........ !!!) Nhiều câu trả lời được đánh giá cao khác là "hoàn toàn sai", "cực kỳ xấu hổ", hoặc bị hỏng hoàn toàn và thậm chí không được biên dịch. Hơn nữa, trong khi bản chất của Q này đòi hỏi "kỹ thuật regex ưu tú", nhiều câu trả lời (được đánh giá cao!) Có tính năng kỹ thuật regex kinh khủng. Đó là một QA thực sự thú vị !! Tại sao??
Fattie

Câu trả lời:


769

Tôi sẽ sử dụng 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)
}

cho các phiên bản Swift sớm hơn 3.0:

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)
}

cho các phiên bản Swift sớm hơn 1.2:

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
sẽ không return emailTest.evaluateWithObject(testStr)đơn giản và dễ đọc hơn nhiều? So sánh với == truemột chút giống như Javascript.
Sulthan

15
Nó không kiểm tra xem có tiện ích mở rộng không, a @ a đã ổn rồi :(
CularBytes 12/07/2015

6
điều này không hợp lệ cho test @ test ... com
Alan

3
Điều này không phát hiện email. @ Không hợp lệ.com hoặc email @ .invalid.com. Câu trả lời dưới đây từ @alexcristea hiện
Ben Sullivan

3
Điều khá buồn cười là ............ cũng như (1) regex hoàn toàn không chính xác (2) regex (ngay cả trong bối cảnh những gì nó cố gắng làm) có lỗi lớn ( 3) Swift sai (4) thậm chí đặt sang một bên, phong cách hoàn toàn sai (5) không phải là vấn đề được đưa ra cho tất cả những người còn lại nhưng thậm chí còn không đề cập đến việc bạn phải lưu trữ vị ngữ ... một cách hài hước, ( 6) vẫn còn thừa mã ("lịch" - cái gì?) Từ bất cứ nơi nào nó được sao chép từ đó.
Fattie

115

Chỉnh sửa, cập nhật cho 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)

}

Câu trả lời gốc cho 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)

}

Nó hoạt động tốt.


2
đầu tiên với một regex hợp lệ. những người khác xác nhận aa @ aach thành đúng
Netshark1000

1
@ Netshark1000, chỉ với upvotes, bất kỳ câu trả lời sẽ được đặt lên hàng đầu. :)
Azik Abdullah

NSRegularExpression sử dụng đơn giản hơn NSPredicate
Guillaume Laurent

1
Nó không xử lý hai điều kiện dấu chấm sau tên miền. hãy thử câu trả lời này stackoverflow.com/a/53441176/5032981
Prashant Gaikwad

@AzikAbdullah Nếu bạn nhập 'abc @ gmail..com' thì nó cũng sẽ xác thực
Nij

110

Là một Stringphần mở rộng lớp học

Chuyển 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
    }
}

Sử dụng

if "rdfsdsfsdfsd".isValidEmail() {

}

4
countElementsbây giờcount
Zack Shapiro

25
xxx @ yyy trở lại có đúng không?
Cullen CN

1
Giống như Cullen SUN, foo @ bar trở lại đúng.
Rémy Virin

3
user @ host không có .tld cũng là một địa chỉ email hợp lệ, ví dụ: root @ localhost
Thứ tư,

1
Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

64

Nếu bạn đang tìm kiếm một giải pháp đơn giản và sạch sẽ để làm điều này, bạn nên xem https://github.com/nsagora/validation-components .

Nó chứa một vị từ xác thực email dễ dàng tích hợp trong mã của bạn:

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

Đằng sau mui xe, nó sử dụng 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
Ồ, không biết về emailregex.com. Thật là tuyệt vời
Samuel Ev

2
Cuối cùng, một bộ lọc email. @. Email.com
Ben Sullivan

nó hoạt động chính xác - abcd@abcd.com. nó không xác thực abc @ abc
Anil Gupta

À, Cuối cùng ..: D
Ümañg ßürmån

39

Đây là giải pháp hợp lý:

"GIẢI PHÁP HỢP LÝ"

Được sử dụng và thử nghiệm trong nhiều năm trong nhiều ứng dụng khối lượng lớn.

1 - nó tránh được nhiều lỗi regex khủng khiếp mà bạn thường thấy trong các đề xuất này

2 - KHÔNG cho phép các email ngu ngốc như "x @ x" được cho là hợp lệ theo một số RFC nhất định, nhưng hoàn toàn ngớ ngẩn, không thể được sử dụng làm email và nhân viên hỗ trợ của bạn sẽ từ chối ngay lập tức và tất cả dịch vụ gửi thư (mailchimp, google, aws, v.v.) chỉ cần từ chối. Nếu (vì một số lý do) bạn cần một giải pháp cho phép các chuỗi như 'x @ x', hãy sử dụng giải pháp khác.

3 - mã rất, rất, rất dễ hiểu

4 - đó là KISS, đáng tin cậy và đã được thử nghiệm để phá hủy trên các ứng dụng thương mại với số lượng người dùng khổng lồ

5 - một điểm kỹ thuật, vị ngữ là toàn cầu, như Apple nói rằng nó phải như vậy (coi chừng các đề xuất mã không có điều này)

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()
    }
}

Nó là dễ dàng.

Giải trình:

Trong mô tả sau đây, "OC" có nghĩa là ký tự bình thường - một chữ cái hoặc một chữ số.

__firstpart ... phải bắt đầu và kết thúc bằng OC. Đối với các ký tự ở giữa, bạn có thể có một số ký tự nhất định như gạch dưới, nhưng bắt đầu và kết thúc phải là một OC. (Tuy nhiên, nó ok để chỉ có một OC và đó là nó, ví dụ: j@blah.com)

__serverpart ... Bạn có các phần như "blah." mà lặp lại . (Vì vậy, loại mail.city.fcu.edu.) Các phần phải bắt đầu và kết thúc bằng OC, nhưng ở giữa, bạn cũng có thể có dấu gạch ngang "-". (Nếu bạn muốn cho phép khác nhân vật khác thường trong đó, có lẽ là dấu gạch dưới, chỉ cần thêm trước khi dấu gạch ngang.) Đó là OK để có một phần mà chỉ là một OC. (Như trong joe@w.campus.edu) Bạn có thể có tối đa năm phần, bạn phải có một phần. Cuối cùng, TLD (chẳng hạn như .com) có kích thước từ 2 đến 8. Rõ ràng, chỉ cần thay đổi "8" theo sở thích của bộ phận hỗ trợ của bạn.


QUAN TRỌNG !

Bạn phải giữ vị ngữ là toàn cầu, không xây dựng nó mỗi lần.

Lưu ý rằng đây là điều đầu tiên Apple đề cập đến toàn bộ vấn đề trong các tài liệu.

Thật đáng ngạc nhiên khi bạn thấy các đề xuất không lưu trữ vị ngữ.


1
Nó có hỗ trợ các TLD mới như .engineer không?
La Mã

hi @Roman - chú ý nơi ghi rõ ràng "Cuối cùng, TLD (.com hoặc tương tự) chỉ đúng 2 đến 8 chữ cái." Điều đó chăm sóc nó. Bạn có thể thay đổi "8" thành giá trị bạn thích. (Còn bây giờ, trong nhiều công ty lớn, dịch vụ khách hàng sẽ chỉ đơn giản là từ chối bất kỳ TLD dài như chỉ là một scam - nhưng dù sao, đó là quyết định của bạn, sử dụng "8" hoặc bất kỳ giá trị mà bạn như thế nào.)
Fattie

2
Liên quan đến điểm (4): bạn đã kiểm tra như thế nào với nhiều người dùng? Bạn đã theo dõi người dùng, điều đó không thể đăng ký với các ứng dụng thương mại, vì regex đã ngăn họ sử dụng địa chỉ email của họ? "Hợp lý" duy nhất nên là, những gì thông số kỹ thuật (RFC) chỉ định hoặc nếu điều này không thể đạt được, thì một cái gì đó thoải mái hơn, nhưng bao gồm mọi thứ từ thông số kỹ thuật. Nếu người dùng không được phép nhập x @ x, họ sẽ nhập một số rác@example.com sẽ vượt qua / bất kỳ regex nào của bạn.
thetrutz

hi @thetrutz, "Waste@example.com" là một địa chỉ email hoàn toàn bình thường. RFC bao gồm thành ngữ lý thuyết như "x @ x". bất kỳ khách hàng thương mại thực tế nào mà bạn hoặc tôi từng làm việc sẽ nói "không cho phép những người đó". (lưu ý rằng trong bất kỳ doanh nghiệp lớn nào trong thế giới thực, có rất nhiều hạn chế hơn so với phác thảo sơ bộ của tôi ở đây, như tôi đã đề cập trong phần bình luận ở trên với Roman.) xét nghiệm địa phương? Ý anh là gì? Rõ ràng là email cuối cùng chỉ được xác minh thông qua hệ thống "xác nhận email của bạn".
Fattie

Trong Swift cần phải tối ưu hóa mọi quy trình vì chúng ta thường sử dụng ngôn ngữ này ở phía máy chủ.
Nicolas Manzini

25

Đây là một cầu chì của hai câu trả lời được bình chọn nhiều nhất với biểu thức chính xác: phần mở rộng Chuỗi sử dụng vị ngữ để bạn có thể gọi chuỗi.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

Cách đơn giản nhất trong 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)
    }
}

Thí dụ

"kenmueller0@gmail.com".isValidEmail

trả lại ...

true

2
điểm lặp lại câu trả lời lặp đi lặp lại là gì? không phụ thuộc vào bất kỳ tính năng Swift 5 nào
rommex

17

Tôi sẽ đề nghị sử dụng nó như một phần mở rộng của 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
    }
}

Và để sử dụng nó:

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

1
Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

Cập nhật Swift 4: Chuỗi mở rộng {public var isEmail: Bool {let dataDetector = thử? NSDataDetector (các loại: NSTextCheckingResult.CheckingType.link.rawValue) hãy để FirstMatch = dataDetector? .FirstMatch (in: self, tùy chọn: NSRegularExpression.MatchingOptions.reportCompletion !? range.location = NSNotFound && firstMatch .url .scheme == "mailto")}
Duẩn Nguyễn

15

Đây là phiên bản cập nhật cho 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
Thanh foo @ trả về có đúng không?!
Rémy Virin

2
xác thực aa @ aach thành đúng
Netshark1000

4
Đó là bởi vì RFC xác nhận các địa chỉ email này là đúng;)
dulgan

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

thật sự sai / kém khi không lưu trữ vị ngữ. đó là điều đầu tiên Apple nói về vấn đề trong tài liệu. một lỗi sai rõ ràng được thực hiện bởi hầu hết các câu trả lời trên trang.
Fattie

9

Có rất nhiều câu trả lời đúng ở đây, nhưng nhiều "regex" không đầy đủ và có thể xảy ra rằng một email như: "name @ domain" dẫn đến một email hợp lệ, nhưng thực tế không phải vậy. Đây là giải pháp hoàn chỉnh:

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
        }
    }
}

không hoạt động đúng, nó cho phép bạn thêm khoảng trắng sau tên miền.
Juan Boero

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

@Fattie tranh luận về tuyên bố của bạn. Nhận xét của bạn là rất vô dụng, đề nghị cải tiến, đề xuất sửa chữa. Nói sai hoàn toàn là rất ngu ngốc và làm nền tảng cho một tâm lý gần gũi
Andrea.Ferrando

"Có rất nhiều câu trả lời đúng ở đây" câu đó không chính xác một cách ngoạn mục :) :)
Fattie

8

Đây là một phương pháp dựa trên 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
}

Lưu ý: cập nhật chiều dài TLD.

Dưới đây là RegEx dứt khoát cho email theo RFC 5322, lưu ý rằng điều này tốt nhất không được sử dụng vì nó chỉ kiểm tra cú pháp cơ bản của địa chỉ email và không kiểm tra là tên miền cấp cao nhất tồn tại.

(?: [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- \ x 8
          | \ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f]) +)
     \])

Xem Thường xuyên-Expressions.info để biết thêm thông tin đầy đủ về email RegExs.

Lưu ý rằng không có lối thoát nào theo yêu cầu của một ngôn ngữ như Objective-C hoặc Swift.


1
emailRegEx bạn sử dụng hoàn toàn sai. Nó chỉ cho phép TLD dài từ 2 đến 4 ký tự, trong khi các tên miền như .engineertồn tại.
Antzi

Hiểu rồi, tôi không bảo vệ câu trả lời của mình mà là mức độ chỉnh sửa. Thêm một nhận xét như trên, bỏ phiếu xuống, chỉ ra một câu trả lời tốt hơn, thêm câu trả lời của riêng bạn. Nó không thích hợp để thay đổi đáng kể một câu trả lời. Tôi đã thêm RegEx khuếch tán cho đầy đủ.
zaph

Tại sao oh tại sao không xóa câu trả lời sau đó? Lý do nào có thể có để giữ nó ở đây?
Fattie

7

Tôi thích sử dụng một phần mở rộng cho điều đó. Ngoài ra, url này http://emailregex.com có thể giúp bạn kiểm tra xem regex có đúng không. Trong thực tế, trang web cung cấp các triển khai khác nhau cho một số ngôn ngữ lập trình. Tôi chia sẻ việc triển khai cho 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)
    }
}

có một vài vấn đề .. bạn có thể có, ví dụ .. blah @ .abc với một dấu chấm kỳ lạ ở đó
Fattie

5

Đối với swift 2.1: điều này hoạt động chính xác với email 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
Điều này dường như làm việc tốt cho tôi. Theo như tôi hiểu, bạn thậm chí có thể bỏ qua 'AZ' (chữ in hoa) vì bạn có tùy chọn .CaseInsensitive được đặt dù sao ...
AZOM

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

5

Sử dụng 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
    } }

Và được sử dụng

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

    }

4

Đây là phiên bản mới cho "GIẢI PHÁP HỢP LÝ" của @Fattie, đã thử nghiệm trên Swift 4.1 trong một tệp mới có tên 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)
    }
}

Vì vậy, cách sử dụng của nó rất đơn giản:

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")
}

Tôi chỉ đơn giản là không muốn thêm a funcvào các Stringđối tượng, vì là một địa chỉ email là vốn có của chúng (hoặc không). Vì vậy, một Booltài sản sẽ phù hợp hơn một func, từ sự hiểu biết của tôi.


2

Tạo phần mở rộng đơn giản:

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
    }
}

Thí dụ:

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

Bạn có thể mở rộng phần mở rộng sau cho bất cứ thứ gì bạn cần : isValidPhoneNumber, isValidPasswordv.v ...


Lưu ý rằng NSRangetài sản có độ dài nên sử dụng String utf16.countthay vìcharacters.count
Leo Dabus

mô hình hoàn toàn sai
Fattie

2

Trong Swift 4.2 và 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")
}

Nếu bạn muốn sử dụng 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() {

}
}

Và gọi chức năng như thế này ....

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

Tôi đã tạo một thư viện được thiết kế để xác thực đầu vào và một trong những "mô-đun" cho phép bạn dễ dàng xác thực một loạt các công cụ ...

Ví dụ để xác thực một email:

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

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

SwiftCop là thư viện ... hy vọng nó có ích!


1

Đây là một phần mở rộng trong 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)
    }
}

Chỉ cần sử dụng nó như thế này:

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

Thay đổi để sử dụng Regex từ câu trả lời của alexcristea, đó là giải pháp hoàn hảo.
ittgung

0

Vì hiện tại có rất nhiều tên miền cấp cao kỳ lạ, tôi ngừng kiểm tra độ dài của tên miền hàng đầu ...

Đây là những gì tôi sử dụng:

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

Có vẻ như cũng làm việc ...

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

Câu trả lời được cập nhật @Arsonik trả lời cho Swift 2.2, sử dụng ít mã dài dòng hơn các giải pháp được cung cấp khác:

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 đang vượt qua với regex này. Bạn nên sửa nó.
Gunhan

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

0

Câu trả lời của @ JeffersonBe rất gần, nhưng trả về truenếu chuỗi đó là "thứ gì đó có chứa email của ai đó @ email" không phải là thứ chúng tôi muốn. Sau đây là tiện ích mở rộng trên Chuỗi hoạt động tốt (và cho phép kiểm tra phoneNumber hợp lệ và các trình phát hiện dữ liệu khác để khởi động.

/// 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
}

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

0

Và cho 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
    }
}

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

0

Bổ sung duy nhất của tôi vào danh sách các câu trả lời sẽ là đối với Linux, NSRegularExpressionkhông tồn tại, nó thực sự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

Điều này biên dịch thành công trên cả macOS & Ubuntu.


Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus

0

Giải pháp tốt nhất với kết quả tốt nhất cho

Swift 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

Tôi thích tạo phần mở rộng

   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)
}

}

sử dụng:

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

}

0

Swift 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
}

Sau đó:

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

0

Regex hoàn hảo như Google Email

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

2
Bất cứ ai bỏ phiếu cho câu trả lời của tôi, vui lòng kiểm tra kiến ​​thức của bạn. Tôi đã áp dụng regex này trong nhiều mã và bạn bè của tôi đang sử dụng regex này và nó hoạt động rất tốt. Trước khi bỏ phiếu, câu trả lời của tôi vui lòng bình luận và cho tôi biết điều gì sai với regex này.
ami rt

Tôi nghĩ rằng tôi có thể trả lời: regex của bạn đơn giản và không phù hợp với RFC. Ví dụ, email có thể có dấu ngoặc kép và thậm chí khoảng trắng trong phần đầu tiên! Nhìn vào haacked.com/archive 2007/08/21/21
Hrif31

1
Xin lỗi, anh bạn, tôi nghĩ bạn nên kiểm tra xác thực email của google, không có cách nào để thêm Space vào phần đầu của email và nếu regex của tôi sai thì tại sao không ai đăng bài viết và regex hoàn hảo.
ami rt

Theo RFC 5322, "Xin chào thế giới!" @ Example.com là một email hợp lệ. Thật vậy, gần như không thể thực hiện một regex hợp lệ. Không phải mọi nhà cung cấp thư sẽ dính vào xác nhận email của google.
Hrif31

1
Đó là những gì tôi muốn nghe, và đó là lý do tại sao tôi đã đề cập trong tiêu đề táo bạo rằng regex ở trên giống như Google. Cảm ơn
ami rt

-1

Hoặc bạn có thể có phần mở rộng cho văn bản tùy chọn của UITextField:

cách sử dụng:

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

sự mở rộng:

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
    }
}

Lưu ý rằng thuộc tính độ dài NSRange nên sử dụng Chuỗi utf16.count thay vì character.count
Leo Dabus
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.