from dataclasses import dataclass from typing import ClassVar from fansifter_common.adapters.stripo import StripoClient, StripoV2Client from fansifter_common.auth.requests import AuthRequest from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from email_campaigns.adapters.db import Repository from email_campaigns.adapters.features import ( AUDIENCE_ENABLE_STRIPO_PLUGIN_V2, Features, ) from email_campaigns.emails.exceptions import EmailNotFoundError from email_campaigns.emails.models import BaseEmail from email_campaigns.emails.services import EmailSendService from email_campaigns.emails.validators import EmailValidator @dataclass class SendTestEmailRequest(AuthRequest): email_id: str emails: set[str] content: str | None with_unapplied_changes: bool = False class SendTestEmailHandler[T: BaseEmail]: permission: ClassVar[Permission] def __init__( self, auth_service: AuthService, email_send_service: EmailSendService, email_validator: EmailValidator, email_repository: Repository[T], stripo_client: StripoClient, stripo_v2_client: StripoV2Client, features: Features, ) -> None: self.auth_service = auth_service self.email_validator = email_validator self.email_send_service = email_send_service self.email_repository = email_repository self.stripo_client = stripo_client self.stripo_v2_client = stripo_v2_client self.features = features def handle(self, request: SendTestEmailRequest) -> None: email = self.email_repository.get(request.email_id) if email is None: raise EmailNotFoundError self.auth_service.authorize_account( request.identity_id, account=email.account, permission=self.permission, ) # Validate email required content fields self.email_validator.validate_required_content( email, raise_on_error=True, data={"subject": "skip"} ) # Validate privacy footer presence before send self.email_validator.validate_privacy_footer_block_presence(email.html_content) # Ensure that sender email is valid self.email_validator.validate_sender_email(email.sender_email) content = request.content if ( request.with_unapplied_changes and content is None and self.features.is_on_for_identity( AUDIENCE_ENABLE_STRIPO_PLUGIN_V2, identity_id=request.identity_id, ) ): response = self.stripo_v2_client.get_html_css( email_id=email.id, user_id=request.identity_id, ) content = self.stripo_client.compress(response.html, response.css) self.email_send_service.send_test_email( email, content=content, emails=request.emails, identity_id=request.identity_id, with_unapplied_changes=request.with_unapplied_changes, )