88:def validate_html(html: str) -> List[str]:
89- """Basic structural validation of rendered HTML. Returns list of problems."""
90- problems = []
91- if not html or not html.strip():
92- problems.append("Empty HTML body")
93- return problems
94- from bs4 import BeautifulSoup
95- soup = BeautifulSoup(html, "lxml")
96- if soup.find(True) is None:
97- problems.append("No HTML elements found")
98- for tag in soup.find_all(["script", "iframe", "object", "embed", "form"]):
99- problems.append(f"Disallowed tag <{tag.name}> present")
100- for img in soup.find_all("img"):
101- if not (img.get("src") or "").strip():
102- problems.append("img without src")
103- leftovers = re.findall(r"%([A-Za-z0-9_]+)%", html)
104- if leftovers:
105- problems.append(f"Unsubstituted variables remain: {sorted(set(leftovers))[:10]}")
106- return problems
107-
108-
109-def html_to_pdf(html: str) -> bytes:
110- """Real HTML → PDF conversion via WeasyPrint."""
111- try:
112- return WeasyHTML(string=html).write_pdf()
113- except Exception as e:
===
{"accounts":[{"id":5,"email":"qa.bot.sender@gmail.com","sending_method":"api"}]}
{"templates":[{"id":13,"name":"QA Invoice — blue"}]}