Как проверить адрес электронной почты в swift?

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
перевод должен быть простым. какая часть доставляет вам проблемы?
Sulthan
12
Не забывайте молиться, чтобы ни у кого из ваших пользователей не было одного из новых доменов верхнего уровня. Например.coffee
Матиас Баух
1
@Antzi: я проверил с "somebody @ gmail", и ваше регулярное выражение вернуло true.
Донг
2
Регулярные выражения не работают для проверки того, что пользователи ввели свой адрес электронной почты. Единственный 100% правильный способ - отправить электронное письмо с кодом активации. Смотрите: я знал, как
проверить
2
Это захватывающий QA. Это почти наверняка "самый неправильный" контроль качества на всем сайте. В настоящее время ответ № 1 с 600 голосами (что ?!) абсолютно, абсолютно неверен во всех возможных отношениях (каждая отдельная строка совершенно неверна, а каждая концепция и идея ошибочны ........ !!!) Многие из других высоко оцененных ответов либо «совершенно неверны», «крайне неопрятны», либо просто разбиты и даже не компилируются. Кроме того, хотя природа этого Q требует «элитного регулярного выражения», многие ответы (высоко голосовали!) Приводят к ужасной разработке регулярных выражений. Это действительно интересный QA! Зачем??
Толстяк

Ответы:

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.
Sulthan
15
Он не проверяет, есть ли доступное расширение, a @ a уже в порядке :(
CularBytes
6
это не подходит для test @ test ... com
Alan
3
Это не обнаруживает электронную почту. @ Invalid.com или электронную почту @ .invalid.com. Ответ от @alexcristea ниже
Бен Салливан
3
Довольно забавно, что ............ а также (1) регулярное выражение совершенно, совершенно неверно (2) регулярное выражение (даже в контексте того, что он пытается сделать) имеет серьезные ошибки ( 3) Swift неправильный (4) даже если оставить в стороне, стиль совершенно неправильный (5) не то, чтобы он имел значение, учитывая все остальное, но он даже не упоминает, что вы должны кэшировать предикат ... с юмором, ( 6) есть еще код («календарь» - что?), Откуда он был скопирован.
Толстяк
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
Прашант Гайквад
@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() {

}
Arsonik
источник
4
countElementsсейчасcount
Зак Шапиро
25
ххх @ ггг верни истину?
Cullen SUN
1
Так же, как и Cullen SUN, foo @ bar возвращает true.
Реми Вирин
3
user @ host без .tld также является действительным адресом электронной почты, например, root @ localhost
ср.
1
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.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])+)\\])"
alexcristea
источник
3
Вау, не знал о emailregex.com. Это превосходно!
Самуил Эв
2
Наконец, тот, который фильтрует электронную почту. @. Email.com
Бен Салливан
он работает точно - abcd@abcd.com. это не валидно abc @ abc
Анил Гупта
Ах, наконец ..: D
mamañ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. (Однако это нормально , чтобы иметь только одну ОС , и это его, например: j@blah.com)

__serverpart ... У вас есть такие разделы, как "бла". которые повторяют . (Так что типа mail.city.fcu.edu.) Разделы должны начинаться и заканчиваться OC, но в середине вы также можете иметь тире "-". (Если вы хотите, чтобы другие необычные символы были там, возможно, подчеркивание, просто добавьте перед чертой.) Хорошо иметь раздел, который является только одним OC. (Как в joe@w.campus.edu) У вас может быть до пяти разделов, у вас должен быть один. Наконец, TLD (например, .com) строго от 2 до 8 дюймов размер. Очевидно, просто измените эту цифру «8», как предпочитает ваша служба поддержки.


ВАЖНЫЙ !

Вы должны хранить предикат как глобальный, не создавайте его каждый раз.

Обратите внимание, что это первое, что Apple упоминает о всей проблеме. в документации.

Это очень удивительно, когда вы видите предложения, которые не кэшируют предикат.

Fattie
источник
1
Поддерживает ли он новые TLD, такие как .engineer?
Роман
Привет @Roman - обратите внимание, где четко сказано: «Наконец, TLD (.com или тому подобное) строго 2-8 букв» Это позаботится об этом. Вы можете изменить «8» на значение, которое вы предпочитаете. (В настоящее время во многих крупных компаниях служба поддержки клиентов просто отвергает любые длинные TLD как мошенничество, но в любом случае это ваше решение, используйте «8» или любое
другое
2
Что касается пункта (4): как вы тестировали с большим количеством пользователей? Вы отслеживали пользователей, которые не могли зарегистрироваться в коммерческих приложениях, потому что регулярное выражение не позволяло им использовать свой адрес электронной почты? Единственным «разумным» должно быть то, что спецификация (RFC) определяет или, если это не может быть достигнуто, то что-то более смягченное, но охватывающее все из спецификации. Если пользователям не разрешено вводить x @ x, они введут некоторый garbage@example.com, который передаст ваше / любое регулярное выражение.
Thetrutz
hi @thetrutz, "garbage@example.com" - это совершенно нормальный адрес электронной почты. RFC включает в себя теоретический идиотизм, такой как «х @ х». любой реальный коммерческий клиент, на которого вы или я когда-либо работаете, скажет «запретить этим». (обратите внимание, что в любом крупном бизнесе реального мира здесь гораздо больше ограничений, чем мой грубый набросок, как я упоминаю в комментарии выше к Роману.) Ваше последнее предложение сбивает с толку - конечно, «неработающее письмо» пропустит любое местный тест? Что вы имеете в виду? Очевидно, что электронные письма в конечном итоге проверяются только через системы «подтвердите вашу электронную почту».
Толстяк
В 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
18

Я бы предложил использовать его как расширение строки:

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")
}
JeffersonBe
источник
1
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.count
Лео Дабус
Обновление Swift 4: расширение String {public var isEmail: Bool {let dataDetector = try? NSDataDetector (типы: NSTextCheckingResult.CheckingType.link.rawValue) range.location! = NSNotFound && firstMatch? .url? .scheme == "mailto")}
Дуан Нгуен,
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 ?!
Реми Вирин
2
проверяет aa @ aach на true
netshark1000
4
Это потому, что RFC проверяет правильность адресов электронной почты;)
Dulgan
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.count
Лео Дабус
это действительно неправильно / плохо не кэшировать предикат. это первое, что Apple говорит о проблеме в доко. вопиющая ошибка, допущенная большинством ответов на странице.
Толстяк
9

