./discourse-setup coloca nome de usuário SMTP no início da senha SMTP

Recomendações geradas por LLM/IA

\nabaixo está um patch conciso que:\n\n- para de usar sed\n- constrói um SMTP_URL com codificação percentual\n- edita containers/app.yml via Ruby’s YAML (Psych), então o escape/codificação YAML é tratado por um analisador real\n- exclui as variáveis SMTP por chave para evitar contradições\n\naplicar com git apply -p0 no repositório discourse_docker.\n\n- - -\n\nPatch 1 -\n\ndiscourse-setup\n\n(escreve SMTP usando Ruby YAML, não 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+ # Constrói um SMTP_URL codificado em URL usando a biblioteca padrão do Python (sem jogos de escape do 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: lê variáveis sem manipulação de barra invertida\n+ # (estas vêm de prompts anteriores; apenas garanta que -r seja usado no momento do 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 carregar/modificar/descarregar YAML com segurança (elimina 3 camadas 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+# Garante que a estrutura de nível superior seja um Hash e tenha env\n+unless doc.is_a?(Hash)\n+ abort \"containers/app.yml não analisa para um Hash\"\n+end\n+doc[\"env\"] ||= {}\n+env = doc[\"env\"]\n+\n+# Escreve SMTP_URL de linha única; remove variáveis por chave para evitar conflitos\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+# Descarrega de volta. (Psych preserva strings com aspas seguras conforme necessário.)\n+File.write(path, Psych.dump(doc))\n+RUBY\n+\n+ # rápida verificação de sanidade para a falha clássica de \"senha prefixada pelo nome de usuário\"\n+ python3 - \u003c\u003c'PY'\n+import re, sys\n+y = open(\"containers/app.yml\",\"r\",encoding=\"utf-8\").read()\nm = re.search(r'^\\s*SMTP_URL:\\s*(?:\"|\\')?([^\\r\\n\"\\']+)', y, re.M)\n+assert m, \"SMTP_URL ausente após a escrita\"\n+creds = m.group(1).split('@',1)[0].split('://',1)[-1]\n+assert \":\" in creds, \"Credenciais SMTP_URL ausentes ':'\"\n+u, p = creds.split(':',1)\n+assert not p.startswith(u), \"Senha parece prefixada pelo nome de usuário\"\n+print(\"SMTP_URL parece razoável.\")\n+PY\n+}\n+\n- # Escreve entradas SMTP por chave (endereço/porta/nome de usuário/senha)\n- # (legado: realizado via substituições de sed)\n- # NOTA: historicamente frágil com caracteres especiais\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+ # (escritas legadas por chave removidas em favor de SMTP_URL via YAML)\n+}\n\n\nentão Patch 2 -\n\ntemplates/web.template.yml\n\n(para documentar o caminho mais seguro)\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+ ## Configuração SMTP preferida em linha única (definida por discourse-setup):\n+ ## Codifica em URL o nome de usuário e a senha; exemplo:\n+ ## SMTP_URL: \"smtp://user%40example.com:p%40ss%3Aword@smtp.example.com:587\"\n+ ##\n+ #SMTP_URL:\n+\n ## Se você não puder usar SMTP_URL, pode definir variáveis por chave em vez disso.\n ## Cuidado ao editar essas linhas com ferramentas de shell, pois os valores podem incluir\n ## caracteres como @, :, /, \", \\ ou novas linhas.\n\n\npor que isso funciona (e o que evita)\n\t•\tcamada bash: interpolamos apenas variáveis simples; segredos são passados para Python/Ruby via stdin/argv, não através de regexes sed ou avaliações de shell.\n\t•\tcamada sed: removida completamente.\n\t•\tcamada YAML: Ruby/Psych lida com aspas e escape corretamente; sem aspas manuais.\n\t•\tcredenciais SMTP: o escape % na SMTP_URL é o lugar certo para codificar caracteres especiais para autenticação.\n\nse você preferir manter variáveis por chave, posso fornecer um patch irmão que usa a mesma abordagem Ruby-YAML para definir DISCOURSE_SMTP_* diretamente (ainda sem sed), mas a rota SMTP_URL é a mais limpa porque é uma chave, uma escrita, uma etapa de codificação.\n