./discourse-setup pone el nombre de usuario SMTP al principio de la contraseña SMTP

Recomendaciones generadas por LLM/IA

\nEl siguiente es un parche ajustado que:\n\n- deja de usar sed\n- construye una SMTP_URL codificada en porcentaje\n- edita containers/app.yml usando YAML de Ruby (Psych), por lo que el escape/codificación de YAML es manejado por un analizador real\n- elimina las variables SMTP por clave para evitar contradicciones\n\naplicar con git apply -p0 en el repositorio discourse_docker.\n\n- - -\n\nParche 1 -\n\ndiscourse-setup\n\n(escribe SMTP usando YAML de Ruby, no sed)\n\ndiff\n--- a/discourse-setup\n+++ b/discourse-setup\n@@ -867,6 +867,77 @@ write_smtp_settings() {\n local app_yml=\"containers/app.yml\"\n [[ -f \"$app_yml\" ]] || die \"Cannot find $app_yml. Did you run bootstrap?\"\n\n+ # Construye una SMTP_URL codificada en URL usando la biblioteca estándar de Python (sin juegos de escape de shell)\n+ urlencode() {\n+ python3 - \u003c\u003c'PY'\n+import sys, urllib.parse\n+print(urllib.parse.quote(sys.stdin.read().strip(), safe='._~-'))\n+PY\n+ }\n+\n+ # IMPORTANTE: lee variables sin manipulación de barras invertidas\n+ # (estas provienen de prompts anteriores; solo asegúrate de que -r se use en el momento del prompt)\n+ local addr=\"$smtp_address\"\n+ local port=\"$smtp_port\"\n+ local user_enc pass_enc\n+ user_enc=\"$(printf '%s' \"$smtp_user\" | urlencode)\"\n+ pass_enc=\"$(printf '%s' \"$smtp_password\" | urlencode)\"\n+ local smtp_url=\"smtp://${user_enc}:${pass_enc}@${addr}:${port}\"\n+\n+ # Usa Ruby para cargar/modificar/guardar YAML de forma segura (elimina 3 capas de escape)\n+ ruby - \u003c\u003c'RUBY' \"$app_yml\" \"$smtp_url\"\n+require \"yaml\"\n+require \"psych\"\n+path, url = ARGV\n+doc = YAML.safe_load(File.read(path), permitted_classes: [], aliases: true) || {}\n+\n+# Asegura que la estructura de nivel superior sea un Hash y tenga env\n+unless doc.is_a?(Hash)\n+ abort \"containers/app.yml no se analiza como un Hash\"\n+end\n+doc[\"env\"] ||= {}\n+env = doc[\"env\"]\n+\n+# Escribe SMTP_URL en una sola línea; elimina las variables por clave para evitar conflictos\n+env[\"SMTP_URL\"] = url\n+%w[DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_PORT DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD].each { |k| env.delete(k) }\n+\n+# Guarda de nuevo. (Psych preserva las cadenas de forma segura entre comillas según sea necesario.)\n+File.write(path, Psych.dump(doc))\n+RUBY\n+\n+ # chequeo rápido de cordura para el clásico fallo de \"contraseña prefijada por nombre de usuario\"\n+ python3 - \u003c\u003c'PY'\n+import re, sys\n+y = open(\"containers/app.yml\",\"r\",encoding=\"utf-8\").read()\n+m = re.search(r'^\\s*SMTP_URL:\\s*(?:\"|\\')?([^\\r\\n\"\\']+)', y, re.M)\n+assert m, \"SMTP_URL missing after write\"\n+creds = m.group(1).split('@',1)[0].split('://',1)[-1]\n+assert \":\" in creds, \"SMTP_URL creds missing ':'\"\n+u, p = creds.split(':',1)\n+assert not p.startswith(u), \"Password appears prefixed by username\"\n+print(\"SMTP_URL looks sane.\")\n+PY\n+}\n+\n- # Escribe entradas SMTP por clave (dirección/puerto/nombre de usuario/contraseña)\n- # (legado: realizado a través de sustituciones de sed)\n- # NOTA: históricamente frágil con caracteres especiales\n- update_setting_yaml \"DISCOURSE_SMTP_ADDRESS\" \"$smtp_address\"\n- update_setting_yaml \"DISCOURSE_SMTP_PORT\" \"$smtp_port\"\n- update_setting_yaml \"DISCOURSE_SMTP_USER_NAME\" \"$smtp_user\"\n- update_setting_yaml \"DISCOURSE_SMTP_PASSWORD\" \"$smtp_password\"\n-}\n+ # (escrituras legadas por clave eliminadas en favor de SMTP_URL a través de YAML)\n+}\n\n\nluego Parche 2 -\n\ntemplates/web.template.yml\n\n(para documentar la ruta más segura)\n\ndiff\n--- a/templates/web.template.yml\n+++ b/templates/web.template.yml\n@@ -68,6 +68,14 @@ params:\n DISCOURSE_SMTP_ENABLE_START_TLS: true\n #DISCOURSE_NOTIFICATION_EMAIL: noreply@example.com\n\n+ ## Configuración SMTP preferida en una sola línea (establecida por discourse-setup):\n+ ## Codifica en URL el nombre de usuario y la contraseña; ejemplo:\n+ ## SMTP_URL: \"smtp://user%40example.com:p%40ss%3Aword@smtp.example.com:587\"\n+ ##\n+ #SMTP_URL:\n+\n ## Si no puedes usar SMTP_URL, puedes establecer variables por clave en su lugar.\n ## Ten cuidado, ya que editar esas líneas con herramientas de shell puede ser frágil si los valores incluyen\n ## caracteres como @, :, /, \", \\ o saltos de línea.\n\n\npor qué funciona (y qué evita)\n\t•\tCapa bash: solo interpolamos variables simples; los secretos se pasan a Python/Ruby a través de stdin/argv, no a través de expresiones regulares de sed o evaluaciones de shell.\n\t•\tCapa sed: eliminada por completo.\n\t•\tCapa YAML: Ruby/Psych maneja las comillas y el escape correctamente; sin comillas hechas a mano.\n\t•\tCredenciales SMTP: la codificación % en SMTP_URL es el lugar correcto para codificar caracteres especiales para la autenticación.\n\nsi prefieres mantener las variables por clave, puedo darte un parche hermano que usa el mismo enfoque Ruby-YAML para establecer DISCOURSE_SMTP_* directamente (todavía sin sed), pero la ruta SMTP_URL es la más limpia porque es una clave, una escritura, un paso de codificación.\n