Introduce "EmailAddress" class #11
|
@ -2,6 +2,7 @@ from unittest.case import TestCase
|
|||
|
||||
from validate_email.domainlist_check import (
|
||||
domainlist_check, update_builtin_blacklist)
|
||||
from validate_email.email_address import EmailAddress
|
||||
from validate_email.exceptions import DomainBlacklistedError
|
||||
from validate_email.validate_email import (
|
||||
validate_email, validate_email_or_fail)
|
||||
|
@ -16,7 +17,7 @@ class BlacklistCheckTestCase(TestCase):
|
|||
def test_blacklist_positive(self):
|
||||
'Disallows blacklist item: mailinator.com.'
|
||||
with self.assertRaises(DomainBlacklistedError):
|
||||
domainlist_check(user_part='pa2', domain_part='mailinator.com')
|
||||
domainlist_check(EmailAddress('pa2@mailinator.com'))
|
||||
with self.assertRaises(DomainBlacklistedError):
|
||||
validate_email_or_fail(
|
||||
email_address='pa2@mailinator.com', check_regex=False,
|
||||
|
@ -37,5 +38,4 @@ class BlacklistCheckTestCase(TestCase):
|
|||
def test_blacklist_negative(self):
|
||||
'Allows a domain not in the blacklist.'
|
||||
self.assertTrue(expr=domainlist_check(
|
||||
user_part='pa2',
|
||||
domain_part='some-random-domain-thats-not-blacklisted.com'))
|
||||
EmailAddress('pa2@some-random-domain-thats-not-blacklisted.com')))
|
||||
|
|
68
tests/test_email_address.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
from unittest.case import TestCase
|
||||
|
||||
from validate_email import validate_email
|
||||
from validate_email.email_address import EmailAddress
|
||||
from validate_email.exceptions import AddressFormatError
|
||||
|
||||
|
||||
class UserDomainTestCase(TestCase):
|
||||
'Test the split of an email address into user and domain.'
|
||||
|
||||
valid_tests = {
|
||||
'email@domain.com': ('email', 'domain.com'),
|
||||
'email@subdomain.domain.com': ('email', 'subdomain.domain.com'),
|
||||
'email@123.123.123.123': ('email', '123.123.123.123'),
|
||||
'email@[123.123.123.123]': ('email', '[123.123.123.123]'),
|
||||
'email@domain-one.com': ('email', 'domain-one.com'),
|
||||
'email@domain.co.jp': ('email', 'domain.co.jp'),
|
||||
}
|
||||
|
||||
invalid_tests = [
|
||||
'plainaddress', # missing @ sign and domain
|
||||
'email.domain.com', # missing @
|
||||
]
|
||||
|
||||
def test_user_domain_valid(self):
|
||||
'Splits email address into user and domain parts.'
|
||||
for address, (user, domain) in self.valid_tests.items():
|
||||
self.assertEqual(EmailAddress(address).user, user)
|
||||
self.assertEqual(EmailAddress(address).domain, domain)
|
||||
|
||||
def test_user_domain_invalid(self):
|
||||
'Rejects unparseable email address.'
|
||||
for address in self.invalid_tests:
|
||||
# This must be rejected directly by the EmailAddress constructor...
|
||||
with self.assertRaises(AddressFormatError) as exc:
|
||||
EmailAddress(address)
|
||||
self.assertTupleEqual(exc.exception.args, ())
|
||||
# ...and indirectly by validate_email().
|
||||
self.assertFalse(validate_email(address))
|
||||
|
||||
|
||||
class IdnaTestCase(TestCase):
|
||||
'Testing IDNA conversion.'
|
||||
|
||||
valid_tests = {
|
||||
'email@address.com': 'email@address.com',
|
||||
'email@motörhéád.com': 'email@xn--motrhd-tta7d3f.com',
|
||||
'email@[123.123.123.123]': ('email@[123.123.123.123]'),
|
||||
}
|
||||
|
||||
invalid_tests = [
|
||||
'test@♥web.de',
|
||||
]
|
||||
|
||||
def test_idna_conversion_valid(self):
|
||||
'Converts email address into ASCII-compatible encoding.'
|
||||
for address, ace in self.valid_tests.items():
|
||||
self.assertEqual(EmailAddress(address).ace, ace)
|
||||
|
||||
def test_idna_conversion_invalid(self):
|
||||
'Rejects email address which is not IDNA-convertible.'
|
||||
for address in self.invalid_tests:
|
||||
# This must be rejected directly by the EmailAddress constructor...
|
||||
with self.assertRaises(AddressFormatError) as exc:
|
||||
EmailAddress(address)
|
||||
self.assertTupleEqual(exc.exception.args, ())
|
||||
# ...and indirectly by validate_email().
|
||||
self.assertFalse(validate_email(address))
|
|
@ -5,19 +5,8 @@ from unittest.mock import Mock, patch
|
|||
from dns.exception import Timeout
|
||||
|
||||
from validate_email import mx_check as mx_module
|
||||
from validate_email.exceptions import (
|
||||
AddressFormatError, DNSTimeoutError, NoValidMXError)
|
||||
from validate_email.mx_check import (
|
||||
_dissect_email, _get_idna_address, _get_mx_records)
|
||||
|
||||
DOMAINS = {
|
||||
'email@domain.com': 'domain.com',
|
||||
'email@subdomain.domain.com': 'subdomain.domain.com',
|
||||
'email@123.123.123.123': '123.123.123.123',
|
||||
'email@[123.123.123.123]': '123.123.123.123',
|
||||
'email@domain-one.com': 'domain-one.com',
|
||||
'email@domain.co.jp': 'domain.co.jp',
|
||||
}
|
||||
from validate_email.exceptions import DNSTimeoutError, NoValidMXError
|
||||
from validate_email.mx_check import _get_mx_records
|
||||
|
||||
|
||||
class DnsNameStub(object):
|
||||
|
@ -33,30 +22,6 @@ class DnsNameStub(object):
|
|||
TEST_QUERY = Mock()
|
||||
|
||||
|
||||
class DomainTestCase(TestCase):
|
||||
|
||||
def test_domain_from_email_address(self):
|
||||
for address, domain in DOMAINS.items():
|
||||
_user, domain_from_function = _dissect_email(email_address=address)
|
||||
self.assertEqual(domain_from_function, domain)
|
||||
|
||||
|
||||
class IdnaTestCase(TestCase):
|
||||
'Testing IDNA converting.'
|
||||
|
||||
def test_resolves_idna_domains(self):
|
||||
'Resolves email@motörhéád.com.'
|
||||
self.assertEqual(
|
||||
first=_get_idna_address(email_address='email@motörhéád.com'),
|
||||
second='email@xn--motrhd-tta7d3f.com')
|
||||
|
||||
def test_resolves_conventional_domains(self):
|
||||
'Resolves email@address.com.'
|
||||
self.assertEqual(
|
||||
first=_get_idna_address(email_address='email@address.com'),
|
||||
second='email@address.com')
|
||||
|
||||
|
||||
class GetMxRecordsTestCase(TestCase):
|
||||
'Testing `_get_mx_records`.'
|
||||
|
||||
|
@ -97,10 +62,3 @@ class GetMxRecordsTestCase(TestCase):
|
|||
with self.assertRaises(DNSTimeoutError) as exc:
|
||||
_get_mx_records(domain='testdomain3', timeout=10)
|
||||
self.assertTupleEqual(exc.exception.args, ())
|
||||
|
||||
def test_returns_false_on_idna_failure(self):
|
||||
'Returns `False` on IDNA failure.'
|
||||
with self.assertRaises(AddressFormatError) as exc:
|
||||
mx_module.mx_check(
|
||||
email_address='test@♥web.de', from_address='mail@example.com')
|
||||
self.assertTupleEqual(exc.exception.args, ())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from unittest.case import TestCase
|
||||
|
||||
from validate_email.email_address import EmailAddress
|
||||
from validate_email.exceptions import AddressFormatError
|
||||
from validate_email.regex_check import regex_check
|
||||
from validate_email.validate_email import validate_email
|
||||
|
||||
VALID_EXAMPLES = [
|
||||
'email@domain.com', # basic valid email
|
||||
|
@ -35,11 +35,6 @@ INVALID_EXAMPLES = [
|
|||
'email@domain..com', # multiple dot in the domain portion is invalid
|
||||
]
|
||||
|
||||
UNPARSEABLE_EXAMPLES = [
|
||||
'plainaddress', # missing @ sign and domain
|
||||
'email.domain.com', # missing @
|
||||
]
|
||||
|
||||
|
||||
class FormatValidity(TestCase):
|
||||
'Testing regex validation + format validity.'
|
||||
|
@ -47,21 +42,14 @@ class FormatValidity(TestCase):
|
|||
def test_valid_email_structure_regex(self):
|
||||
'Accepts an email with a valid structure.'
|
||||
for address in VALID_EXAMPLES:
|
||||
user_part, domain_part = address.rsplit('@', 1)
|
||||
self.assertTrue(
|
||||
expr=regex_check(user_part=user_part, domain_part=domain_part),
|
||||
expr=regex_check(EmailAddress(address)),
|
||||
msg=f'Check is not true with {address}')
|
||||
|
||||
def test_invalid_email_structure_regex(self):
|
||||
'Rejects an email with an invalid structure.'
|
||||
for address in INVALID_EXAMPLES:
|
||||
user_part, domain_part = address.rsplit('@', 1)
|
||||
with self.assertRaises(
|
||||
expected_exception=AddressFormatError,
|
||||
msg=f'Test failed for {address}'):
|
||||
regex_check(user_part=user_part, domain_part=domain_part),
|
||||
|
||||
def test_unparseable_email(self):
|
||||
'Rejects an unparseable email.'
|
||||
for address in UNPARSEABLE_EXAMPLES:
|
||||
self.assertFalse(expr=validate_email(email_address=address))
|
||||
regex_check(EmailAddress(address))
|
||||
|
|
|
@ -5,7 +5,6 @@ HOST_REGEX = re_compile(
|
|||
# max length for domain name labels is 63 characters per RFC 1034
|
||||
r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)'
|
||||
r'(?:[A-Z0-9-]{2,63}(?<!-))\Z', IGNORECASE)
|
||||
EMAIL_EXTRACT_HOST_REGEX = re_compile(r'(?<=@)\[?([^\[\]]+)')
|
||||
LITERAL_REGEX = re_compile(
|
||||
If I am not mistaken, if an IP address is used as the domain part of an email address, it must be enclosed in brackets. So syntactically, user@[123.123.123.123] is a valid email address, while user@123.123.123.123 isn't (unless 123.123.123.123 can be considered a domain name). This regex removes the brackets, so we will later not be able to distinguish between these cases. I think it's better to just use the rsplit and keep the brackets. If I am not mistaken, if an IP address is used as the domain part of an email address, it **must** be enclosed in brackets. So syntactically, user@[123.123.123.123] is a valid email address, while user@123.123.123.123 isn't (unless 123.123.123.123 can be considered a domain name). This regex *removes* the brackets, so we will later not be able to distinguish between these cases. I think it's better to just use the rsplit and keep the brackets.
|
||||
# literal form, ipv4 or ipv6 address (SMTP 4.1.3)
|
||||
r'\[([A-f0-9:\.]+)\]\Z', IGNORECASE)
|
||||
|
|
|
@ -3,6 +3,7 @@ from typing import Optional
|
|||
|
||||
from filelock import FileLock
|
||||
|
||||
from .email_address import EmailAddress
|
||||
from .exceptions import DomainBlacklistedError
|
||||
from .updater import (
|
||||
BLACKLIST_FILEPATH_INSTALLED, BLACKLIST_FILEPATH_TMP, LOCK_PATH,
|
||||
|
@ -55,11 +56,11 @@ class DomainListValidator(object):
|
|||
self.domain_blacklist = set(
|
||||
x.strip().lower() for x in lines if x.strip())
|
||||
|
||||
def __call__(self, user_part: str, domain_part: str) -> bool:
|
||||
def __call__(self, address: EmailAddress) -> bool:
|
||||
'Do the checking here.'
|
||||
if domain_part in self.domain_whitelist:
|
||||
if address.domain in self.domain_whitelist:
|
||||
return True
|
||||
if domain_part in self.domain_blacklist:
|
||||
if address.domain in self.domain_blacklist:
|
||||
raise DomainBlacklistedError
|
||||
return True
|
||||
|
||||
|
|
60
validate_email/email_address.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
from idna.core import IDNAError, encode
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
from .exceptions import AddressFormatError
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
class EmailAddress(object):
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
"""
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
Internally used class to hold an email address.
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
This class featuers splitting the email address into user and domain
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
part as well as converting internationalized domain name into the
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
ASCII-compatible encoding (ACE) according to the IDNA standard.
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
"""
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
def __init__(self, address: str):
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
self._address = address
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
As per PEP8, docstrings terminate at 72 columns. As per PEP8, docstrings terminate at 72 columns.
same here with the PEP8 stuff ```suggestion
"""
The username part of the email address, that is the part before
the "@" sign.
"""
```
same here with the PEP8 stuff
```suggestion
"""
The domain part of the email address, that is the part after the
"@" sign.
"""
```
```suggestion
"""
The ASCII-compatible encoding for the domain part of the email
address.
"""
```
python3 object ```suggestion
class EmailAddress(object):
```
python3 object
```suggestion
def user(self) -> str:
```
```suggestion
def domain(self) -> str:
```
```suggestion
def ace(self) -> str:
```
```suggestion
def ace_domain(self) -> str:
```
|
||||
# Split email address into user and domain part.
|
||||
```suggestion
"""
Internally used class to hold an email address.
This class featuers splitting the email address into user and domain
part as well as converting internationalized domain name into the
ASCII-compatible encoding (ACE) according to the IDNA standard.
"""
```
|
I would keep this constant and use for dissecting email address user and domain parts, so the problem you mentioned in the other issue will be easier to address.