import logging from dataclasses import dataclass from datetime import date from itertools import chain from urllib.parse import urlencode import jinja2 from cachelib import BaseCache from email_validator import EmailNotValidError, validate_email from fansifter_common.legal_info.services import LegalInfoService from fansifter_common.legal_info.types import PrivacyLink from jinja2 import Environment from app.connectors.aws.ses.email_client import EmailClient from app.connectors.ows_preference_center import ( OwsPreferenceCenterClient, ) from app.models import Event, Record logger = logging.getLogger(__name__) @dataclass(kw_only=True) class SongwhipFanConsentHandler: email_client: EmailClient jinja: Environment email_content_wording: dict[str, dict[str, str]] email_title_templates: dict[str, str] preference_center_url: str ows_preference_center_client: OwsPreferenceCenterClient legal_info_service: LegalInfoService cache: BaseCache def handle(self, event: Event) -> None: for record in chain(*event.records.values()): try: self.validate_record(record) self.process_record(record) except EmailNotValidError: logger.exception("Email validation fail") except Exception: logger.exception("Unhandled exception") def validate_record(self, record: Record) -> None: """Validates email from record using regexp and DNS resolver. In case of any problems raises an exception""" validate_email(record.message.email, check_deliverability=True) def process_record(self, record: Record) -> None: logger.info("Processing message %s", record.message_id) if self.cache.has(record.message.cache_id): logger.info( "Page path and email found in cache, skipping", extra={"message_id": record.message_id}, ) return privacy_links = self.prepare_privacy_links( self.legal_info_service.get_privacy_links(record.message.country) ) legal_entity = self.legal_info_service.get_legal_entity(record.message.country) subscribe_button_link = self.prepare_subscribe_button_link(record) email_template = self.jinja.get_template("email.html") try: email_content_wording = self.email_content_wording[ record.message.country.lower() ] except KeyError: email_content_wording = self.email_content_wording["en"] email_content = email_template.render( **email_content_wording, email=record.message.email, subscribe_button_link=subscribe_button_link, privacy_links=privacy_links, current_year=date.today().year, legal_name=legal_entity.name, legal_address=legal_entity.address, ) email_content = jinja2.Template(email_content).render( artist_name=record.message.artist_name ) try: email_title_template = self.email_title_templates[ record.message.country.lower() ] except KeyError: email_title_template = self.email_title_templates["en"] email_title = email_title_template.format( artist_name=record.message.artist_name ) self.email_client.send_email( email_address=record.message.email, email_title=email_title, email_content=email_content, message_id=record.message_id, ) self.cache.set(record.message.cache_id, None) def prepare_subscribe_button_link(self, record: Record) -> str: encrypted_fan_consent_id = ( self.ows_preference_center_client.encrypt_fan_consent_id(record.message_id) ) params = { "fanConsentId": encrypted_fan_consent_id, "redirectUrl": record.message.redirect_url, "country": record.message.country, } return f"{self.preference_center_url}?{urlencode(params)}" def prepare_privacy_links(self, privacy_links: dict[str, list[PrivacyLink]]) -> str: template = self.jinja.get_template("privacy_link.html") privacy_links_list: list[str] = [] for lang_privacy_links in privacy_links.values(): lang_privacy_links_list: list[str] = [] for privacy_link in lang_privacy_links: lang_privacy_links_list.append( template.render( privacy_link=privacy_link.url, privacy_title=privacy_link.name, ) ) privacy_links_list.append(" | ".join(lang_privacy_links_list)) return "
".join(privacy_links_list)