Von LLM/KI generierte Empfehlungen
Unten ist ein kleiner Patch, der:
- sed nicht mehr verwendet
- eine prozentkodierte SMTP_URL erstellt
- containers/app.yml über Ruby’s YAML (Psych) bearbeitet, sodass YAML-Anführungszeichen/Escaping von einem echten Parser behandelt werden
- die SMTP-Variablen pro Schlüssel löscht, um Widersprüche zu vermeiden
Anwenden mit git apply -p0 im discourse_docker-Repository.
Patch 1 -
discourse-setup
(SMTP mit Ruby YAML schreiben, nicht mit sed)
--- a/discourse-setup
+++ b/discourse-setup
@@ -867,6 +867,77 @@ write_smtp_settings() {
local app_yml="containers/app.yml"
[[ -f "$app_yml" ]] || die "Cannot find $app_yml. Did you run bootstrap?"
+ # URL-kodierte SMTP_URL mit Python-Standardbibliothek erstellen (keine Shell-Escaping-Spielchen)
+ urlencode() {
+ python3 - <<'PY'
+import sys, urllib.parse
+print(urllib.parse.quote(sys.stdin.read().strip(), safe='._~-'))
+PY
+ }
+
+ # WICHTIG: Variablen ohne Backslash-Veränderung lesen
+ # (diese stammen aus früheren Prompts; stellen Sie einfach sicher, dass -r zur Prompt-Zeit verwendet wird)
+ local addr="$smtp_address"
+ local port="$smtp_port"
+ local user_enc pass_enc
+ user_enc="$(printf '%s' "$smtp_user" | urlencode)"
+ pass_enc="$(printf '%s' "$smtp_password" | urlencode)"
+ local smtp_url="smtp://${user_enc}:${pass_enc}@${addr}:${port}"
+
+ # Ruby verwenden, um YAML sicher zu laden/modifizieren/dumpen (tötet 3 Ebenen des Escapings)
+ ruby - <<'RUBY' "$app_yml" "$smtp_url"
+require "yaml"
+require "psych"
+path, url = ARGV
+doc = YAML.safe_load(File.read(path), permitted_classes: [], aliases: true) || {}
+
+# Sicherstellen, dass die oberste Struktur ein Hash ist und env enthält
+unless doc.is_a?(Hash)
+ abort "containers/app.yml parst nicht zu einem Hash"
+end
+doc["env"] ||= {}
+env = doc["env"]
+
+# Einzelzeilige SMTP_URL schreiben; pro Schlüssel entfernte Variablen, um Konflikte zu vermeiden
+env["SMTP_URL"] = url
+%w[DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_PORT DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD].each { |k| env.delete(k) }
+
+# Zurückschreiben. (Psych bewahrt Zeichenketten sicher kodiert, wie benötigt.)
+File.write(path, Psych.dump(doc))
+RUBY
+
+ # Schnelle Integritätsprüfung für das klassische Fehlschlagen "Passwort mit Benutzernamen als Präfix"
+ python3 - <<'PY'
+import re, sys
+y = open("containers/app.yml","r",encoding="utf-8").read()
+m = re.search(r'^\\s*SMTP_URL:\\s*(?:\"|\\')?([^\\r\\n\"\\']+)', y, re.M)
+assert m, "SMTP_URL nach dem Schreiben fehlt"
+creds = m.group(1).split('@',1)[0].split('://',1)[-1]
+assert ":" in creds, "SMTP_URL-Anmeldedaten fehlen ':'"
+u, p = creds.split(':',1)
+assert not p.startswith(u), "Passwort scheint mit Benutzernamen als Präfix versehen zu sein"
+print("SMTP_URL sieht vernünftig aus.")
+PY
+}
+
- # Schreibe SMTP-Einträge pro Schlüssel (Adresse/Port/Benutzername/Passwort)
- # (Legacy: durchgeführt über sed-Substitutionen)
- # HINWEIS: Historisch fragil bei Sonderzeichen
- update_setting_yaml "DISCOURSE_SMTP_ADDRESS" "$smtp_address"
- update_setting_yaml "DISCOURSE_SMTP_PORT" "$smtp_port"
- update_setting_yaml "DISCOURSE_SMTP_USER_NAME" "$smtp_user"
- update_setting_yaml "DISCOURSE_SMTP_PASSWORD" "$smtp_password"
-}
+ # (Legacy-Schreibvorgänge pro Schlüssel zugunsten von SMTP_URL über YAML entfernt)
+}
dann Patch 2 -
templates/web.template.yml
(um den sichereren Weg zu dokumentieren)
--- a/templates/web.template.yml
+++ b/templates/web.template.yml
@@ -68,6 +68,14 @@ params:
DISCOURSE_SMTP_ENABLE_START_TLS: true
#DISCOURSE_NOTIFICATION_EMAIL: noreply@example.com
+ ## Bevorzugte einzeilige SMTP-Konfiguration (gesetzt durch discourse-setup):
+ ## URL-kodieren Sie Benutzername und Passwort; Beispiel:
+ ## SMTP_URL: "smtp://user%40example.com:p%40ss%3Aword@smtp.example.com:587"
+ ##
+ #SMTP_URL:
+
## Wenn Sie SMTP_URL nicht verwenden können, können Sie stattdessen Variablen pro Schlüssel setzen.
## Beachten Sie, dass die Bearbeitung dieser Zeilen mit Shell-Tools fragil sein kann, wenn Werte enthalten
## Zeichen wie @, :, /, ", \, oder Zeilenumbrüche.
Warum das funktioniert (und was es vermeidet)
• Bash-Ebene: Wir interpolieren nur einfache Variablen; Geheimnisse werden über stdin/argv an Python/Ruby übergeben, nicht über sed-Regexes oder Shell-Evals.
• Sed-Ebene: vollständig entfernt.
• YAML-Ebene: Ruby/Psych behandelt Anführungszeichen und Escaping ordnungsgemäß; keine handgefertigten Anführungszeichen.
• SMTP-Anmeldedaten: %-Kodierung in SMTP_URL ist der richtige Ort, um Sonderzeichen für die Authentifizierung zu kodieren.
Wenn Sie lieber Variablen pro Schlüssel beibehalten möchten, kann ich Ihnen einen Schwester-Patch geben, der denselben Ruby-YAML-Ansatz verwendet, um DISCOURSE_SMTP_* direkt zu setzen (immer noch kein sed), aber der SMTP_URL-Weg ist der sauberste, da es sich um einen Schlüssel, einen Schreibvorgang und einen Kodierungsschritt handelt.