Ruby Email validation with regex

RubyRegexValidationEmail

Ruby Problem Overview


I have a large list of emails I am running through. A lot of the emails have typos. I am trying to build a string that will check valid emails.

this is what I have for regex.

def is_a_valid_email?(email)
  (email =~ /^(([A-Za-z0-9]*\.+*_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\+)|([A-Za-z0-9]+\+))*[A-Z‌​a-z0-9]+@{1}((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,4}$/i)
end

It passes if an email as underscores and only one period. I have a lot of emails that have more then one periods in the name itself. How do I check that in regex.

[email protected] # <~~ valid
foo.bar#gmail.co.uk # <~~~ not valid
[email protected] # <~~~valid 
[email protected] # <~~ not valid 
get_at_m.e@gmail  #<~~ valid

Can someone help me rewrite my regex ?

Ruby Solutions


Solution 1 - Ruby

This has been built into the standard library since at least 2.2.1

URI::MailTo::EMAIL_REGEXP

Solution 2 - Ruby

TL;DR:

credit goes to @joshuahunter (below, upvote his answer). Included here so that people see it.

URI::MailTo::EMAIL_REGEXP
Old TL;DR
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

###Original answer

You seem to be complicating things a lot, I would simply use:

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

which is taken from michael hartl's rails book

since this doesn't meet your dot requirement it can simply be ammended like so:

VALID_EMAIL_REGEX = /\A([\w+\-]\.?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

As mentioned by CAustin, there are many other solutions.

EDIT:

it was pointed out by @installero that the original fails for subdomains with hyphens in them, this version will work (not sure why the character class was missing digits and hyphens in the first place).

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

Solution 3 - Ruby

Here's a great article by David Celis explaining why every single regular expression you can find for validating email addresses is wrong, including the ones above posted by Mike.

From the article:

> The local string (the part of the email address that comes before the > @) can contain the following characters: > ! $ & * - = ^ | ~ # % ' + / ? _ { }` > > But guess what? You can use > pretty much any character you want if you escape it by surrounding it > in quotes. For example, "Look at all these spaces!"@example.com is a > valid email address. Nice.

If you need to do a basic check, the best regular expression is simply /@/.

Solution 4 - Ruby

This one is more short and safe:

/\A[^@\s]+@[^@\s]+\z/

The regular is used in Devise gem. But it has some vulnerabilities for these values:

  ".....@a....",
  "david.gilbertson@SOME+THING-ODD!!.com",
  "a.b@example,com",
  "a.b@example,co.de"

I prefer to use regexp from the ruby library URI::MailTo::EMAIL_REGEXP

There is a gem for email validations

Email Validator

Solution 5 - Ruby

Nowadays Ruby provides an email validation regexp in its standard library. You can find it in the URI::MailTo module, it's URI::MailTo::EMAIL_REGEXP. In Ruby 2.4.1 it evaluates to

/\A[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])?)*\z/

But I'd just use the constant itself.

Solution 6 - Ruby

I guess the example from the book can be improved to match emails with - in subdomain.

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i

For example:

> '[email protected]' =~ VALID_EMAIL_REGEX
=> 0

Solution 7 - Ruby

Yours is complicated indeed.

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

The above code should suffice.

Explanation of each piece of the expression above for clarification:

Start of regex:

/

Match the start of a string:

\A

At least one word character, plus, hyphen, or dot:

[\w+\-.]+

A literal "at sign":

@

A literal dot:

\.

At least one letter:

[a-z]+

Match the end of a string:

\z

End of regex:

/

Case insensitive:

i

Putting it back together again:

/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

Check out Rubular to conveniently test your expressions as you write them.

Solution 8 - Ruby

Use

/\A[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])?)+\z/

Explanation below.

Whilst Joshua Hunter's answer is great URI::MailTo::EMAIL_REGEXP has a significant flaw in my opinion.

It matches fred@example which cause Net::SMTPSyntaxError: 501 5.1.3 Bad recipient address syntax errors.

URI::MailTo::EMAIL_REGEXP evaluates to

/\A[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])?)*\z/

Changing the last star to a plus makes it better.

Note: this is pointed out in Darpan's comment to Joshua Hunter's answer, but I think it deserves its own answer to make it more visible.

Solution 9 - Ruby

If you're using Devise, you can also use their included regex via:

Devise.email_regexp

which returns:

/\A[^@\s]+@[^@\s]+\z/

Solution 10 - Ruby

The accepted answer suggest using URI::MailTo::EMAIL_REGEXP.

However, this regexp considers 1234@1234 as a valid e-mail address, which is something you probably don't want in a real life app (for instance, AWS SES will throw an exception if you try to send an e-mail to an address like this).

As Darpan points out in the comments, you can simply change the trailing ? in that regexp with +, and it will work as expected. The resulting regex is:

/\A[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])?)+\z/

Since the original URI::MailTo regexp, whilst technically valid according to the spec, is imho useless for our needs, we "fix" it in the Devise initializer.

# in config/initializers/devise.rb, put this at the beginning of the file
URI::MailTo.send(:remove_const, :EMAIL_REGEXP)
URI::MailTo.const_set(:EMAIL_REGEXP, /\A[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])?)+\z/)

# And then find `config.email_regexp` (it will already be there in the file) and change it to:
config.email_regexp = URI::MailTo::EMAIL_REGEXP

If you're wondering why this monkeypatch isn't put in a separate initializer file, you'd have to name the initializer file as 00_xxx.rb to make it load before the devise initializer. This is against Rails docs recommendations, which actually suggests you use a single initializer for cases like this:

> If an initializer has code that relies on code in another initializer, you can combine them into a single initializer instead. This makes the dependencies more explicit, and can help surface new concepts within your application. Rails also supports numbering of initializer file names, but this can lead to file name churn.

Solution 11 - Ruby

Ruby Multiple Emails validation with regex in the controller

emails = testcontroller@gmail.com,testregex@gmail.com,etc...
unless emails =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
   flash[:error] = "Invalid emails"
else
   Here send invitation and create users
end

Solution 12 - Ruby

This works good for me:

if email.match?('[a-z0-9]+[_a-z0-9\.-]*[a-z0-9]+@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})')
      puts 'matches!'
else
      puts 'it doesn\'t match!'
end

Solution 13 - Ruby

try this!!!

/\[A-Z0-9._%+-\]+@\[A-Z0-9.-\]+\.\[AZ\]{2,4}/i

only email string selected

"Robert Donhan" <bob@email.com>sadfadf
Robert Donhan <bob@email.com>
"Robert Donhan" abc.bob@email.comasdfadf
Robert Donhan bob@email.comadfd

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionT0ny lombardiView Question on Stackoverflow
Solution 1 - RubyJoshua HunterView Answer on Stackoverflow
Solution 2 - RubyMike H-RView Answer on Stackoverflow
Solution 3 - RubyJohn CarneyView Answer on Stackoverflow
Solution 4 - RubyilgamView Answer on Stackoverflow
Solution 5 - RubykaikuchnView Answer on Stackoverflow
Solution 6 - RubyinstalleroView Answer on Stackoverflow
Solution 7 - RubybdbasingerView Answer on Stackoverflow
Solution 8 - RubydiabolistView Answer on Stackoverflow
Solution 9 - Rubyjeffdill2View Answer on Stackoverflow
Solution 10 - Rubysandre89View Answer on Stackoverflow
Solution 11 - RubyVENKATESH KARNIView Answer on Stackoverflow
Solution 12 - RubyMichele RivaView Answer on Stackoverflow
Solution 13 - RubyKiry MeasView Answer on Stackoverflow