2
\$\begingroup\$

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]'))
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Oct 27, 2022 at 19:49
\$\endgroup\$
6
  • \$\begingroup\$ "if a code needs to check multiple things" Like additional checks for the same purpose (valid email) or multiple purposes? \$\endgroup\$ Commented Oct 27, 2022 at 20:05
  • \$\begingroup\$ I mean the same purpose. \$\endgroup\$ Commented Oct 27, 2022 at 20:11
  • 1
    \$\begingroup\$ This doesn't seem like a very good address validator. What about .co.uk and the dozens of other TLDs? \$\endgroup\$ Commented Oct 27, 2022 at 21:47
  • \$\begingroup\$ regex101.com/r/fbvPXi/1 \$\endgroup\$ Commented Oct 28, 2022 at 8:56
  • \$\begingroup\$ You are aware that capital letters are allowed in email addresses (and that programs must not change the local part in any way)? \$\endgroup\$ Commented Oct 28, 2022 at 9:00

2 Answers 2

3
\$\begingroup\$

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.

answered Oct 27, 2022 at 20:46
\$\endgroup\$
0
1
\$\begingroup\$
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.

answered Oct 28, 2022 at 9:03
\$\endgroup\$
1
  • \$\begingroup\$ I was thinking all email providers have incasesensitive mail addresses. \$\endgroup\$ Commented Oct 29, 2022 at 10:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.