2 Commits

Author SHA1 Message Date
Jonas Linter
669cf00bbc Fixed testcase due to email validation 2025-10-14 09:27:39 +02:00
Jonas Linter
99d1ed1732 Email validation no longer breaks customer retrieval 2025-10-14 08:46:16 +02:00
3 changed files with 27 additions and 7 deletions

View File

@@ -1,9 +1,12 @@
import re
import traceback
from dataclasses import dataclass
from datetime import UTC
from enum import Enum
from typing import Any
from email_validator import EmailNotValidError, validate_email
from alpine_bits_python.db import Customer, Reservation
from alpine_bits_python.logging_config import get_logger
from alpine_bits_python.schemas import (
@@ -618,6 +621,20 @@ def create_res_notif_push_message(
return _create_xml_from_db(list, OtaMessageType.NOTIF, config)
def _validate_and_repair_email(email: str | None) -> str | None:
if email is None:
return None
try:
# remove numbers from top-level domain (TLD) if any
email = re.sub(r"\.\d+", ".", email)
email_info = validate_email(email)
except EmailNotValidError as e:
_LOGGER.warning("invalid email address: %s", e)
return None
return email_info.normalized
def _process_single_reservation(
reservation: Reservation,
customer: Customer,
@@ -628,13 +645,16 @@ def _process_single_reservation(
[(customer.phone, PhoneTechType.MOBILE)] if customer.phone is not None else []
)
# Validate and repair email address
email = _validate_and_repair_email(customer.email_address)
customer_data = CustomerData(
given_name=customer.given_name,
surname=customer.surname,
name_prefix=customer.name_prefix,
name_title=customer.name_title,
phone_numbers=phone_numbers,
email_address=customer.email_address,
email_address=email,
email_newsletter=customer.email_newsletter,
address_line=customer.address_line,
city_name=customer.city_name,

View File

@@ -13,7 +13,6 @@ from dataclasses import dataclass
from datetime import datetime
from enum import Enum, IntEnum
from typing import Any, Optional, override
from zoneinfo import ZoneInfo
from xsdata.formats.dataclass.serializers.config import SerializerConfig
from xsdata_pydantic.bindings import XmlParser, XmlSerializer
@@ -24,8 +23,7 @@ from alpine_bits_python.alpine_bits_helpers import (
)
from alpine_bits_python.logging_config import get_logger
from .db import AckedRequest, Customer, Reservation
from .reservation_service import ReservationService
from .db import Customer, Reservation
from .generated.alpinebits import (
OtaNotifReportRq,
OtaNotifReportRs,
@@ -34,6 +32,7 @@ from .generated.alpinebits import (
OtaReadRq,
WarningStatus,
)
from .reservation_service import ReservationService
# Configure logging
_LOGGER = get_logger(__name__)
@@ -147,7 +146,8 @@ class AlpineBitsResponse:
"""Validate that status code is one of the allowed values."""
if self.status_code not in [200, 400, 401, 500]:
raise ValueError(
f"Invalid status code {self.status_code}. Must be 200, 400, 401, or 500"
"Invalid status code %s. Must be 200, 400, 401, or 500",
self.status_code,
)

View File

@@ -66,7 +66,7 @@ def sample_customer():
contact_id="CONTACT-12345",
name_prefix="Mr.",
name_title="Jr.",
email_address="john.doe@example.com",
email_address="john.doe@gmail.com",
phone="+1234567890",
email_newsletter=True,
address_line="123 Main Street",
@@ -378,7 +378,7 @@ class TestXMLParsing:
# Verify customer data is present
assert "John" in xml_output
assert "Doe" in xml_output
assert "john.doe@example.com" in xml_output
assert "john.doe@gmail.com" in xml_output
# Verify reservation data is present
# assert "RES-2024-001" in xml_output