What are best practices for validating email addre

2020-01-23 10:09发布

What is the cleanest way to validate an email address that a user enters on iOS 2.0?

NOTE: This is a historical question that is specific to iOS 2.0 and due to its age and how many other questions are linked to it it cannot be retired and MUST NOT be changed to a "modern" question.

13条回答
太酷不给撩
2楼-- · 2020-01-23 10:48

Many web sites provide RegExes but you'd do well to learn and understand them as well as verify that what you want it to do meets your needs within the official RFC for email address formats.

For learning RegEx, interpreted languages can be a great simplifier and testbed. Rubular is built on Ruby, but is a good quick way to test and verify: http://www.rubular.com/

Beyond that, buy the latest edition of the O'Reilly book Mastering Regular Expressions. You'll want to spend the time to understand the first 3 or 4 chapters. Everything after that will be building expertise on highly optimized RegEx usage.

Often a series of smaller, easier to manage RegExes are easier to maintain and debug.

查看更多
迷人小祖宗
3楼-- · 2020-01-23 10:49

Here is an extension of String that validates an email in Swift.

extension String {

    func isValidEmail() -> Bool {
        let stricterFilter = false
        let stricterFilterString = "^[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"
        let laxString = "^.+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2}[A-Za-z]*$"
        let emailRegex = stricterFilter ? stricterFilterString : laxString
        let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
        return emailTest.evaluate(with: self)
    }
}

Copied from the answer to: Check that an email address is valid on iOS

查看更多
老娘就宠你
4楼-- · 2020-01-23 10:51

Digging up the dirt, but I just stumbled upon SHEmailValidator which does a perfect job and has a nice interface.

查看更多
做个烂人
5楼-- · 2020-01-23 10:58

Read the RFC. Almost everyone that thinks they know how to parse/clean/validate an email address is wrong.

http://tools.ietf.org/html/rfc2822 Section 3.4.1 is very useful. Notice

dtext           =       NO-WS-CTL /     ; Non white space controls

                        %d33-90 /       ; The rest of the US-ASCII
                        %d94-126        ;  characters not including "[",
                                        ;  "]", or "\"

Yes, that means +, ', etc are all legit.

查看更多
该账号已被封号
6楼-- · 2020-01-23 11:03

You shouldn't try to use regex to validate an email. With ever changing TLDs, your validator is either incomplete or inaccurate. Instead, you should leverage Apple's NSDataDetector libraries which will take a string and try to see if there are any known data fields (emails, addresses, dates, etc). Apple's SDK will do the heavy lifting of keeping up to date with TLDs and you can piggyback off of their efforts!! :)

Plus, if iMessage (or any other text field) doesn't think it's an email, should you consider an email?

I put this function in a NSString category, so the string you're testing is self.

- (BOOL)isValidEmail {
    // Trim whitespace first
    NSString *trimmedText = [self stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
    if (self && self.length > 0) return NO;

    NSError *error = nil;
    NSDataDetector *dataDetector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:&error];
    if (!dataDetector) return NO;

    // This string is a valid email only if iOS detects a mailto link out of the full string
    NSArray<NSTextCheckingResult *> *allMatches = [dataDetector matchesInString:trimmedText options:kNilOptions range:NSMakeRange(0, trimmedText.length)];
    if (error) return NO;
    return (allMatches.count == 1 && [[[allMatches.firstObject URL] absoluteString] isEqual:[NSString stringWithFormat:@"mailto:%@", self]]);
}

or as a swift String extension

extension String {
    func isValidEmail() -> Bool {
        let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty, let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
            return false
        }
        let allMatches = dataDetector.matches(in: trimmed, options: [], range: NSMakeRange(0, trimmed.characters.count))

        return allMatches.count == 1 && allMatches.first?.url?.absoluteString == "mailto:\(trimmed)"
    }
}
查看更多
beautiful°
7楼-- · 2020-01-23 11:04

A good start is to decide what do you and do you not want to accept as an email address?

99% of of email addresses look like this: bob.smith@foo.com or fred@bla.edu

However, it's technically legal to have an email address like this: f!#$%&'*+-/=?^_{|}~"ha!"@com

There are probably only a handful of valid emails in the world for top-level domains, and almost nobody uses most of those other characters (especially quotes and backticks), so you might want to assume that these are all invalid things to do. But you should do so as a conscious decision.

Beyond that, do what Paul says and try to match the input to a regular expression like this: ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$

That one will match pretty much everybody's email address.

查看更多
登录 后发表回答