Compare commits

...

38 Commits

Author SHA1 Message Date
Andrew Shumway
6d671ef69d Add delete statement back in 2025-04-14 12:14:37 -06:00
Andrew Shumway
cc7714713f Check if delete sql statement is causing issues 2025-04-14 12:11:01 -06:00
Andrew Shumway
7596bcd982 Add migration for second e2e test user 2025-04-14 12:06:59 -06:00
Andrew Shumway
ba24485808 poetry 2025-04-14 12:02:34 -06:00
Kenneth Kehl
ffdc0edc4e Merge pull request #1629 from GSA/intl_nums
restore international numbers
2025-04-14 10:24:49 -07:00
Andrew Shumway
2f220a17a5 Merge pull request #1641 from GSA/dependabot/pip/charset-normalizer-3.4.1
Bump charset-normalizer from 3.4.0 to 3.4.1
2025-04-14 09:28:13 -06:00
dependabot[bot]
37691f504e Bump charset-normalizer from 3.4.0 to 3.4.1
Bumps [charset-normalizer](https://github.com/jawah/charset_normalizer) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/jawah/charset_normalizer/releases)
- [Changelog](https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jawah/charset_normalizer/compare/3.4.0...3.4.1)

---
updated-dependencies:
- dependency-name: charset-normalizer
  dependency-version: 3.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 15:20:35 +00:00
Andrew Shumway
a1273d7f01 Merge pull request #1640 from GSA/dependabot/pip/flake8-bugbear-24.12.12
Bump flake8-bugbear from 24.8.19 to 24.12.12
2025-04-14 09:18:21 -06:00
Kenneth Kehl
0c65b50043 update project 2025-04-14 07:53:35 -07:00
dependabot[bot]
9e7f747675 Bump flake8-bugbear from 24.8.19 to 24.12.12
Bumps [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) from 24.8.19 to 24.12.12.
- [Release notes](https://github.com/PyCQA/flake8-bugbear/releases)
- [Commits](https://github.com/PyCQA/flake8-bugbear/compare/24.8.19...24.12.12)

---
updated-dependencies:
- dependency-name: flake8-bugbear
  dependency-version: 24.12.12
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-10 15:55:56 +00:00
Andrew Shumway
0af9cac583 Merge pull request #1642 from GSA/dependabot/pip/flake8-7.2.0
Bump flake8 from 7.1.1 to 7.2.0
2025-04-10 09:53:41 -06:00
dependabot[bot]
7d54322846 Bump flake8 from 7.1.1 to 7.2.0
Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.1 to 7.2.0.
- [Commits](https://github.com/pycqa/flake8/compare/7.1.1...7.2.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-version: 7.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-09 14:55:34 +00:00
ccostino
0fceff42c4 Merge pull request #1638 from GSA/dependabot/pip/packaging-24.2
Bump packaging from 24.1 to 24.2
2025-04-09 10:53:21 -04:00
dependabot[bot]
51c0793ffe Bump packaging from 24.1 to 24.2
Bumps [packaging](https://github.com/pypa/packaging) from 24.1 to 24.2.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/24.1...24.2)

---
updated-dependencies:
- dependency-name: packaging
  dependency-version: '24.2'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 20:40:57 +00:00
ccostino
55bcf7f722 Merge pull request #1637 from GSA/dependabot/pip/pre-commit-4.2.0
Bump pre-commit from 3.8.0 to 4.2.0
2025-04-08 16:38:46 -04:00
Kenneth Kehl
7aaa36e630 merge from main 2025-04-08 10:05:30 -07:00
Kenneth Kehl
f87a54fffe fix test 2025-04-08 10:05:06 -07:00
ccostino
21330acf51 Merge pull request #1639 from GSA/dependabot/pip/newrelic-10.8.1
Bump newrelic from 10.7.0 to 10.8.1
2025-04-08 12:51:34 -04:00
dependabot[bot]
365d68183e Bump pre-commit from 3.8.0 to 4.2.0
Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.8.0 to 4.2.0.
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v3.8.0...v4.2.0)

---
updated-dependencies:
- dependency-name: pre-commit
  dependency-version: 4.2.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 15:16:07 +00:00
Andrew Shumway
f9995e24cb Merge pull request #1632 from GSA/dependabot/pip/black-25.1.0
Bump black from 24.10.0 to 25.1.0
2025-04-08 09:13:54 -06:00
dependabot[bot]
e9d2d03796 Bump newrelic from 10.7.0 to 10.8.1
Bumps [newrelic](https://github.com/newrelic/newrelic-python-agent) from 10.7.0 to 10.8.1.
- [Release notes](https://github.com/newrelic/newrelic-python-agent/releases)
- [Commits](https://github.com/newrelic/newrelic-python-agent/compare/v10.7.0...v10.8.1)

---
updated-dependencies:
- dependency-name: newrelic
  dependency-version: 10.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 22:47:27 +00:00
Andrew Shumway
51c1dcf159 Merge pull request #1636 from GSA/invites
fix invites again
2025-04-07 15:54:04 -06:00
Kenneth Kehl
91f269646f fix invites again 2025-04-07 14:36:21 -07:00
Kenneth Kehl
e4b7cf98a3 fix invites again 2025-04-07 14:31:33 -07:00
Beverly Nguyen
48e8ff755b Merge pull request #1635 from GSA/invites
fix invites
2025-04-07 13:24:46 -07:00
Kenneth Kehl
b605c74262 fix invites 2025-04-07 12:48:35 -07:00
Kenneth Kehl
df305a815a fix invites 2025-04-07 12:45:27 -07:00
Kenneth Kehl
d4a33549ca fix invites 2025-04-07 12:37:35 -07:00
Kenneth Kehl
14de65816f fix invites 2025-04-07 12:27:59 -07:00
dependabot[bot]
4d5ae7c9db Bump black from 24.10.0 to 25.1.0
Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-version: 25.1.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 17:21:40 +00:00
ccostino
ecb5747b7b Merge pull request #1628 from GSA/dependabot/pip/pytest-cov-6.1.0
Bump pytest-cov from 5.0.0 to 6.1.0
2025-04-07 13:19:34 -04:00
dependabot[bot]
f3966afe53 Bump pytest-cov from 5.0.0 to 6.1.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 5.0.0 to 6.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v5.0.0...v6.1.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 16:29:35 +00:00
ccostino
dce57ab964 Merge pull request #1597 from GSA/dependabot/pip/async-timeout-5.0.1
Bump async-timeout from 4.0.3 to 5.0.1
2025-04-07 11:40:15 -04:00
dependabot[bot]
bc85de75f1 Bump async-timeout from 4.0.3 to 5.0.1
Bumps [async-timeout](https://github.com/aio-libs/async-timeout) from 4.0.3 to 5.0.1.
- [Release notes](https://github.com/aio-libs/async-timeout/releases)
- [Changelog](https://github.com/aio-libs/async-timeout/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/async-timeout/compare/v4.0.3...v5.0.1)

---
updated-dependencies:
- dependency-name: async-timeout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 15:07:43 +00:00
ccostino
d06fd588ba Merge pull request #1631 from GSA/dependabot/pip/click-datetime-0.4.0
Bump click-datetime from 0.2 to 0.4.0
2025-04-07 11:05:30 -04:00
dependabot[bot]
30180574c9 Bump click-datetime from 0.2 to 0.4.0
Bumps click-datetime from 0.2 to 0.4.0.

---
updated-dependencies:
- dependency-name: click-datetime
  dependency-version: 0.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 21:17:32 +00:00
Kenneth Kehl
28444a460b fix test 2025-04-03 08:16:33 -07:00
Kenneth Kehl
e9ea22ad6d restore international numbers 2025-04-03 08:02:08 -07:00
9 changed files with 416 additions and 558 deletions

View File

@@ -48,7 +48,10 @@ class AwsSnsClient(SmsClient):
def send_sms(self, to, content, reference, sender=None, international=False):
matched = False
for match in phonenumbers.PhoneNumberMatcher(to, "US"):
if "+" not in to:
to = f"+{to}"
for match in phonenumbers.PhoneNumberMatcher(to, None):
matched = True
to = phonenumbers.format_number(
match.number, phonenumbers.PhoneNumberFormat.E164

View File

@@ -185,8 +185,10 @@ def send_email_to_provider(notification):
recipient = recipient.decode("utf-8")
personalisation = redis_store.get(f"email-personalisation-{notification.id}")
if personalisation:
personalisation = personalisation.decode("utf-8")
notification.personalisation = json.loads(personalisation)
p = personalisation.decode("utf-8")
p = json.loads(p)
notification.personalisation = p
service = SerialisedService.from_id(notification.service_id)
if not service.active:
@@ -210,6 +212,12 @@ def send_email_to_provider(notification):
template_dict, values=notification.personalisation
)
html_email = str(html_email)
html_email = html_email.replace("%5B", "")
html_email = html_email.replace("%5D", "")
html_email = html_email.replace("(", "")
html_email = html_email.replace(")", "")
if notification.key_type == KeyType.TEST:
notification.reference = str(create_uuid())
update_notification_to_sending(notification, provider)
@@ -225,7 +233,7 @@ def send_email_to_provider(notification):
recipient,
plain_text_email.subject,
body=str(plain_text_email),
html_body=str(html_email),
html_body=html_email,
reply_to_address=notification.reply_to_text,
)
notification.reference = reference

View File

@@ -0,0 +1,58 @@
import datetime
import os
import uuid
import sqlalchemy as sa
from alembic import op
from app import db
from app.dao.users_dao import get_user_by_email
from app.enums import AuthType
from app.models import User
from app.utils import utc_now
revision = "0417_add_second_e2e_test_user"
down_revision = "0416_readd_e2e_test_user"
def upgrade():
email_address = os.getenv("NOTIFY_E2E_TEST_EMAIL_TWO")
password = os.getenv("NOTIFY_E2E_TEST_PASSWORD_TWO")
name = f"e2e_test_user_{uuid.uuid4()}"
data = {
"id": uuid.uuid4(),
"name": name,
"email_address": email_address,
"password": password,
"mobile_number": "+12025555555",
"state": "active",
"created_at": utc_now(),
"password_changed_at": utc_now(),
"failed_login_count": 0,
"platform_admin": "f",
"email_access_validated_at": utc_now(),
"auth_type": AuthType.SMS,
}
conn = op.get_bind()
# delete the old user because
delete_sql = f"""
delete from users where email_address='{email_address}'
"""
insert_sql = """
insert into users (id, name, email_address, _password, mobile_number, state, created_at, password_changed_at, failed_login_count, platform_admin, email_access_validated_at, auth_type)
values (:id, :name, :email_address, :password, :mobile_number, :state, :created_at, :password_changed_at, :failed_login_count, :platform_admin, :email_access_validated_at, :auth_type)
"""
conn.execute(sa.text(delete_sql))
conn.execute(sa.text(insert_sql), data)
def downgrade():
email_address = os.getenv("NOTIFY_E2E_TEST_EMAIL_TWO")
user_to_delete = get_user_by_email(email_address)
if not user_to_delete:
return
db.session.remove(user_to_delete)
db.session.commit()

View File

@@ -628,8 +628,6 @@ def validate_phone_number(number, international=False):
try:
parsed = phonenumbers.parse(number, None)
if parsed.country_code != 1:
raise InvalidPhoneError("Invalid country code")
number = f"{parsed.country_code}{parsed.national_number}"
if len(number) < 8:
raise InvalidPhoneError("Not enough digits")

690
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,9 @@ cachetools = "==5.4.0"
celery = {version = "==5.4.0", extras = ["redis"]}
certifi = ">=2022.12.7"
cffi = "==1.17.1"
charset-normalizer = "^3.1.0"
charset-normalizer = "^3.4.1"
click = "==8.1.7"
click-datetime = "==0.2"
click-datetime = "==0.4.0"
click-didyoumean = "==0.3.1"
click-plugins = "==1.1.1"
click-repl = "==0.3.0"
@@ -41,7 +41,7 @@ marshmallow-sqlalchemy = "==1.0.0"
newrelic = "*"
notifications-python-client = "==10.0.0"
oscrypto = { git = "https://github.com/wbond/oscrypto.git", rev = "1547f53" }
packaging = "==24.1"
packaging = "==24.2"
poetry-dotenv-plugin = "==0.2.0"
psycopg2-binary = "==2.9.9"
pyjwt = "==2.10.1"
@@ -49,7 +49,7 @@ python-dotenv = "==1.0.1"
sqlalchemy = "==2.0.31"
werkzeug = "^3.0.6"
faker = "^26.0.0"
async-timeout = "^4.0.3"
async-timeout = "^5.0.1"
bleach = "^6.1.0"
geojson = "^3.2.0"
numpy = "^2.2.3"
@@ -81,22 +81,22 @@ requests = "^2.32.3"
[tool.poetry.group.dev.dependencies]
awscli = "^1.33.32"
bandit = "*"
black = "^24.8.0"
black = "^25.1.0"
cloudfoundry-client = "*"
exceptiongroup = "==1.2.2"
flake8 = "^7.1.1"
flake8-bugbear = "^24.1.17"
flake8 = "^7.2.0"
flake8-bugbear = "^24.12.12"
freezegun = "^1.5.1"
honcho = "*"
isort = "^5.13.2"
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
moto = "==5.1.0"
pip-audit = "*"
pre-commit = "^3.8.0"
pre-commit = "^4.2.0"
pytest = "^8.3.2"
pytest-env = "^1.1.3"
pytest-mock = "^3.14.0"
pytest-cov = "^5.0.0"
pytest-cov = "^6.1.1"
pytest-xdist = "^3.5.0"
radon = "^6.0.1"
requests-mock = "^1.11.0"

View File

@@ -5,7 +5,7 @@ from app import aws_sns_client
def test_send_sms_successful_returns_aws_sns_response(notify_api, mocker):
boto_mock = mocker.patch.object(aws_sns_client, "_client", create=True)
to = "6135555555"
to = "16135555555"
content = reference = "foo"
with notify_api.app_context():
aws_sns_client.send_sms(to, content, reference)

View File

@@ -628,6 +628,8 @@ def test_bad_or_missing_data(
assert recipients.has_errors is True
# TODO, original test for number one had {0, 1, 2}, but it has morphed to {0, 1}
# Is +447900123 legit or not? What changed?
@pytest.mark.parametrize(
("file_contents", "rows_with_bad_recipients"),
[
@@ -638,7 +640,7 @@ def test_bad_or_missing_data(
1234
+447900123
""",
{0, 1, 2},
{0, 1},
),
(
"""
@@ -647,7 +649,7 @@ def test_bad_or_missing_data(
+12022340104, USA
+23051234567, Mauritius
""",
{2},
set(),
),
],
)

View File

@@ -24,21 +24,16 @@ valid_us_phone_numbers = [
"(202) 555-0104",
]
# TODO
# International phone number tests are commented out as a result of issue #943 in notifications-admin. We are
# deliberately eliminating the ability to send to numbers outside of country code 1. These tests should
# be removed at some point when we are sure we are never going to support international numbers
valid_international_phone_numbers = [
# "+71234567890", # Russia
# "+447123456789", # UK
# "+4407123456789", # UK
# "+4407123 456789", # UK
# "+4407123-456-789", # UK
# "+23051234567", # Mauritius,
# "+682 12345", # Cook islands
# "+3312345678",
# "+9-2345-12345-12345", # 15 digits
"+71234567890", # Russia
"+447123456789", # UK
"+4407123456789", # UK
"+4407123 456789", # UK
"+4407123-456-789", # UK
"+23051234567", # Mauritius,
"+682 12345", # Cook islands
"+3312345678",
"+9-2345-12345-12345", # 15 digits
]
@@ -85,7 +80,7 @@ invalid_us_phone_numbers = sum(
invalid_phone_numbers = [
("+80233456789", "Not a valid country prefix"),
("1234567", "Not enough digits"),
("+682 1234", "Invalid country code"), # Cook Islands phone numbers can be 5 digits
("+682 1234", "Not enough digits"), # Cook Islands phone numbers are 5 digits
("+12345 12345 12345 6", "Too many digits"),
]
@@ -156,46 +151,46 @@ def test_detect_us_phone_numbers(phone_number):
@pytest.mark.parametrize(
("phone_number", "expected_info"),
[
# (
# "+4407900900123",
# international_phone_info(
# international=True,
# country_prefix="44", # UK
# billable_units=1,
# ),
# ),
# (
# "+4407700900123",
# international_phone_info(
# international=True,
# country_prefix="44", # Number in TV range
# billable_units=1,
# ),
# ),
# (
# "+4407700800123",
# international_phone_info(
# international=True,
# country_prefix="44", # UK Crown dependency, so prefix same as UK
# billable_units=1,
# ),
# ),
# ( #
# "+20-12-1234-1234",
# international_phone_info(
# international=True,
# country_prefix="20", # Egypt
# billable_units=1,
# ),
# ),
# (
# "+201212341234",
# international_phone_info(
# international=True,
# country_prefix="20", # Egypt
# billable_units=1,
# ),
# ),
(
"+4407900900123",
international_phone_info(
international=True,
country_prefix="44", # UK
billable_units=1,
),
),
(
"+4407700900123",
international_phone_info(
international=True,
country_prefix="44", # Number in TV range
billable_units=1,
),
),
(
"+4407700800123",
international_phone_info(
international=True,
country_prefix="44", # UK Crown dependency, so prefix same as UK
billable_units=1,
),
),
( #
"+20-12-1234-1234",
international_phone_info(
international=True,
country_prefix="20", # Egypt
billable_units=1,
),
),
(
"+201212341234",
international_phone_info(
international=True,
country_prefix="20", # Egypt
billable_units=1,
),
),
(
"+1 664-491-3434",
international_phone_info(
@@ -204,14 +199,14 @@ def test_detect_us_phone_numbers(phone_number):
billable_units=1,
),
),
# (
# "+71234567890",
# international_phone_info(
# international=True,
# country_prefix="7", # Russia
# billable_units=1,
# ),
# ),
(
"+71234567890",
international_phone_info(
international=True,
country_prefix="7", # Russia
billable_units=1,
),
),
(
"1-202-555-0104",
international_phone_info(
@@ -228,14 +223,14 @@ def test_detect_us_phone_numbers(phone_number):
billable_units=1,
),
),
# (
# "+23051234567",
# international_phone_info(
# international=True,
# country_prefix="230", # Mauritius
# billable_units=1,
# ),
# ),
(
"+23051234567",
international_phone_info(
international=True,
country_prefix="230", # Mauritius
billable_units=1,
),
),
],
)
def test_get_international_info(phone_number, expected_info):
@@ -288,11 +283,11 @@ def test_valid_us_phone_number_can_be_formatted_consistently(phone_number):
@pytest.mark.parametrize(
("phone_number", "expected_formatted"),
[
# ("+44071234567890", "+4471234567890"),
("+44071234567890", "+4471234567890"),
("1-202-555-0104", "+12025550104"),
("+12025550104", "+12025550104"),
("12025550104", "+12025550104"),
# ("+23051234567", "+23051234567"),
("+23051234567", "+23051234567"),
],
)
def test_valid_international_phone_number_can_be_formatted_consistently(
@@ -368,17 +363,17 @@ def test_validates_against_guestlist_of_phone_numbers(phone_number):
)
# @pytest.mark.parametrize(
# "recipient_number, allowlist_number",
# [
# ["+4407123-456-789", "+4407123456789"],
# ["+4407123456789", "+4407123-456-789"],
# ],
# )
# def test_validates_against_guestlist_of_international_phone_numbers(
# recipient_number, allowlist_number
# ):
# assert allowed_to_send_to(recipient_number, [allowlist_number])
@pytest.mark.parametrize(
"recipient_number, allowlist_number",
[
["+4407123-456-789", "+4407123456789"],
["+4407123456789", "+4407123-456-789"],
],
)
def test_validates_against_guestlist_of_international_phone_numbers(
recipient_number, allowlist_number
):
assert allowed_to_send_to(recipient_number, [allowlist_number])
@pytest.mark.parametrize("email_address", valid_email_addresses)
@@ -388,19 +383,21 @@ def test_validates_against_guestlist_of_email_addresses(email_address):
)
# TODO something wrong with formatting Egyptian numbers, doesn't seem
# like this would affect sendability need to confirm with AWS simulated numbers.
@pytest.mark.parametrize(
("phone_number", "expected_formatted"),
[
# ("+4407900900123", "+44 7900 900123"), # UK
# ("+44(0)7900900123", "+44 7900 900123"), # UK
# ("+447900900123", "+44 7900 900123"), # UK
("+4407900900123", "+44 7900 900123"), # UK
("+44(0)7900900123", "+44 7900 900123"), # UK
("+447900900123", "+44 7900 900123"), # UK
# ("+20-12-1234-1234", "+20 121 234 1234"), # Egypt
# ("+201212341234", "+20 121 234 1234"), # Egypt
("+1 664 491-3434", "+1 664-491-3434"), # Montserrat
# ("+7 499 1231212", "+7 499 123-12-12"), # Moscow (Russia)
("+7 499 1231212", "+7 499 123-12-12"), # Moscow (Russia)
("1-202-555-0104", "(202) 555-0104"), # Washington DC (USA)
# ("+23051234567", "+230 5123 4567"), # Mauritius
# ("+33(0)1 12345678", "+33 1 12 34 56 78"), # Paris (France)
("+23051234567", "+230 5123 4567"), # Mauritius
("+33(0)1 12345678", "+33 1 12 34 56 78"), # Paris (France)
],
)
def test_format_us_and_international_phone_numbers(phone_number, expected_formatted):
@@ -417,7 +414,7 @@ def test_format_us_and_international_phone_numbers(phone_number, expected_format
(None, ""),
("foo", "foo"),
("TeSt@ExAmPl3.com", "test@exampl3.com"),
# ("+4407900 900 123", "+447900900123"),
("+4407900 900 123", "+447900900123"),
("+1 800 555 5555", "+18005555555"),
],
)