Build a Email Validator in Python


Objective: Building a Email Validator in Python where script can processing a list of user inputs to generate a report of valid email addresses and their domains.
It demonstrates:
variables,
control structures (nested loops and conditionals),
functions,
exception handling,
functions (including
*args
and**kwargs
)basic string manipulation
pytest (for testing script)
What new Concept covered
*args
(Variable Positional Arguments):
What: Allows a function to accept any number of positional arguments (e.g.,
generate_report(emails, "personal", "work")
).Why: Flexible for functions that need varying inputs (e.g., categories).
Where: Used in scripts or APIs to handle dynamic inputs.
New:
*categories
collects extra arguments as a tuple.Exceptions: Misusing
*args
with incorrect types (handled by checkingcategory.lower()
).
**kwargs
(Variable Keyword Arguments):
What: Allows a function to accept any number of keyword arguments similar like key-value pair (e.g.,
show_invalid=True
).Why: Provides optional configuration without fixed parameters.
Where: Common in utilities or APIs for customizable behavior.
New:
**options
collects keyword arguments as a dictionary; accessed with.get()
.Exceptions: Missing keys (handled with
.get(default)
).
String Manipulation:
What: Uses
split('@')
,in
operator, andlower()
for email validation and domain extraction.Why: Processes text data efficiently.
Where: Parsing user inputs or logs.
New: Basic email validation checks for
@
and a domain.Exceptions: Invalid emails cause
IndexError
(handled inis_valid_email
).
Nested Loops and any()
:
What: Nested loop in list comprehension (
any(category.lower() in email.lower() ...)
).Why: Checks if any category matches an email, simplifying control flow.
Where: Filtering data based on multiple criteria.
New:
any()
is a Python built-in that returnsTrue
if any element in an iterable isTrue
.Exceptions: Empty iterables or case mismatches (handled with
lower()
).
Pytest:
What: A testing framework for Python to write and run tests.
Why: Automates verification of code functionality, ensuring reliability.
Where: Used in development to validate logic and in CI/CD pipelines for DevOps.
New: Tests are written as functions with
assert
statements;pytest
discovers and runs them.Exceptions: Test failures indicate bugs or incomplete test coverage.
Test Functions:
What: Functions like
test_is_valid_email()
that check specific behaviors.Why: Isolates functionality for targeted validation.
Where: Unit testing individual components (e.g., email validation).
New: Prefix with
test_
forpytest
to recognize; use descriptive assertions.Exceptions: Overly specific tests may break with minor code changes.
Importing Modules:
What: Importing functions from
email_validator
.py (e.g.,from basics.email_validator import ...
).Why: Tests need access to the code being tested.
Where: Common in modular projects with separate test files.
New: Path-based import requires correct directory structure.
Exceptions: Incorrect paths cause
ModuleNotFoundError
.
Project summary
Processing a list of user inputs to generate a report of valid email addresses and their domains.
Understand difference and use of
*args
and**kwargs
in functions.Why
pytest
needed - Automates verification of code functionality, ensuring reliability. .Importing Modules - Tests need access to the code being tested
Structure
core-python
βββ basics
β βββ email_validator
β βββ README.md
β βββ main.py
βββ tests
βββ test_email_validator.py
email_validator/main.py
email validator script.test_email_validator.py
test script for email validator.
How I Built it
Build a pseudo flow chart with pen and paper.
Start writing code:
Letβs start with
main()
:Execute each step with considering pseudo flow chart.
emails
assign to a list of emails.report1
assign togenerate_report(emails)
which return only valid emails.report2
assign togenerate_report(emails, "personal")
which return only emails which haspersonal
in it.report3
assign togenerate_report(emails, show_invalid=True)
which return all emails (including invalid).print_report()
do the printing work.
About
generate_report()
:Generate report depending on passed arguments.
Take three arguments:
emails
take all provided emails*categories
take all remaining argument after emails.**options
take only key-pair type argument. (e.g.show_invalid=True
)
Return:
β dict[str, list[str]]
means a dictionary which has domain name and itβs corresponding email in a list.
About
is_valid_email()
:Check weather email is valid or not.
Has
email
parameter which takes email.Return:
β bool
means return beTrue
orFalse
.
About
extract_domain()
:Extract the domain from a valid email.
Has
email
parameter which takes email.Return:
β str
means return beif email valid
domain.com
if email is invalid
β β
.
About
print_report()
:First check report empty or not then do the printing work on report.
Has
report
parameter which take a report.Return:
β None
means no return.
How to run
Change directoru to
core-python
, so that test can also be performed.# optional: in python-foundation dir # source venv/bin/activate # Windows: venv\Scripts\activate cd core-python
Run
main.py
.python3 basics/email_validator/main.py
Output:
Report 1: All valid emails Domain: gmail.com - alice@gmail.com Domain: work.com - bob@work.com Domain: yahoo.com - charlie.personal@yahoo.com Domain: outlook.com - dave@outlook.com Report 2: Personal emails only Domain: yahoo.com - charlie.personal@yahoo.com Report 3: All emails (including invalid) Domain: gmail.com - alice@gmail.com Domain: work.com - bob@work.com Domain: invalid - invalid.email Domain: yahoo.com - charlie.personal@yahoo.com Domain: outlook.com - dave@outlook.com
Run
test_email_validator.py
:PYTHONPATH=. pytest tests/test_email_validator.py -vv
Output:
PYTHONPATH=. pytest tests/test_email_validator.py -vv ============================= test session starts ============================== platform linux -- Python 3.12.8, pytest-8.4.0, pluggy-1.6.0 -- /usr/bin/python3.12 cachedir: .pytest_cache rootdir: /Path/to/repos/PYTHON-FOUNDATION/core-python plugins: anyio-4.9.0 collected 4 items tests/test_email_validator.py::test_is_valid_email PASSED [ 25%] tests/test_email_validator.py::test_extract_domain PASSED [ 50%] tests/test_email_validator.py::test_generate_report PASSED [ 75%] tests/test_email_validator.py::test_generate_report_edge_cases PASSED [100%] ============================== 4 passed in 0.08s ===============================
Possible Issues
Of email_validator
Invalid Emails: Handled by
is_valid_email()
with IndexError` protection.Empty Inputs: Empty email lists or categories (handled with checks).
Type Hints: Use
mypy
for static checking:
pip install mypy
mypy basics/email_validator/main.py
Of Test
Test Failures: Indicate bugs in
email_validator/main.py
(e.g., incorrect domain extraction).Module Import Errors: Ensure
basics/email_validator/main.py
exists; fix path ifModuleNotFoundError
occurs.Incomplete Coverage: Tests cover main cases but not every scenario (e.g., very long emails); add more as needed.
Pytest Setup: Ensure
pytest
is installed; updaterequirements.txt
if missed.
Next
Functions demonstrates decorators and lambda functions.
Links
Github: Repo - Python Foundation/email_validator
Click here for: Project list
π€ How to Contribute / Follow Along
Clone the repo or copy scripts to try on your own machine.
Share your output or improvements in the comments.
DM me on GitHub or Hashnode for feedback!
π’ Letβs Connect
Follow me on Hashnode to get notified when I publish new Python projects π
β‘οΈ Chetan Tekam
Subscribe to my newsletter
Read articles from Chetan Tekam directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
