|
|
|
|
|
from pathlib import Path |
|
|
from app.schema import Prospect |
|
|
from app.config import ( |
|
|
COMPANY_FOOTER_PATH, ENABLE_CAN_SPAM, |
|
|
ENABLE_PECR, ENABLE_CASL |
|
|
) |
|
|
|
|
|
class Compliance: |
|
|
"""Enforces email compliance and policies""" |
|
|
|
|
|
def __init__(self, mcp_registry): |
|
|
self.mcp = mcp_registry |
|
|
self.store = mcp_registry.get_store_client() |
|
|
|
|
|
|
|
|
footer_path = Path(COMPANY_FOOTER_PATH) |
|
|
if footer_path.exists(): |
|
|
self.footer = footer_path.read_text() |
|
|
else: |
|
|
self.footer = "\n\n---\nLucidya Inc.\n123 Market St, San Francisco, CA 94105\nUnsubscribe: https://lucidya.example.com/unsubscribe" |
|
|
|
|
|
async def run(self, prospect: Prospect) -> Prospect: |
|
|
"""Check compliance and enforce policies""" |
|
|
|
|
|
if not prospect.email_draft: |
|
|
prospect.status = "blocked" |
|
|
prospect.dropped_reason = "No email draft to check" |
|
|
await self.store.save_prospect(prospect) |
|
|
return prospect |
|
|
|
|
|
policy_failures = [] |
|
|
|
|
|
|
|
|
for contact in prospect.contacts: |
|
|
if await self.store.check_suppression("email", contact.email): |
|
|
policy_failures.append(f"Email suppressed: {contact.email}") |
|
|
|
|
|
domain = contact.email.split("@")[1] |
|
|
if await self.store.check_suppression("domain", domain): |
|
|
policy_failures.append(f"Domain suppressed: {domain}") |
|
|
|
|
|
if await self.store.check_suppression("company", prospect.company.id): |
|
|
policy_failures.append(f"Company suppressed: {prospect.company.name}") |
|
|
|
|
|
|
|
|
body = prospect.email_draft.get("body", "") |
|
|
|
|
|
|
|
|
if ENABLE_CAN_SPAM: |
|
|
if "unsubscribe" not in body.lower() and "unsubscribe" not in self.footer.lower(): |
|
|
policy_failures.append("CAN-SPAM: Missing unsubscribe mechanism") |
|
|
|
|
|
if not any(addr in self.footer for addr in ["St", "Ave", "Rd", "Blvd"]): |
|
|
policy_failures.append("CAN-SPAM: Missing physical postal address") |
|
|
|
|
|
|
|
|
if ENABLE_PECR: |
|
|
|
|
|
|
|
|
if "existing customer" not in body.lower(): |
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
if ENABLE_CASL: |
|
|
if "consent" not in body.lower() and prospect.company.domain.endswith(".ca"): |
|
|
policy_failures.append("CASL: May need express consent for Canadian recipients") |
|
|
|
|
|
|
|
|
forbidden_phrases = [ |
|
|
"guaranteed", "100%", "no risk", "best in the world", |
|
|
"revolutionary", "breakthrough" |
|
|
] |
|
|
|
|
|
for phrase in forbidden_phrases: |
|
|
if phrase in body.lower(): |
|
|
policy_failures.append(f"Unverifiable claim: '{phrase}'") |
|
|
|
|
|
|
|
|
if not policy_failures: |
|
|
prospect.email_draft["body"] = body + "\n" + self.footer |
|
|
|
|
|
|
|
|
if policy_failures: |
|
|
prospect.status = "blocked" |
|
|
prospect.dropped_reason = "; ".join(policy_failures) |
|
|
else: |
|
|
prospect.status = "compliant" |
|
|
|
|
|
await self.store.save_prospect(prospect) |
|
|
return prospect |