Regular Expression Swift 3

I see there is a constraint in my regular expressions which i am not understanding when validating email address.

When using "dot" before @

eg: abc.12@gmail.com . It is validating.

But when i don't use "dot" before @

eg: abc12@gmail.com . It is not validating. Means i am not able to login the user using this kind of email format ?

Replies

I am not sure if I understand your problem, but adding the dot, you are saying that there will be exactly one character other than newline in the pattern. You could use


abc\.*12@gmail.com


The star is to indicate that there will be zero or more occurences. The back slash is also important, because dot matches any character except newline and backslash and dot matches dot only. So if you want to capture dot and not any character, you should use "\." instead of "."


Both the following are captred by the pattern above:

abc.12@gmail.com

abc12@gmail.com

This is the regex i am using to validate email address.


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


This regex is validating when i enter email address like this

eg : alex.smith@gmail.com ( Please note i am using dot between two names) . It is working fine.


But it is not working when i enter email address like this

eg: alexsmith12@gmail.com ( Please note i didn't used dot here ) . May i know why it is not working ? If so can anyone provide the correct regex ?

Your regex does match both of your example email addresses when I try with Swift 3.0.2 in an Xcode 8.2.1 playground. (Some valid addresses will fail to be matched and some invalid addresses will be matched, though.)


Might be a good idea to post your code that tests the regex matching.

The regex you posted seems to work fine for me for the two examples you provided - it validates both alex.smith@gmail.com and alexsmith12@gmail.com, but limits the domain to 3 characters. Addresses like alex.smith@domain.info wont validate.


Two regexes that worked for me (these are plain patterns, do not include Swift escape characters, i.e. \. vs. \\.)


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


and this more thorough one:


(?:[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])+)\])

I hate to be the bearer of bad news but attempting to validate an email address in this way is both difficult and counter productive. We specifically addressed this in WWDC 2016 Session 714 Networking for the Modern Internet. Quoting from the transcript:

Email addresses are also becoming internationalized today. And this is also not hard to do, but users face problems for a silly, trivial reason. Many apps, when you sign up for an account or you go onto the website to sign up for an account, they try to validate if the email address is valid and they check whether it ends in

.com
or things of that form. And users with perfectly valid email addresses are not allowed to sign up for accounts because their email address is rejected. So we need to remove those ill-advised validators. Really the only thing you can check for in an email address is it has to have an @ sign. And if it's got that, it could be a valid email address. If you want to know if it's valid, send a validation email and have the user respond to confirm that it's live. If you're writing an email client or an email server, there are a bunch of RFCs you are going to need to look at.

I’m not going to pick holes in the specific patterns posted here, but it’s safe to say that they all either:

  • Reject valid email addresses

  • Accept invalid ones

  • or both

Of these problems, the first one is the most annoying. I have a friend who’s attempt to switch to a new email address is being stymied because many sites don’t recognise the new top-level domains that have sprung up in recent years.

It’s also worth considering the second problem: your back end systems still have to deal with folks entering invalid email addresses, so all you’re doing here is reducing the chances of that code being tested properly (-:

Whatever else you do here, I strongly recommend that you make this check advisory. If the email address looks wrong, let the user know but, if they insist, allow them to continue.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

@IBAction func register_pressed(_ sender: AnyObject) {

if full_name.text == "" || phone.text == "" || register_email.text == "" || register_password.text == "" || register_address.text == "" || register_postcode.text == "" {

displayAlert(title: "Alert", message: "Please enter all the fields")

}

if (register_email.text?.characters.count)! > 0 {

if isValidEmail(emailAddressStr: self.register_email.text!) {

displayAlert(title: "Message", message: "Email Address is valid")

}

} else {

displayAlert(title: "Alert", message: "Email Address is invalid")

}

Alamofire.request(server_url+"register.php", parameters: ["email":register_email.text!,"password":register_password.text!,"phone":phone.text!,"fullname":full_name.text!])

.responseJSON { response in

if let JSON = response.result.value {

print("JSON: \(JSON)")

let dict = JSON as! Dictionary<String,String>

if dict["success"] == "1" {

let defaults = UserDefaults.standard

defaults.set(self.register_email.text!, forKey: "email")

if self.delegate != nil {

self.dismiss(animated: false, completion: {

self.delegate?.did_login()

})

}

else{

self.dismiss(animated: false, completion: nil)

}

}

}

}

}

func displayAlert(title: String, message: String) {

let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)

alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))

present(alertController, animated: true, completion: nil)

}

func isValidEmail(emailAddressStr:String) -> Bool {

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

let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)

return emailTest.evaluate(with: emailAddressStr)

Your email validation function does return true for the example email addresses that you provided earlier. A leading or trailing space in the address will invalidate it, though, so maybe you've been accidentally including one. (There is a useful trimmingCharacters(in:) method on String). Anyway, I think you'd be best to follow eskimo's advice.


By the way, consider using guard statements to reduce/avoid nesting of ifs and much unwrapping of optionals - it will make your code easier to write, read and maintain.