data = attachments_service.read_attachment_bytes(att) if data is not None: attachments.append({"filename": att.filename, "content": data, "mime_type": att.mime_type}) att_names.append(att.filename) html_problems = message_builder.validate_html(result_html) if html_problems: log.warning("HTML validation warnings for %s: %s", cr.email, html_problems) mime = message_builder.build_mime_message( from_email=account.email, # real authenticated account; never spoofed to_email=cr.email, subject=subject, html_body=result_html if campaign.message_type != "plain" else "", text_body=result_text, ===TEMPLATES=== res = engine.substitute(t.body_html, sample.get("recipient", { "FirstName": "John", "LastName": "Smith", "CompanyName": "Example Corp", "CustomerEmail": "customer@example.com", "Email": "john@example.com"}), g, custom_fields=sample.get("custom_fields", {}), extra={"unsubscribe_link": "https://example.com/unsubscribe?token=sample"}) problems = message_builder.validate_html(res.text) return {"rendered_html": message_builder.sanitize_preview(res.text), "unknown_variables": res.unknown, "missing_variables": res.missing, "warnings": problems, "generated": {"invoice_number": g.invoice_number, "amount": g.amount, "shipping": g.shipping}} @router.post("/{template_id}/test-pdf") async def test_pdf(template_id: int, sample: dict = {}, ===TESTSEND=== if not template or template.user_id != user.id: raise HTTPException(status_code=404, detail="Template not found") body_html = template.body_html if template else payload.body_html body_text = template.body_text if template else payload.body_text if not body_html and not body_text: raise HTTPException(status_code=400, detail="Provide a template or message body") problems = message_builder.validate_html(body_html) if body_html else {} if problems.get("errors"): raise HTTPException(status_code=400, detail=f"HTML rejected: {'; '.join(problems['errors'])}") # fake recipient record for variable substitution (test only) class _FakeRecipient: pass fr = _FakeRecipient() fr.email = str(payload.to_email) fr.first_name = "Test" fr.last_name = "Recipient" fr.company_name = await get_setting(db, "company_name", "Acme Corp") or "Acme Corp" fr.company_phone = "555-0100"