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"}]}