feat(notifications): document SMTP env and translate channel strings

Add the webhook + email Settings copy and the admin notification-health
panel labels across all six locales. Add the SMTP_* operator vars to the
env manifest (all-or-none: HOST + PORT + FROM enable the channel,
USER/PASS optional), to .env.production.example, and to the docker-compose
environment whitelist so an operator's .env values actually reach the
container.
This commit is contained in:
Marc-André Bombeck committed 2026-06-15 00:46:28 +02:00
1 parent 17dd10c3b9
commit c04bdc8f4e
9 files changed
+170

No files matched your search

+18
View File
@@ -84,6 +84,24 @@ API_TOKEN_HMAC_KEY="<openssl rand -hex 32>"
# APNS_KEY_FILE=""
# -----------------------------------------------------------------------------
# SMTP -- email notification channel (optional, all-or-none)
# -----------------------------------------------------------------------------
# Operator SMTP transport for the email channel. SMTP_HOST + SMTP_PORT +
# SMTP_FROM together enable it; SMTP_USER/SMTP_PASS are optional (omit for an
# unauthenticated relay). SMTP_SECURE=true uses implicit TLS (port 465);
# unset/false uses STARTTLS (port 587). Per-user recipient address is set in
# Settings -> Notifications, not here. Missing the core trio disables the
# channel silently. Listed in docker-compose.yml's environment whitelist so
# these reach the container.
# SMTP_HOST=""
# SMTP_PORT="587"
# SMTP_FROM="HealthLog <noreply@example.com>"
# SMTP_USER=""
# SMTP_PASS=""
# SMTP_SECURE="false"
# -----------------------------------------------------------------------------
# Deploy webhook -- Coolify -> HealthLog auto-deploy feedback
# -----------------------------------------------------------------------------
+12
View File
@@ -107,6 +107,18 @@ services:
# container (the `environment:` block is a whitelist). See
# docs/ops/tls-cert-pin.md.
TLS_LEAF_SPKI_PINS: "${TLS_LEAF_SPKI_PINS:-}"
# v1.17.1 — SMTP transport for the email notification channel (optional,
# all-or-none: HOST + PORT + FROM enable it; USER/PASS optional; SECURE
# toggles implicit TLS). Listed here so operator values in .env reach the
# container (the `environment:` block is a whitelist — vars not listed
# never propagate from .env, even with `${VAR}` substitution at
# compose-up). Per-user recipient is stored in the DB, not here.
SMTP_HOST: "${SMTP_HOST:-}"
SMTP_PORT: "${SMTP_PORT:-}"
SMTP_FROM: "${SMTP_FROM:-}"
SMTP_USER: "${SMTP_USER:-}"
SMTP_PASS: "${SMTP_PASS:-}"
SMTP_SECURE: "${SMTP_SECURE:-}"
depends_on:
db:
condition: service_healthy
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Auth-Token (optional)",
"ntfyAuthTokenHint": "Nur nötig bei privaten Topics mit Zugangsschutz.",
"webhook": "Webhook",
"webhookDescription": "Benachrichtigungen per POST an eine beliebige URL — Gotify, Discord, Slack, Matrix oder Home Assistant.",
"webhookEnable": "Webhook aktivieren",
"webhookUrl": "Webhook-URL",
"webhookUrlHint": "Die vollständige URL für den POST. Muss öffentlich erreichbar sein.",
"webhookHeaderName": "Header-Name (optional)",
"webhookHeaderValue": "Header-Wert (optional)",
"email": "E-Mail",
"emailDescription": "Warnungen und Erinnerungen per E-Mail empfangen.",
"emailEnable": "E-Mail aktivieren",
"emailRecipient": "Empfängeradresse",
"webPush": "Browser-Push",
"webPushDescription": "Erhalte Benachrichtigungen direkt im Browser, auch wenn HealthLog nicht geöffnet ist.",
"webPushNotSupported": "Dein Browser unterstützt keine Push-Benachrichtigungen.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Token widerrufen",
"medicationReminders": "Medikamentenerinnerungen",
"medicationRemindersDescription": "Schwellenwerte für die Farbübergänge der Erinnerungs-Badges auf den Medikamentenkarten.",
"notificationHealth": {
"title": "Zustellungsstatus",
"description": "Zustellungsergebnisse aller Nutzer der letzten 24 Stunden.",
"empty": "In diesem Zeitraum wurden keine Benachrichtigungen gesendet.",
"ok": "OK",
"error": "Fehlgeschlagen",
"skipped": "Übersprungen",
"autoDisabled": "Automatisch deaktivierte Kanäle"
},
"reminderLateMinutes": "Spät-Schwellenwert (Minuten)",
"reminderLateMinutesDescription": "Minuten nach Fenster-Ende bis der Badge von Gelb auf Orange wechselt.",
"reminderMissedMinutes": "Verpasst-Schwellenwert (Minuten)",
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Auth Token (optional)",
"ntfyAuthTokenHint": "Only needed for private topics with access control.",
"webhook": "Webhook",
"webhookDescription": "POST notifications to any URL — Gotify, Discord, Slack, Matrix, or Home Assistant.",
"webhookEnable": "Enable webhook",
"webhookUrl": "Webhook URL",
"webhookUrlHint": "The full URL to POST to. Must be publicly reachable.",
"webhookHeaderName": "Header name (optional)",
"webhookHeaderValue": "Header value (optional)",
"email": "Email",
"emailDescription": "Receive alerts and reminders by email.",
"emailEnable": "Enable email",
"emailRecipient": "Recipient address",
"webPush": "Browser Push",
"webPushDescription": "Receive notifications directly in your browser, even when HealthLog is not open.",
"webPushNotSupported": "Your browser does not support push notifications.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Token revoked",
"medicationReminders": "Medication Reminders",
"medicationRemindersDescription": "Thresholds for reminder badge color transitions on medication cards.",
"notificationHealth": {
"title": "Notification health",
"description": "Delivery results across all users over the last 24 hours.",
"empty": "No notifications sent in this window.",
"ok": "OK",
"error": "Failed",
"skipped": "Skipped",
"autoDisabled": "Auto-disabled channels"
},
"reminderLateMinutes": "Late threshold (minutes)",
"reminderLateMinutesDescription": "Minutes after window end until the badge changes from yellow to orange.",
"reminderMissedMinutes": "Missed threshold (minutes)",
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Token de autenticación (opcional)",
"ntfyAuthTokenHint": "Solo necesario para temas privados con control de acceso.",
"webhook": "Webhook",
"webhookDescription": "Envía notificaciones por POST a cualquier URL: Gotify, Discord, Slack, Matrix o Home Assistant.",
"webhookEnable": "Activar webhook",
"webhookUrl": "URL del webhook",
"webhookUrlHint": "La URL completa para el POST. Debe ser accesible públicamente.",
"webhookHeaderName": "Nombre de cabecera (opcional)",
"webhookHeaderValue": "Valor de cabecera (opcional)",
"email": "Correo electrónico",
"emailDescription": "Recibe alertas y recordatorios por correo electrónico.",
"emailEnable": "Activar correo electrónico",
"emailRecipient": "Dirección del destinatario",
"webPush": "Push del navegador",
"webPushDescription": "Recibe notificaciones directamente en tu navegador, incluso cuando HealthLog no está abierto.",
"webPushNotSupported": "Tu navegador no admite notificaciones push.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Token revocado",
"medicationReminders": "Recordatorios de medicación",
"medicationRemindersDescription": "Umbrales para los cambios de color de las insignias de recordatorio en las tarjetas de medicación.",
"notificationHealth": {
"title": "Estado de entrega",
"description": "Resultados de entrega de todos los usuarios en las últimas 24 horas.",
"empty": "No se enviaron notificaciones en este periodo.",
"ok": "OK",
"error": "Fallidas",
"skipped": "Omitidas",
"autoDisabled": "Canales desactivados automáticamente"
},
"reminderLateMinutes": "Umbral de retraso (minutos)",
"reminderLateMinutesDescription": "Minutos tras el fin de la ventana hasta que la insignia cambia de amarillo a naranja.",
"reminderMissedMinutes": "Umbral de omisión (minutos)",
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Jeton d’authentification (facultatif)",
"ntfyAuthTokenHint": "Nécessaire uniquement pour les sujets privés avec contrôle d’accès.",
"webhook": "Webhook",
"webhookDescription": "Envoyer les notifications par POST vers n’importe quelle URL — Gotify, Discord, Slack, Matrix ou Home Assistant.",
"webhookEnable": "Activer le webhook",
"webhookUrl": "URL du webhook",
"webhookUrlHint": "L’URL complète pour le POST. Doit être accessible publiquement.",
"webhookHeaderName": "Nom d’en-tête (facultatif)",
"webhookHeaderValue": "Valeur d’en-tête (facultatif)",
"email": "E-mail",
"emailDescription": "Recevoir les alertes et les rappels par e-mail.",
"emailEnable": "Activer l’e-mail",
"emailRecipient": "Adresse du destinataire",
"webPush": "Push navigateur",
"webPushDescription": "Recevez des notifications directement dans votre navigateur, même lorsque HealthLog n’est pas ouvert.",
"webPushNotSupported": "Votre navigateur ne prend pas en charge les notifications push.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Jeton révoqué",
"medicationReminders": "Rappels de médicaments",
"medicationRemindersDescription": "Seuils des transitions de couleur des badges de rappel sur les fiches de médicaments.",
"notificationHealth": {
"title": "État de distribution",
"description": "Résultats de distribution de tous les utilisateurs sur les dernières 24 heures.",
"empty": "Aucune notification envoyée sur cette période.",
"ok": "OK",
"error": "Échecs",
"skipped": "Ignorées",
"autoDisabled": "Canaux désactivés automatiquement"
},
"reminderLateMinutes": "Seuil de retard (minutes)",
"reminderLateMinutesDescription": "Minutes après la fin de la fenêtre avant que le badge passe du jaune à l'orange.",
"reminderMissedMinutes": "Seuil d'oubli (minutes)",
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Token di autenticazione (facoltativo)",
"ntfyAuthTokenHint": "Necessario solo per topic privati con controllo degli accessi.",
"webhook": "Webhook",
"webhookDescription": "Invia le notifiche via POST a qualsiasi URL — Gotify, Discord, Slack, Matrix o Home Assistant.",
"webhookEnable": "Attiva webhook",
"webhookUrl": "URL del webhook",
"webhookUrlHint": "L’URL completo per il POST. Deve essere raggiungibile pubblicamente.",
"webhookHeaderName": "Nome intestazione (opzionale)",
"webhookHeaderValue": "Valore intestazione (opzionale)",
"email": "Email",
"emailDescription": "Ricevi avvisi e promemoria via email.",
"emailEnable": "Attiva email",
"emailRecipient": "Indirizzo del destinatario",
"webPush": "Push del browser",
"webPushDescription": "Ricevi notifiche direttamente nel browser, anche quando HealthLog non è aperto.",
"webPushNotSupported": "Il tuo browser non supporta le notifiche push.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Token revocato",
"medicationReminders": "Promemoria dei farmaci",
"medicationRemindersDescription": "Soglie per i cambi di colore dei badge di promemoria sulle schede dei farmaci.",
"notificationHealth": {
"title": "Stato di consegna",
"description": "Risultati di consegna di tutti gli utenti nelle ultime 24 ore.",
"empty": "Nessuna notifica inviata in questo periodo.",
"ok": "OK",
"error": "Non riuscite",
"skipped": "Saltate",
"autoDisabled": "Canali disattivati automaticamente"
},
"reminderLateMinutes": "Soglia di ritardo (minuti)",
"reminderLateMinutesDescription": "Minuti dopo la fine della finestra prima che il badge passi da giallo ad arancione.",
"reminderMissedMinutes": "Soglia di mancata assunzione (minuti)",
+20
View File
@@ -4133,6 +4133,17 @@
"ntfyTopic": "Topic",
"ntfyAuthToken": "Token uwierzytelniania (opcjonalny)",
"ntfyAuthTokenHint": "Wymagany tylko dla prywatnych tematów z kontrolą dostępu.",
"webhook": "Webhook",
"webhookDescription": "Wysyłaj powiadomienia metodą POST na dowolny URL — Gotify, Discord, Slack, Matrix lub Home Assistant.",
"webhookEnable": "Włącz webhook",
"webhookUrl": "Adres URL webhooka",
"webhookUrlHint": "Pełny adres URL dla żądania POST. Musi być publicznie dostępny.",
"webhookHeaderName": "Nazwa nagłówka (opcjonalnie)",
"webhookHeaderValue": "Wartość nagłówka (opcjonalnie)",
"email": "E-mail",
"emailDescription": "Otrzymuj alerty i przypomnienia e-mailem.",
"emailEnable": "Włącz e-mail",
"emailRecipient": "Adres odbiorcy",
"webPush": "Push przeglądarki",
"webPushDescription": "Otrzymuj powiadomienia bezpośrednio w przeglądarce, nawet gdy HealthLog nie jest otwarty.",
"webPushNotSupported": "Twoja przeglądarka nie obsługuje powiadomień push.",
@@ -5011,6 +5022,15 @@
"authTokenRevoke": "Token unieważniony",
"medicationReminders": "Przypomnienia o lekach",
"medicationRemindersDescription": "Progi zmian koloru oznaczeń przypomnień na kartach leków.",
"notificationHealth": {
"title": "Stan dostarczania",
"description": "Wyniki dostarczania wszystkich użytkowników z ostatnich 24 godzin.",
"empty": "W tym okresie nie wysłano żadnych powiadomień.",
"ok": "OK",
"error": "Nieudane",
"skipped": "Pominięte",
"autoDisabled": "Automatycznie wyłączone kanały"
},
"reminderLateMinutes": "Próg opóźnienia (minuty)",
"reminderLateMinutesDescription": "Minuty po końcu okna, zanim oznaczenie zmieni kolor z żółtego na pomarańczowy.",
"reminderMissedMinutes": "Próg pominięcia (minuty)",
+20
View File
@@ -137,6 +137,26 @@
}
]
},
{
"name": "SMTP (email channel)",
"description": "Operator SMTP transport for the email notification channel (v1.17.1). All of SMTP_HOST, SMTP_PORT, SMTP_FROM together enable the channel; SMTP_USER/SMTP_PASS are optional (unauthenticated relay). Missing any of the three core vars disables email silently — the channel is never offered and the Settings card hides itself.",
"required": false,
"allOrNone": true,
"variables": [
{
"name": "SMTP_HOST",
"purpose": "SMTP server hostname, e.g. smtp.example.com."
},
{
"name": "SMTP_PORT",
"purpose": "SMTP port. 587 for STARTTLS (SMTP_SECURE unset/false), 465 for implicit TLS (SMTP_SECURE=true)."
},
{
"name": "SMTP_FROM",
"purpose": "From address for outbound mail, e.g. \"HealthLog <noreply@example.com>\"."
}
]
},
{
"name": "Off-host backups",
"description": "Required ALL-OR-NONE: any of these without the rest disables backups silently.",