Здесь есть много правильных ответов, но многие из «регулярных выражений» являются неполными, и может случиться так, что электронное письмо типа: «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
        }
    }
}
Andrea.Ferrando
источник
не работает должным образом, позволяет добавлять пробелы после домена.
Хуан Боэро
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.count
Лео Дабус
@ Толстяк спорит с твоим утверждением. Ваш комментарий очень бесполезен, предлагает улучшение, предлагает исправление. Говорить совершенно неправильно - очень глупо и лежит в основе близкого менталитета
Андреа. Ферандо,
«Здесь много правильных ответов», это предложение
невероятно
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, обратите внимание, что это лучше не использовать, потому что он только проверяет основной синтаксис адресов электронной почты и не проверяет, существует ли домен верхнего уровня.

(: [А-z0-9 # $% & '* + / = ^ _ `{|} ~ - + (?.!: \ [А-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] (?: [ а-z0-9 -] * [а-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] | [а-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.

zaph
источник
1
emailRegEx, который вы используете, просто неверен. Допускается использование доменов верхнего уровня длиной от 2 до 4 символов, в то время как .engineerсуществуют подобные домены .
Антзи
Понял, я не защищаю свой ответ, но уровень редактирования. Добавьте комментарий, как указано выше, проголосуйте вниз, укажите лучший ответ, добавьте свой собственный ответ. Не стоит существенно менять ответ. Я добавил диффузный RegEx для полноты.
zaph
Почему бы тогда просто не удалить ответ? Какова возможная причина , чтобы держать это здесь?
Толстяк
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)
    }
}
Марлон Руис
источник
есть несколько проблем .. у вас может быть, например .. бла @ .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
        }
    }
}
lee5783
источник
1
Это, кажется, работает хорошо для меня. Насколько я понимаю, вы могли бы даже опустить 'AZ' (заглавные буквы), так как у вас есть опция .CaseInsensitive установлен в любом случае ...
AZOM
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.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свойство length следует использовать String utf16.countвместоcharacters.count
Leo Dabus
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
}
IOS
источник
1

Я сделал библиотеку, предназначенную для проверки входных данных, и один из «модулей» позволяет легко проверять кучу вещей ...

Например, чтобы подтвердить адрес электронной почты:

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

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

SwiftCop - это библиотека ... надеюсь, это поможет!

Andres
источник
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, это идеальное решение.
17
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)
    } 
}
snowmen10
источник
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
}
Logicopolis
источник
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 вместо characters.count
Лео Дабус
0

Ответ @ JeffersonBe близок, но возвращается, trueесли строка является «чем-то, содержащим кем-то@something.com действительный адрес электронной почты», а это не то, что нам нужно. Ниже приведено расширение для 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
}
Gujamin
источник
Обратите внимание, что свойство длины NSRange должно использовать String utf16.count вместо characters.count
Лео Дабус
0

И для Свифта 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 вместо characters.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 вместо characters.count
Лео Дабус
0

Лучшее решение с лучшим результатом для

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

Мне нравится создавать расширение

   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

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
}

Затем:

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
кто бы ни проголосовал за мой ответ, пожалуйста, проверьте свои знания. Я применил это регулярное выражение во многих кодах, и мои друзья используют это регулярное выражение, и оно прекрасно работает. Перед тем как проголосовать за мой ответ, пожалуйста, прокомментируйте и дайте мне знать, что не так с этим регулярным выражением.
Ами к.т.
Я думаю, что могу ответить: ваше регулярное выражение простое и не соответствует RFC. Например, электронные письма могут содержать кавычки и даже пробелы в первой части! Посмотрите на haacked.com/archive/2007/08/21/…
Hugal31
1
Извините, брат, я думаю, вы должны проверить валидацию электронной почты Google, нет способа добавить пробел в первую часть письма, и если мое регулярное выражение неверно, то почему никто не публикует и не совершенствует регулярное выражение.
Ами к.т.
Согласно 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 вместо characters.count
Лео Дабус