PDF invoice reports + SMTP email sending

PDF Reports:
- Professional invoice HTML renderer (company header, partner address,
  styled line items, totals, Odoo-purple branding, A4 @page CSS)
- wkhtmltopdf installed in Docker runtime stage for real PDF generation
- Print button on invoice form (opens PDF in new tab)
- Exported HtmlToPDF/RenderInvoiceHTML for cross-package use

SMTP Email:
- SendEmail + SendEmailWithAttachments with MIME multipart support
- Base64 file attachments
- Config via ODOO_SMTP_HOST/PORT/USER/PASSWORD/FROM env vars
- LoadSMTPConfig helper, nil auth for relay servers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc
2026-04-04 13:58:19 +02:00
parent cc6184a18b
commit 2c7c1e6c88
6 changed files with 336 additions and 12 deletions

View File

@@ -37,6 +37,13 @@ type Config struct {
// Limits
LimitMemorySoft int64
LimitTimeReal int
// SMTP Email
SMTPHost string
SMTPPort int
SMTPUser string
SMTPPassword string
SMTPFrom string
}
// DefaultConfig returns a configuration with default values.
@@ -54,6 +61,7 @@ func DefaultConfig() *Config {
Workers: 0,
DataDir: "/var/lib/odoo",
LogLevel: "info",
SMTPPort: 587,
}
}
@@ -104,6 +112,23 @@ func (c *Config) LoadFromEnv() {
if v := os.Getenv("ODOO_BUILD_DIR"); v != "" {
c.BuildDir = v
}
if v := os.Getenv("ODOO_SMTP_HOST"); v != "" {
c.SMTPHost = v
}
if v := os.Getenv("ODOO_SMTP_PORT"); v != "" {
if p, err := strconv.Atoi(v); err == nil {
c.SMTPPort = p
}
}
if v := os.Getenv("ODOO_SMTP_USER"); v != "" {
c.SMTPUser = v
}
if v := os.Getenv("ODOO_SMTP_PASSWORD"); v != "" {
c.SMTPPassword = v
}
if v := os.Getenv("ODOO_SMTP_FROM"); v != "" {
c.SMTPFrom = v
}
}
// DSN returns the PostgreSQL connection string.