19

I'm looking for a regex to validate an email to learn if it's valid or not.. I have the following:

def is_a_valid_email?(email)
    email_regex = %r{
      ^ # Start of string
      [0-9a-z] # First character
      [0-9a-z.+]+ # Middle characters
      [0-9a-z] # Last character
      @ # Separating @ character
      [0-9a-z] # Domain name begin
      [0-9a-z.-]+ # Domain name middle
      [0-9a-z] # Domain name end
      $ # End of string
    }xi # Case insensitive

    (email =~ email_regex)
end

Problem with the above is XXX_XXX@Xxx.com does not return as valid when it should be. Any thoughts or suggestions for a better regex?

Thanks

jensgram
  • 31,109
  • 6
  • 81
  • 98
AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012
  • 2
    I think the underscore issues is just one of many where the above would fail (yield false positives or negatives). Do you really *need* to validate beyond "contains a `@` character"? The thread ["What is the best regular expression for validating email addresses?"](http://stackoverflow.com/questions/201323/what-is-the-best-regular-expression-for-validating-email-addresses) contains more details. – jensgram Jan 22 '11 at 19:48
  • possible duplicate of [Ruby email check (RFC 2822)](http://stackoverflow.com/questions/535600/ruby-email-check-rfc-2822) – apaderno Jun 05 '13 at 02:33

15 Answers15

25
validates_format_of :email, 
  :with => /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$/i

Don't ask me to explain it! That was from a validation plugin that I've since lost track of as all I needed was the email regex.

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
scragz
  • 6,670
  • 2
  • 23
  • 23
  • This regex identifies empty strings as valid emails. You should omit the outer parentheses and the pipe in the second character, which is the one accepting empty strings `/^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$/i` – Pablo Marambio Jun 26 '13 at 21:24
  • 4
    This should be used with `validates_presence_of :email`, that way they get the proper error message when it is empty. – scragz Jun 27 '13 at 03:09
  • This will fail against new TLDs like `.international`. – Ain Tohvri Jan 24 '17 at 10:23
  • or the crazier, but valid .XN--CLCHC0EA0B2G2A9GCD – Josh Vickery Feb 14 '17 at 23:25
  • 1
    If you want to allow Gmail aliases using `+`, add `(\+)` in the valid values. The regex becomes: `^(|(([A-Za-z0-9]+_+)|(\+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6})$` – Pierre-Yves O. Dec 12 '18 at 16:49
19

Not enough reputation to add a comment but if you are going to use the Devise regexp, and you are already using Devise itself, then you can simply use:

validates :email, presence: true, format: Devise.email_regexp

apanzerj
  • 467
  • 3
  • 9
14

@jensgram's answer is really good, but it actually still allows for an email without a domain, e.g. foo@bar is as valid as foo@bar.com.

Here's a slight variation on it that requires string@string.string:

/\A\S+@.+\.\S+\z/

or, more readable (though the parentheses aren't needed):

/\A(\S+)@(.+)\.(\S+)\z/

Play around with this

*Note: this regex is better than many, more complex ones, because of how incredibly diverse an email is allowed to be. Technically, an email can even use spaces if wrapped in quotes, e.g. "This is a valid email"@email.com

*Edit: I've replaced the ^ and $ with \A and \z to prevent a multiline anchor error in rails testing.

*Edit: Thanks to @Barry for noticing that the regex allowed white spaces. Updated the regex with \S to prevent emails with improper whitespaces. Multiple dots are still allowed as email@foo.bar.com is an acceptable address.

Sam Thornton
  • 953
  • 7
  • 18
  • @Barry, emails actually can be email@foo.bar.com (having two dots)--Chrome takes that as an acceptable email. Good catch though on the whitespace. I've updated the regex appropriately. – Sam Thornton Mar 03 '14 at 00:56
  • Pretty good this one! Except as noted in previous, the TLD changes now make: {code}.XN--CLCHC0EA0B2G2A9GCD{code} valid – jufemaiz Jun 21 '17 at 01:13
12

My shot at this (see comment and link above):

^.+@.+$
Timothy Alexis Vass
  • 2,526
  • 2
  • 11
  • 30
jensgram
  • 31,109
  • 6
  • 81
  • 98
  • @noodl Is that Ruby specific? I've never seen the `/` characters carry any signaficance in regex. – jensgram Jan 22 '11 at 20:00
  • 1
    Yes, in Ruby and Perl regex literals use `/` by default. The equivalent "bare" regex would be just `@` – noodl Jan 22 '11 at 20:02
  • Thansk jens, so simple. How do I assign that? email_regex = ^.+@.+$ errors – AnApprentice Jan 22 '11 at 20:18
  • Is this fine? email_regex = /^.+@.+$/ – AnApprentice Jan 22 '11 at 20:19
  • @AnApprentice I don't know much about Ruby, but I'd do `email_regex = %r{^.+@.+$}` if I were to hack something together :) – jensgram Jan 22 '11 at 20:29
  • but with that RE this strings are valid, too: @a@a.com a@a – MegaTux Sep 04 '12 at 20:35
  • 2
    @MegaTux Strictly speaking, `a@a` is valid with `a` serving as a TLD. You may be right, however, that using `@a` as the [`local-part`](http://tools.ietf.org/html/rfc5322#section-3.4.1) (in `@a@a`) is not invalid. – jensgram Sep 05 '12 at 05:57
  • 11
    `@@üüü@` will be validated correctly. I don't know, why this got upvoted at all. It's just wrong. – iblue Sep 12 '12 at 12:05
  • 2
    /^[^@]+@[^@]+\.[^@]+$/i. @noodl, /^.+@.+$/ is not at all equivalent to /@/ btw. – eagspoo Nov 16 '12 at 04:15
  • +1 @eagspoo is right that /^.+@.+$/ is not at all equivalent to /@/ I'm surprised that that completely wrong statement collected 5 (by the moment) upvotes. Guys go read books! p.s. sure that regex is very bad for validation. – trushkevich Jan 24 '13 at 23:00
  • Make sure you use \A and \z for checking beginning and end of the whole string not ^ and $ which check just the _line_. – maletor Mar 05 '13 at 01:55
  • But this gonna be start with any word like numerical,wild characters etc,try this \A[\w+.-]+\@[a-z]+.[a-z]{3}\z –  Jun 05 '13 at 01:50
  • the above regex would also let through t@t. But that is not a correct email address! – Robert Reiz Jun 18 '13 at 09:59
  • 1
    @RobertReiz `t@t` is a valid email address, sent to the dns host `t.`, just as `t@localhost` is perfectly fine. Practical is another matter. –  Feb 24 '14 at 23:33
  • Do not use regex to validate email addresses! (unless you're happy with false positives/negatives, I suppose). There are far too many cases to cover, and some -- such as nested comments -- cannot be properly covered via regex. tl;dr: regexes cannot properly validate email addresses. If you try, you will most assuredly fail. – Terra Ashley Jul 15 '17 at 04:29
  • 1
    @TerraAshley There is nothing wrong with using an extremely permissive regex to catch silly mistakes like entering a physical street address into an email address field – user229044 Sep 18 '18 at 13:45
  • 1
    @ilovebigmacs That's fine. Being overly permissive is preferable to rejecting valid emails because your regex is too specific. – user229044 Sep 18 '18 at 13:46
  • Hi this one allows space – Dr Linh Chi Nguyen Mar 03 '20 at 09:58
12

URI module has a build-in regexp

URI::MailTo::EMAIL_REGEXP
Stanislav Kr.
  • 504
  • 4
  • 12
9
/\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/

This is what I use to validate email.

Source: http://www.regular-expressions.info/email.html

eykanal
  • 26,437
  • 19
  • 82
  • 113
Mblake
  • 383
  • 2
  • 9
  • 10
    Don't do this. This regex will fail for email of the format, foo+bar@dingleberry.com. +stuff is valid for emails and is an important part of emails for many people and many apps. Also instead of repeating all the upper and lowercase matchers, just make the entire thing case insensitive. – eagspoo Nov 16 '12 at 04:06
  • 1
    chris+amazon@idontknow.com is a valid email. The +amazon is a tag for the address chris@idontknow.com. [More infos for emailaddress tagging](http://www.stevejenkins.com/blog/2011/03/how-to-use-address-tagging-usertagexample-com-with-postfix) – ali May 04 '15 at 15:14
5

Most of these other answers are too restrictive or allow addresses that are clearly wrong. So it's better to give up on being too strict, which will frustrate users and just get the main things right.

1. The most common use-case:

    validates :email, ..., format: { with: /\A[^@\s]+@([^@.\s]+\.)+[^@.\s]+\z/ }

2. To also allow root@localhost or homer@blinky, use this:

    validates :email, ..., format: { with: /\A[^@\s]+@([^@.\s]+\.)*[^@.\s]+\z/ }

None of the above replaces looking for CAPTCHAs, dns records, dns domain blacklists, IP blacklists and confirmation emails.

For real email domain validation, this can be used instead: https://gist.github.com/9200104

This horse is thoroughly beaten now, and being made into kibble.

4

correct format: email@domain.com

rules:

  • no whitespace
  • character prefix + @ + domain + . + character suffix

simple answer:

def validate_email(email)
  (email =~ %r{^\S+@\S+\.\S+$}xi).present?
end

examples:

'email' # false (no '@' and no domain)
'email@' # false (no domain)
'email@domain' # false (domain format without '.')
'em ail@d omain.com' # false (whitespace included)
'@domain.com' # false (no character prefix)
'email@domain.' # false (no character suffix)
'email@domain.com' # true
Taufan Arif
  • 410
  • 4
  • 8
1

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

It asserts that there are no @ symbols or whitespaces in either the localpart or the domain, and that there is a single @ symbol separating the localpart and the domain.

More importantly: require email verification

As more tlds are being created, this is forward thinking.

This is from Devise , an industry standard for authentication.

Blair Anderson
  • 19,463
  • 8
  • 77
  • 114
1

^.+@[\w]+\S[^\s]+$

A short improvement to first answer

Buniowy
  • 19
  • 1
1

Here's an email regex that I've been using for a while:

\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b

It's from here

ryanprayogo
  • 11,587
  • 11
  • 51
  • 66
  • 2
    I just put an edit in queue for Mblake's response showing the same source. For Ruby, to validate, though, you'll want: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i – A. Wilson Oct 27 '11 at 19:19
0

For email validation, I come up with this regular expression,

/^[\w\d]+@[\w\d]+(\.[\w\d]+)+$/

Don't know how much it will help you but working fine for me.

If anyone find it failing for any email address please reply me so I will be able to work more on this.

Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Swapnil Chincholkar
  • 2,869
  • 3
  • 22
  • 22
-1

In non-English locales you may need to verify emails with accented (unicode) characters such as čšēīū etc.

This method checks for a returned nil as a sign for a failed email validation in such locales:

def validate_unicode_email email
  /\A[\w\u00C0-\u017F\-]+(\.[\w\u00C0-\u017F\-]+)?@[\w\u00C0-\u017F\-]+\.[\w]{2,6}$/.match email
end

This will pass emails like name.surname@gmail.com, āpsis@mājās.lv, test_email@test_domain.org

Epigene
  • 3,634
  • 1
  • 26
  • 31
-2

Here's what we use.

We assume it's "something" @ "something" . "something" (2-4 characters). It should cover any "regular" email.

/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
Matt
  • 47
  • 5
  • do not use this. chris+amazon@idontknow.com is a valid emailaddress that won't match with this regex! – ali May 04 '15 at 15:18
-3
validates_format_of :email, :with => /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/i
Sebastián Palma
  • 32,692
  • 6
  • 40
  • 59
mindsupport
  • 490
  • 1
  • 6
  • 13