mirror of
https://github.com/suitenumerique/django-lasuite
synced 2026-04-25 17:15:14 +02:00
✨(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:
@@ -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/
|
||||
|
||||
1
src/lasuite/tools/__init__.py
Normal file
1
src/lasuite/tools/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Common tools for the LaSuite package or the projects."""
|
||||
19
src/lasuite/tools/email.py
Normal file
19
src/lasuite/tools/email.py
Normal 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
1
tests/tools/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Tools tests."""
|
||||
55
tests/tools/test_email.py
Normal file
55
tests/tools/test_email.py
Normal 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
|
||||
Reference in New Issue
Block a user