import httpx from anydi import singleton from email_validator import EmailNotValidError, validate_email from fansifter_common.adapters.ows_account import OwsAccountClient from fansifter_common.auth.account import Account from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from slugify import slugify from email_campaigns.emails.exceptions import InvalidEmailDomainIdError from email_campaigns.emails.models import EmailDomain from email_campaigns.emails.repositories import EmailDomainRepository @singleton class EmailDomainService: permission = Permission("email_domain", "view") def __init__( self, auth_service: AuthService, ows_account_client: OwsAccountClient, repository: EmailDomainRepository, ) -> None: self.auth_service = auth_service self.ows_account_client = ows_account_client self.repository = repository def get_allowed_domains( self, identity_id: str, account: Account ) -> list[EmailDomain]: account_access = self.auth_service.authorize_account( identity_id, permission=self.permission, account=account, ) # Get brand try: vendor = self.ows_account_client.get_vendor(account.vendor_id) except httpx.HTTPStatusError: return [] domains = self.repository.find_by_brand(vendor.brand) return [ domain for domain in domains if (domain.account and account_access.has_access(domain.account)) or domain.account is None ] def get_allowed_domain( self, identity_id: str, account: Account ) -> EmailDomain | None: domains = self.get_allowed_domains(identity_id=identity_id, account=account) if len(domains) == 1: return domains[0] return None def resolve_allowed_domain( self, email_domain_id: str | None, identity_id: str, account: Account ) -> EmailDomain | None: if email_domain_id is None: return self.get_allowed_domain(identity_id=identity_id, account=account) email_domain = self.repository.get(email_domain_id) if email_domain is None: raise InvalidEmailDomainIdError allowed_email_domains = self.get_allowed_domains( identity_id=identity_id, account=account ) for allowed_email_domain in allowed_email_domains: if allowed_email_domain.id == email_domain.id: return email_domain raise InvalidEmailDomainIdError("Email domain is not allowed.") @staticmethod def create_email_username(sender_name: str, domain_name: str) -> str | None: """Create valid email username from sender name, or None if invalid.""" email_username = slugify(sender_name, separator="") try: validate_email( f"{email_username}@{domain_name}", check_deliverability=False ) return email_username except EmailNotValidError: return None