A regular expression (regex) describes a pattern of text. This program uses one to check that a string has the shape of an email address: a name, an @, a domain and an ending such as .com.
The program
import re EMAIL_PATTERN = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*\.[A-Za-z]{2,}") def is_valid_email(email): return EMAIL_PATTERN.fullmatch(email) is not None tests = [ "ada@example.com", "grace.hopper+navy@mail.example.org", "not-an-email", "user@.com", "linus@example", "alan@example.c", "hedy @example.com", ] for email in tests: print(f"{email:36} {is_valid_email(email)}")
ada@example.com True grace.hopper+navy@mail.example.org True not-an-email False user@.com False linus@example False alan@example.c False hedy @example.com False
How it works
The pattern has three parts:
[A-Za-z0-9._%+-]+is the part before the@: one or more letters, digits or the characters. _ % + -.@[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*is the domain: one or more labels such asmailandexample, separated by dots. Because the first label needs at least one character,user@.comfails.\.[A-Za-z]{2,}is the ending: a dot and at least two letters, soalan@example.cfails.
re.fullmatch() checks that the whole string matches. re.match() only checks the start, so with re.match() the string "ada@example.com and more" would pass. re.compile() builds the pattern once, so it is not rebuilt on every call.
What a regex cannot check
A regex only checks the shape. It cannot tell you whether the address exists or whether the person can read mail sent to it. It also lets through some unusual strings, such as ada..lovelace@example.com. The full rules for email addresses are long, and no short pattern follows all of them. For a sign-up form, a simple shape check like this one, followed by a confirmation email, is the usual approach.