agentic.email/backend/app/services/handoff_email_templates.py
2026-10-06 02:44:54 +05:30

149 lines
4.6 KiB
Python

from html import escape
def _clean_external_subject(subject: str) -> str:
value = (subject or "(No subject)").strip()
for prefix in ("Re: ", "RE: ", "re: "):
if value.startswith(prefix):
value = value[len(prefix) :].strip()
for prefix in ("Human Handoff · ", "Human Handoff: "):
if value.lower().startswith(prefix.lower()):
value = value[len(prefix) :].strip()
return value or "(No subject)"
def handoff_email_subject(external_subject: str) -> str:
return f"Human Handoff · {_clean_external_subject(external_subject)}"
def external_reply_subject(external_subject: str) -> str:
cleaned = _clean_external_subject(external_subject)
return f"Re: {cleaned}"
def format_sender_line(sender: dict) -> str:
name = (sender.get("name") or "").strip()
address = (sender.get("address") or "").strip()
if not address:
return "unknown sender"
local = address.split("@", 1)[0].lower()
if name and name.lower() not in {local, address.lower()}:
return f"{name} <{address}>"
return address
def _footer_html(agent_email: str) -> str:
return f"""
<div class="gentic-handoff-footer" style="background:#F8F7FC;border-top:1px solid #E9E5F2;padding:12px 20px;">
<p style="margin:0 0 6px;font-size:12px;font-weight:650;color:#6750E8;">↩ Reply normally</p>
<p style="margin:0;font-size:11px;line-height:1.45;color:#77758A;">
Your reply will be sent to the original sender through
<span style="color:#292536;">{escape(agent_email)}</span>.
Only the new text you write will be sent.
</p>
</div>"""
def _footer_text(agent_email: str) -> str:
return (
"↩ Reply normally\n\n"
f"Your reply will be sent to the original sender through {agent_email}.\n"
"Only the new text you write will be sent."
)
def _header_html(sender_line: str, external_subject: str) -> str:
subject = escape(_clean_external_subject(external_subject))
return f"""
<div class="gentic-handoff-header" style="padding:16px 20px 12px;border-bottom:1px solid #ECE9EF;">
<div style="font-size:14px;font-weight:650;color:#6750E8;">✦ Human Handoff</div>
<div style="margin-top:5px;font-size:12px;color:#6F6B7C;">
<span>{escape(sender_line)}</span>
<span style="color:#292536;font-weight:550;"> | {subject}</span>
</div>
</div>"""
def _header_text(sender_line: str, external_subject: str) -> str:
return f"✦ Human Handoff\n{sender_line} | {_clean_external_subject(external_subject)}"
def build_mirror_handoff_html(
*,
sender_line: str,
external_subject: str,
original_html: str,
agent_email: str,
) -> str:
return f"""<!DOCTYPE html>
<html><body style="margin:0;padding:0;background:#FFFFFF;">
{_header_html(sender_line, external_subject)}
<div class="gentic-handoff-original" style="padding:20px 20px 24px;">
{original_html}
</div>
{_footer_html(agent_email)}
</body></html>"""
def build_mirror_handoff_text(
*,
sender_line: str,
external_subject: str,
original_body_text: str,
agent_email: str,
) -> str:
return "\n\n".join(
[
_header_text(sender_line, external_subject),
"─" * 56,
original_body_text.strip(),
"─" * 56,
_footer_text(agent_email),
]
)
def build_mirror_update_html(
*,
sender_line: str,
external_subject: str,
original_html: str,
agent_email: str,
) -> str:
subject = escape(_clean_external_subject(external_subject))
return f"""<!DOCTYPE html>
<html><body style="margin:0;padding:0;background:#FFFFFF;">
<div class="gentic-handoff-header" style="padding:16px 20px 12px;border-bottom:1px solid #ECE9EF;">
<div style="font-size:14px;font-weight:650;color:#6750E8;">✦ Customer replied</div>
<div style="margin-top:5px;font-size:12px;color:#6F6B7C;">
<span>{escape(sender_line)}</span>
<span style="color:#292536;font-weight:550;"> | {subject}</span>
</div>
</div>
<div class="gentic-handoff-original" style="padding:20px 20px 24px;">
{original_html}
</div>
{_footer_html(agent_email)}
</body></html>"""
def build_mirror_update_text(
*,
sender_line: str,
external_subject: str,
original_body_text: str,
agent_email: str,
) -> str:
return "\n\n".join(
[
f"✦ Customer replied\n{sender_line} | {_clean_external_subject(external_subject)}",
"─" * 56,
original_body_text.strip(),
"─" * 56,
_footer_text(agent_email),
]
)
def build_relay_confirmation_text(customer_body: str) -> str:
return f"Sent to customer:\n\n{customer_body.strip()}"