Як швидко перевірити електронну адресу?


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

але я не можу перевести це на Свіфт.


8
переклад повинен бути прямим. яка частина доставляє вам проблеми?
Султан

12
Не забувайте молитися, щоб ніхто з ваших користувачів не мав одного з нових доменів верхнього рівня. Напр..coffee
Маттіас Баух

1
@Antzi: Я перевірив "хтось @ gmail", і ваш регекс повернув істину.
Đông

2
Regexes не працює для перевірки того, що користувачі ввели свою адресу електронної пошти. Єдиний на 100% правильний спосіб - надіслати активаційну електронну пошту. Дивіться: Я знав, як
перевірити

2
Це захоплюючий QA. Майже напевно це "самий неправильний" QA на всьому сайті. Нині відповідь №1 із 600 голосами (що ?!) абсолютно, абсолютно, неправильно всіляко (кожен окремий рядок абсолютно неправильний, а кожна концепція та ідея - неправильна ........ !!!) Багато хто з інших голосуючих відповідей або "абсолютно неправильні", "надзвичайно похмурі", або, звичайно, зламані і навіть не складаються. Крім того, хоча природа цього питання вимагає "елітарного інженерного генерування", у багатьох відповідях (високо проголосованих!) Є жахлива інженерія. Це дійсно цікавий QA !! Чому ??
Fattie

Відповіді:


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

для версій Swift раніше 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)
}

для версій Swift раніше 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
не return emailTest.evaluateWithObject(testStr)було б набагато простіше і читабельніше? Порівняння з == trueтрохи схожим на Javascript.
Султан

15
Він не перевіряє, чи є розширення доступне, а @ a вже в порядку :(
CularBytes

6
це не підтверджує тест @ test ... com
Алан

3
Це не виявляє електронну пошту. @ Invalid.com або email @ .invalid.com. Відповідь нижче від @alexcristea
Бен Салліван

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

1
@ netshark1000, лише з оновленнями, будь-яка відповідь буде зверху. :)
Азік Абдулла

NSRegularExpression простіший у використанні, ніж NSPredicate
Гійом Лоран

1
Він не обробляє умови двох точок після доменного імені. спробуйте цю відповідь stackoverflow.com/a/53441176/5032981
Prashant Gaikwad

@AzikAbdullah Якщо ввести «а @ gmail..com» , то також буде перевіряти
Нідж

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
Зак Шапіро

25
xxx @ yyy повернути правду?
Cullen SUN,

1
Те саме, що Cullen SUN, foo @ bar повертає істину.
Ремі Вірін

3
user @ host without .tld також є дійсною адресою електронної пошти, наприклад, root @ localhost
ср.

1
Зауважте, що властивість довжини NSRange має використовувати String utf16.count замість символів.count
Лев Дабус

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. Це приголомшливо!
Самуїл Єв

2
Нарешті, той, який фільтрує електронну пошту. @. Email.com
Бен Салліван

це працює з точним - abcd@abcd.com. це не підтверджено abc @ abc
Аніл Гупта

Ага, нарешті ..: 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
Чи підтримує він такі нові TLD, як інженер?
Роман

привіт @ Роман - зауважте, де чітко написано: "Нарешті, TLD (.com чи подібне) суворо від 2 до 8 букв". Це піклується про це. Ви можете змінити значення "8" на бажане значення. (Наразі в багатьох великих компаніях служба обслуговування клієнтів просто відхиляє будь-які довгі TLD як просто афера - але все одно, це ваше рішення, використовуйте "8" або будь-яке значення, яке вам подобається.)
Fattie

2
Що стосується пункту 4: як ви пройшли тестування з великою кількістю користувачів? Ви відстежували користувачів, які не могли зареєструватися з комерційними програмами, тому що регулярний геть не дозволяв їм використовувати свою електронну адресу? Єдиним "розумним" повинно бути те, що конкретизує специфікація (RFC) або якщо цього неможливо досягти, то те, що є більш спокійним, але охоплює все від специфікації. Якщо користувачам заборонено вводити x @ x, вони введуть garbage@example.com, який передасть ваш / будь-який регулярний вираз.
thetrutz

