(tools) extract domain from email address

This provides a standard way to extract the domain from an email
address. This is not used in the package but it could be used in several
projects.
This commit is contained in:
Quentin BEY
2025-04-02 11:33:53 +02:00
parent 137f923d17
commit c0d76bb20c
5 changed files with 80 additions and 0 deletions

View File

@@ -8,4 +8,8 @@ and this project adheres to
## [Unreleased]
### Added
- ✨(tools) extract domain from email address #2
[unreleased]: https://github.com/suitenumerique/django-lasuite/commits/main/

View File

@@ -0,0 +1 @@
"""Common tools for the LaSuite package or the projects."""

View File

@@ -0,0 +1,19 @@
"""Email related tools."""
from email.errors import HeaderParseError
from email.headerregistry import Address
def get_domain_from_email(email: str | None) -> str | None:
"""Extract domain from email."""
try:
address = Address(addr_spec=email)
if len(address.username) > 64 or len(address.domain) > 255: # noqa: PLR2004
# Simple length validation using the RFC 5321 limits
return None
if not address.domain:
# If the domain is empty, return None
return None
return address.domain
except (ValueError, AttributeError, IndexError, HeaderParseError):
return None

1
tests/tools/__init__.py Normal file
View File

@@ -0,0 +1 @@
"""Tools tests."""

55
tests/tools/test_email.py Normal file
View File

@@ -0,0 +1,55 @@
"""Tests for email tools."""
import pytest
from lasuite.tools.email import get_domain_from_email
@pytest.mark.parametrize(
("email", "expected"),
[
("user@example.com", "example.com"),
("test.user@sub.domain.co.uk", "sub.domain.co.uk"),
("name+tag@gmail.com", "gmail.com"),
("user@localhost", "localhost"),
("user@127.0.0.1", "127.0.0.1"),
],
)
def test_get_domain_from_email_valid(email, expected):
"""Test extracting domain from valid email addresses."""
assert get_domain_from_email(email) == expected
@pytest.mark.parametrize(
"invalid_email",
[
None,
"",
"invalid-email",
"user@",
"@domain.com",
"user@domain@com",
"user@@domain.com",
"user domain.com",
"<script>alert('XSS')</script>@example.com",
"user@example.com\n",
"user@example.com;drop table users",
],
)
def test_get_domain_from_email_invalid(invalid_email):
"""Test handling of invalid email addresses."""
assert get_domain_from_email(invalid_email) is None
def test_get_domain_from_email_length_limits():
"""Test handling of extremely long email addresses."""
# Very long local part (should fail)
long_local = "a" * 65 + "@example.com"
assert get_domain_from_email(long_local) is None
# Very long domain (valid according to standards)
domain_parts = ".".join(["a" * 64] * 4)
long_domain = f"user@{domain_parts}"
# This might fail depending on email validation implementation
# The test expects None since such domains aren't typically valid in practice
assert get_domain_from_email(long_domain) is None