Email validation no longer breaks customer retrieval
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import UTC
|
from datetime import UTC
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from email_validator import EmailNotValidError, validate_email
|
||||||
|
|
||||||
from alpine_bits_python.db import Customer, Reservation
|
from alpine_bits_python.db import Customer, Reservation
|
||||||
from alpine_bits_python.logging_config import get_logger
|
from alpine_bits_python.logging_config import get_logger
|
||||||
from alpine_bits_python.schemas import (
|
from alpine_bits_python.schemas import (
|
||||||
@@ -618,6 +621,34 @@ def create_res_notif_push_message(
|
|||||||
return _create_xml_from_db(list, OtaMessageType.NOTIF, config)
|
return _create_xml_from_db(list, OtaMessageType.NOTIF, config)
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_and_repair_email(email: str | None) -> str | None:
|
||||||
|
"""Validate and repair email addresses with common typos.
|
||||||
|
|
||||||
|
Attempts to fix trailing digits in TLDs (e.g., .de1 -> .de)
|
||||||
|
before validation. If the email is still invalid, returns None
|
||||||
|
instead of raising an exception.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email: Email address to validate and repair
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Normalized email address or None if invalid
|
||||||
|
"""
|
||||||
|
if email is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Remove trailing digits from TLD (e.g., .de1 -> .de, .com2 -> .com)
|
||||||
|
# This matches a dot followed by letters, then trailing digits at the end
|
||||||
|
email = re.sub(r'(\.[a-zA-Z]+)\d+$', r'\1', email)
|
||||||
|
|
||||||
|
try:
|
||||||
|
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(
|
def _process_single_reservation(
|
||||||
reservation: Reservation,
|
reservation: Reservation,
|
||||||
customer: Customer,
|
customer: Customer,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from dataclasses import dataclass
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from enum import Enum, IntEnum
|
from enum import Enum, IntEnum
|
||||||
from typing import Any, Optional, override
|
from typing import Any, Optional, override
|
||||||
from zoneinfo import ZoneInfo
|
|
||||||
|
|
||||||
from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
from xsdata.formats.dataclass.serializers.config import SerializerConfig
|
||||||
from xsdata_pydantic.bindings import XmlParser, XmlSerializer
|
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 alpine_bits_python.logging_config import get_logger
|
||||||
|
|
||||||
from .db import AckedRequest, Customer, Reservation
|
from .db import Customer, Reservation
|
||||||
from .reservation_service import ReservationService
|
|
||||||
from .generated.alpinebits import (
|
from .generated.alpinebits import (
|
||||||
OtaNotifReportRq,
|
OtaNotifReportRq,
|
||||||
OtaNotifReportRs,
|
OtaNotifReportRs,
|
||||||
@@ -34,6 +32,7 @@ from .generated.alpinebits import (
|
|||||||
OtaReadRq,
|
OtaReadRq,
|
||||||
WarningStatus,
|
WarningStatus,
|
||||||
)
|
)
|
||||||
|
from .reservation_service import ReservationService
|
||||||
|
|
||||||
# Configure logging
|
# Configure logging
|
||||||
_LOGGER = get_logger(__name__)
|
_LOGGER = get_logger(__name__)
|
||||||
@@ -147,7 +146,8 @@ class AlpineBitsResponse:
|
|||||||
"""Validate that status code is one of the allowed values."""
|
"""Validate that status code is one of the allowed values."""
|
||||||
if self.status_code not in [200, 400, 401, 500]:
|
if self.status_code not in [200, 400, 401, 500]:
|
||||||
raise ValueError(
|
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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user