привіт @thetrutz, "garbage@example.com" - це абсолютно нормальна адреса електронної пошти. RFC включає теоретичну ідіотичність на кшталт "x @ x". будь-який фактичний комерційний клієнт, для якого ви чи я працюю, скаже «заборонити це». (зауважте, що в будь-якому великому бізнесі реального світу тут набагато більше обмежень, ніж у моїй грубій схемі, як я згадую в коментарі до Романа.) Ваше останнє речення заплутане - звичайно, "непрацюючий електронний лист" пройде будь-який місцевий тест? Що ви маєте на увазі? Очевидно, що електронні листи підтверджуються лише в остаточному підсумку через системи "підтвердження електронної пошти".
Fattie

У Swift є необхідність оптимізувати кожен процес, оскільки ми зазвичай використовуємо цю мову на стороні сервера.
Ніколя Манзіні

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 замість символів.count
Лев Дабус

Оновлення Swift 4: рядок розширення {public var isEmail: Bool {хай dataDetector = спробуйте? NSDataDetector (типи: NSTextCheckingResult.CheckingType.link.rawValue) нехай firstMatch = dataDetector? .FirstMatch (in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange (location: 0, length: count)) return 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 повертає правду ?!
Ремі Вірін

2
перевіряє aa @ aach на правду
netshark1000

4
Це тому, що RFC підтверджує ці адреси електронної пошти істинними;)
dulgan

Зауважте, що властивість довжини NSRange має використовувати String utf16.count замість символів.count
Лев Дабус

насправді неправильно / погано не кешувати присудок. це перше, що Apple каже про цю проблему в doco. очевидна помилка, допущена більшістю відповідей на сторінці.
Fattie

9

Тут є багато правильних відповідей, але багато з "регулярних виразів" є неповними, і може статися так, що електронний лист типу "ім'я @ домен" призводить до дійсної електронної пошти, але це не так. Ось повне рішення:

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

не працює належним чином, дозволяє додавати пробіли після домену.
Хуан Боеро

Зауважте, що властивість довжини NSRange має використовувати String utf16.count замість символів.count
Лев Дабус

@Fattie аргументує вашу заяву. Ваш коментар дуже марний, пропонуйте покращення, запропонуйте виправлення. Сказати абсолютно неправильно, дуже
дурно

«Є багато правильних відповідей тут» , що пропозиція ефектно неправильно :) :)
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.

Ось остаточний RegEx для електронної пошти відповідно до 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, який ви використовуєте, якраз неправильний. Це дозволяє лише для TLD від 2 до 4 символів, тоді як такі домени .engineerіснують.
Анци

Зрозумів, я не захищаю свою відповідь, але рівень редагування. Додайте коментар, як зазначено вище, голосування вниз, вкажіть на кращу відповідь, додайте власну відповідь. Суттєво змінювати відповідь не доцільно. Я додав дифузний RegEx для повноти.
zaph

Чому о, чому б тоді просто не видалити відповідь? Яка можлива причина могла б утримати його тут?
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

Для швидкого 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" (великі літери), оскільки у вас є можливість. Set CaseInsensitive встановити ...
AZOM

Зауважте, що властивість довжини NSRange має використовувати String utf16.count замість символів.count
Лев Дабус

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

Мені просто не подобається додавати funcдо Stringоб’єктів, оскільки адреса електронної пошти їм властива (або ні). Отже , з мого розуміння, Boolвласність підходила б краще, ніж а 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

Ви можете розширити наступне розширення на все, що вам потрібно: isValidPhoneNumberі isValidPasswordт.д. ...


Зауважте, що NSRangeвластивість довжини слід використовувати String utf16.countзамістьcharacters.count
Лео Дабус

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
}

Змінивши використання Regex з відповіді alexcristea, це ідеальне рішення.
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

Оновлена ​​відповідь @Arsonik відповідь на Swift 2.2, використовуючи менш багатослівний код, ніж інші пропоновані рішення:

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 проходить із цим регулярним виразом. Ви повинні це виправити.
Гунхань

Зауважте, що властивість довжини NSRange має використовувати String utf16.count замість символів.count
Лев Дабус

0

@ Відповідь ДжефферсонБе близька, але повертається, trueякщо рядок є "чимось, що містить когось@something.com, дійсний електронний лист", який не є тим, що ми хочемо. Далі йде розширення на String, яке працює добре (і дозволяє перевірити чинність телефонних номерів та інших детекторів даних для завантаження).

/// 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 замість символів.count
Лев Дабус

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 замість символів.count
Лев Дабус

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 замість символів.count
Лев Дабус

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

Ідеальний Regex, як Google Email

"^[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, "Привіт, світ!" @ 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 замість символів.count
Лев Дабус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.