I want to create a function that checks if an email has a username that is 5 to 20 characters long, starts with an alphabet letter and ends with one domain names of (.org, .net, .org). It also corrects, if the user enters a capital letter. I am fully aware of that the code does not make sense as employing regular expressions is the best way, but this is just an exercises for me to built better codes in python. So I was wondering, which would the best way if a code needs to check multiple things and eventually returns True/False (like in this example).
def is_valid_email(raw_email):
email = raw_email.lower()
try:
name, domain_name = email.split('@')
except ValueError:
return False
else:
name_check = all([len(name) < 20, len(name) > 5, name[0].isalpha()])
domains = (".com", ".net", ".org")
domain_check = any([domain_name.endswith(domain)
for domain in domains])
return name_check and domain_check
print(is_valid_email('[email protected]'))
2 Answers 2
You can make it easier to read by transforming the logic into a series of early returns:
TOP_LEVEL_DOMAINS = ("com", "net", "org")
def is_valid_email(email):
if '@' not in email:
return False
name, domain_name = email.split('@', 1)
if '.' not in domain_name:
return False
if domain_name.split('.')[-1] not in TOP_LEVEL_DOMAINS:
return False
if len(name) < 5 or len(name) > 20:
return False
if not name[0].isalpha():
return False
return True
There is another advantege: since we process each check separately, you can wrap the result into a Result
class and send the reason for why the email is invalid instead of plain False
.
Don't use all()
when you can just do ... and ... and ...
. To rephrase the same: don't create collections for no reason.
Don't use exceptions for handling normal flow, they are not designed for it. Also it's much slower (if you call this function very often).
Note that real email addresses can contain non-latin letters, be case-sensitive and up to 256 symbols long.
email = raw_email.lower()
This not only changes the domain part (which is valid as domains are DNS names, and therefore case-insensitive), but it also changes the local part.
That will cause [email protected]
to be silently converted to the different address [email protected]
. You cannot assume those two addresses reach the same mailbox; it's entirely up to the destination MTA.
The only local-part that you may assume matches irrespective of case is postmaster
.
You may need to carefully re-read the RFCs that define mail addresses.
-
\$\begingroup\$ I was thinking all email providers have incasesensitive mail addresses. \$\endgroup\$Taylan GÜNAY– Taylan GÜNAY2022年10月29日 10:23:10 +00:00Commented Oct 29, 2022 at 10:23
.co.uk
and the dozens of other TLDs? \$\endgroup\$