Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / Platform

Reference

PDF and system mail

The Chromium PDF renderer in core/pdf_render.py, the system mailbox in core/system_mail.py, the /api/v1/email routes, and the record export formats.

The platform offers two output services to modules: HTML-to-PDF rendering and a system mailbox that sends transactional mail. This page lists core/pdf_render.py, core/system_mail.py, the routes in server/routes/email.py, and the export helper in server/services/record_formatter.py. Personal mail accounts belong to the mail module; see mail.

Scope and source

  • Defined in: src/cluster_erp/core/pdf_render.py (PdfRenderer, get_renderer, close_renderer, font_face_css), src/cluster_erp/core/system_mail.py, src/cluster_erp/server/routes/email.py, src/cluster_erp/server/services/record_formatter.py
  • Count: 3 email routes (counted from the @router. decorators); 5 export formats (text, pdf, xml, json, csv, from the request pattern in src/cluster_erp/server/routes/email.py:73)

PDF renderer

PdfRenderer renders HTML to PDF with Playwright's Chromium. One browser is started per process on first use, guarded by a lock; each render opens its own browser context and page (src/cluster_erp/core/pdf_render.py:58-120).

Member Behaviour Source
render(html, footer_html=None, page_format="A4") Sets the page content, waits for fonts, and returns PDF bytes with backgrounds, CSS page size, and an optional footer template src/cluster_erp/core/pdf_render.py:92-120
close() Closes the browser and Playwright src/cluster_erp/core/pdf_render.py:122-131
get_renderer() Returns the process-wide renderer src/cluster_erp/core/pdf_render.py:137-141
close_renderer() Closes it; called by the lifespan at shutdown src/cluster_erp/core/pdf_render.py:144-148, src/cluster_erp/server/app.py:198-204
font_face_css() The web app's manrope.css with every font file inlined as a data URI src/cluster_erp/core/pdf_render.py:32-51

RENDER_TIMEOUT_MS is 30,000 (src/cluster_erp/core/pdf_render.py:28). When Playwright or Chromium is missing, the renderer raises AppError with PDF_RENDERER_UNAVAILABLE and HTTP 503 (src/cluster_erp/core/pdf_render.py:70-89). The renderer is used by the trade documents of the sales_orders module (src/cluster_erp/modules/sales_orders/trade_documents/render.py, src/cluster_erp/modules/sales_orders/trade_documents/services.py). See trade documents.

System mailbox

core/system_mail.py is the one SMTP sender for mail that the application sends itself (src/cluster_erp/core/system_mail.py:1-12).

Member Behaviour Source
is_configured(settings) True when smtp_host is set src/cluster_erp/core/system_mail.py:41-42
from_header(settings) smtp_from_name <smtp_from_email>, or the address alone src/cluster_erp/core/system_mail.py:45-48
build_message(...) A multipart/mixed message with text, an optional HTML alternative, and attachments src/cluster_erp/core/system_mail.py:51-80
send_blocking(settings, msg, recipients) Connects with a 25-second timeout, uses STARTTLS when smtp_use_tls is on, logs in when smtp_user is set, and sends src/cluster_erp/core/system_mail.py:83-98
send_system_email(...) Builds the message and sends it in a worker thread src/cluster_erp/core/system_mail.py:101-123
SystemMailNotConfiguredError, SystemMailError Raised when no host is set, and when the SMTP conversation fails src/cluster_erp/core/system_mail.py:33-38

Modules send transactional mail by emitting SendTransactionalEmail. The mail module handles it and calls send_system_email; when the mailbox is not configured it returns {"sent": False, "reason": "not_configured"} (src/cluster_erp/modules/mail/module.py:53, src/cluster_erp/modules/mail/module.py:72-100).

Email routes

The router prefix is /api/v1/email, and every route requires the permission email.send (src/cluster_erp/server/routes/email.py:22, src/cluster_erp/server/routes/email.py:100, src/cluster_erp/server/routes/email.py:126, src/cluster_erp/server/routes/email.py:191).

Method and path Purpose Behaviour Source
POST /resolve Find e-mail addresses of records Emits ResolveEntityEmails and collects the recipient lists from all handlers src/cluster_erp/server/routes/email.py:95-119
POST /send-records Send records as an export Builds the export with generate_export, attaches it unless the format is text, and sends through the system mailbox src/cluster_erp/server/routes/email.py:122-184
POST /send Send a plain message Sends a text and HTML message through the system mailbox src/cluster_erp/server/routes/email.py:187-222

Both send routes answer HTTP 503 with SMTP_NOT_CONFIGURED when the server has no mail settings, and HTTP 502 with SMTP_ERROR when sending fails (src/cluster_erp/server/routes/email.py:131-136, src/cluster_erp/server/routes/email.py:184, src/cluster_erp/server/routes/email.py:195-200, src/cluster_erp/server/routes/email.py:222).

Record export formats

generate_export(fmt, entity_label, columns, records) returns (content, content_type, extension) (src/cluster_erp/server/services/record_formatter.py:308-318). The module docstring lists the formats: plain text, PDF through ReportLab, JSON (RFC 8259), CSV (RFC 4180, UTF-8 with BOM), and XML 1.0 (src/cluster_erp/server/services/record_formatter.py:1-11). This PDF path uses ReportLab, not the Chromium renderer above (src/cluster_erp/server/services/record_formatter.py:23-30).

Constraints and validation

  • send_blocking and send_system_email raise SystemMailNotConfiguredError when smtp_host is empty (src/cluster_erp/core/system_mail.py:85-86, src/cluster_erp/core/system_mail.py:112-113).
  • The settings validator requires smtp_from_email when smtp_host is set (src/cluster_erp/config/settings.py:832-835).
  • Attachment file names in system mail use safe_content_disposition (src/cluster_erp/core/system_mail.py:76-79).

Terms introduced

Term Code identifier Definition Turkish term Source
system mailbox core/system_mail.py The single SMTP identity that the application uses for its own mail, which other modules reach through SendTransactionalEmail. sistem posta kutusu src/cluster_erp/core/system_mail.py:1-12
PDF renderer PdfRenderer The process-wide Chromium that turns HTML into PDF. PDF oluşturucu src/cluster_erp/core/pdf_render.py:58

Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13