Discurso con otros sitios web, problema de SMTP: Fin de archivo alcanzado

(para el personal: esto no tiene relación con la suscripción alojada con la que también está asociada mi cuenta)

Instalé Discourse en un VPS siguiendo las instrucciones de Run other websites on the same machine as Discourse, pero con esta diferencia: adapté el archivo app.yml antes de la primera instalación:

sudo mkdir /var/discourse
sudo git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
sudo cp samples/standalone.yml containers/app.yml
sudo nano containers/app.yml

En el YAML comenté la sección de puertos, agregué - "templates/web.socketed.template.yml" y configuré el nombre de host + SMTP:

  ## TODO: El nombre de dominio al que responderá esta instancia de Discourse
  ## Obligatorio. Discourse no funcionará con una dirección IP desnuda.
  DISCOURSE_HOSTNAME: 'discuss.mydomain.community'

  ## TODO: Lista de correos electrónicos separados por comas que serán administradores y desarrolladores
  ## en el registro inicial, ejemplo 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: 'someuser@protonmail.com,anotheruser@otherdomain.io'

  ## TODO: El servidor SMTP utilizado para validar nuevas cuentas y enviar notificaciones
  # La dirección, el nombre de usuario y la contraseña de SMTP son obligatorios
  # ¡ADVERTENCIA: el carácter '#' en la contraseña de SMTP puede causar problemas!
  DISCOURSE_SMTP_ADDRESS: smtp.myprovider.email
  DISCOURSE_SMTP_PORT: 465
  DISCOURSE_SMTP_USER_NAME: mydomain-no-reply@otherdomain.io
  DISCOURSE_SMTP_PASSWORD: pa$$word
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (opcional, valor predeterminado true)

Luego inicialicé e inicié la aplicación de Discourse:

sudo ./launcher bootstrap app
sudo ./launcher start app

Eso funcionó. Detuve Discourse y configuré el nginx externo (en /etc/nginx/conf.d/discourse.conf) con la configuración sugerida solo HTTP (solo para pruebas). Podía acceder a http://discuss.mydomain.community.

Detuve Discourse nuevamente y con certbot actualicé el archivo discourse.conf y ahora tengo:

server {
	server_name discuss.mydomain.community;  # <-- cambiar esto

	location / {
		proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
		proxy_set_header Host $http_host;
		proxy_http_version 1.1;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Real-IP $remote_addr;
	}

    listen [::]:443 ssl ipv6only=on; # gestionado por Certbot
    listen 443 ssl; # gestionado por Certbot
    ssl_certificate /etc/letsencrypt/live/discuss.mydomain.community/fullchain.pem; # gestionado por Certbot
    ssl_certificate_key /etc/letsencrypt/live/discuss.mydomain.community/privkey.pem; # gestionado por Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # gestionado por Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # gestionado por Certbot

}
server {
    if ($host = discuss.mydomain.community) {
        return 301 https://$host$request_uri;
    } # gestionado por Certbot


	listen 80; listen [::]:80;
	server_name discuss.mydomain.community;
    return 404; # gestionado por Certbot
}

Hasta aquí, todo bien. Puedo acceder a Discourse por HTTPS (más tarde ejecuté ./launcher rebuild app cuando las cosas no funcionaron, pero eso no marcó diferencia).

En la pantalla «Finalizar instalación», después de enviar el formulario de registro, obtengo «Hemos enviado un correo de activación a someuser@protonmail.com».

Problema: no llega ningún correo.

No llega ningún correo electrónico al buzón del administrador. Verifiqué el buzón de mydomain-no-reply@otherdomain.io y tampoco hay nada.

Nota: Es posible que todo el problema se deba a que el usuario de correo está en otherdomain.io y debe residir en mydomain.community. Pero, hasta donde sé, esto no es un requisito.

Comencé a solucionar el problema y posteriormente probé con los siguientes cambios en app.yml (con un rebuild app en medio):

  DISCOURSE_SMTP_ENABLE_START_TLS: false

Sin éxito. Continué:

## Si deseas establecer la dirección de correo electrónico «De» para tu primer registro, descomenta y cambia:
  - exec: rails r "SiteSetting.notification_email='mydomain-no-reply@otherdomain.io"

Así que procedí con Troubleshoot email on a new Discourse install :

  • otherdomain.io tiene DKIM y SPF configurados correctamente en DNS
  • Usar telnet desde el VPS hacia el proveedor SMTP funciona
  • Usar telnet desde el contenedor Docker (con docker exec e instalando telnet) también funciona

Ejecuté ./discourse-doctor y hubo dos partes que destacaron (el resto de los resultados eran los esperados):

========================================
Versión de Discourse en discuss.mydomain.community: Discourse 2.6.0.beta2 
Versión de Discourse en localhost: NO ENCONTRADA
==================== PROBLEMA DE DNS ====================
Este servidor reporta NO ENCONTRADA, pero discuss.mydomain.community reporta Discourse 2.6.0.beta2.
Esto sugiere que tienes un problema de DNS o que un proxy intermedio es el culpable.
Si estás usando Cloudflare o una CDN, es posible que esté mal configurada.
==================== PRUEBA DE CORREO ====================
Para una prueba robusta, obtén una dirección en http://www.mail-tester.com/
Enviando correo a REDACTED . . 
Probando el envío a test-k86jiyqb9@srv1.mail-tester.com usando smtp.myprovider.email:465.
======================================== ERROR ========================================
                                    ERROR INESPERADO

fin de archivo alcanzado

====================================== SOLUCIÓN =======================================
Este no es un error común. ¡No existe una solución recomendada!

Por favor, reporta el mensaje de error exacto anterior en https://meta.discourse.org/
(¡Y una solución, si la encuentras!)

Lo intenté dos veces. Una vez con el correo configurado y otra con uno proporcionado por mail-tester.com. Los resultados fueron los mismos. Así que eso no parece bueno.

Nota: Aparentemente, el procedimiento de instalación de Docker también sirve versiones beta. Bueno saberlo.

Al revisar el registro de producción, aparece lo siguiente:

Started GET "/" for REDACTED-IP at 2020-09-03 06:21:57 +0000
Processing by FinishInstallationController#index as HTML
  Rendering finish_installation/index.html.erb within layouts/finish_installation
  Rendered finish_installation/index.html.erb within layouts/finish_installation (Duration: 3.2ms | Allocations: 356)
  Rendered layouts/_head.html.erb (Duration: 15.7ms | Allocations: 2969)
Completed 200 OK in 323ms (Views: 140.3ms | ActiveRecord: 0.0ms | Allocations: 32137)
Started GET "/finish-installation/register" for REDACTED-IP at 2020-09-03 06:22:01 +0000
Processing by FinishInstallationController#register as HTML
  Rendering finish_installation/register.html.erb within layouts/finish_installation
  Rendered finish_installation/register.html.erb within layouts/finish_installation (Duration: 7.1ms | Allocations: 1607)
  Rendered layouts/_head.html.erb (Duration: 22.3ms | Allocations: 3139)
Completed 200 OK in 107ms (Views: 41.3ms | ActiveRecord: 0.0ms | Allocations: 11760)
Started POST "/finish-installation/register" for REDACTED-IP at 2020-09-03 06:22:22 +0000
Processing by FinishInstallationController#register as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"l1hEEsK/gur5yplJdMIHttZAgYcuzLLkESaAI87IMb88nAFqNwi7l3yJ+3EJBw7leFypVGbH4C5hJl7VnJVYBQ==", "email"=>"someuser@protonmail.com", "username"=>"someusername", "password"=>"[FILTERED]", "commit"=>"Register"}
Redirected to https://discuss.mydomain.community/finish-installation/confirm-email
Completed 302 Found in 48ms (ActiveRecord: 0.0ms | Allocations: 4246)
  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
Started GET "/finish-installation/confirm-email" for REDACTED-IP at 2020-09-03 06:22:22 +0000
Processing by FinishInstallationController#confirm_email as HTML
  Rendering finish_installation/confirm_email.html.erb within layouts/finish_installation
  Rendered finish_installation/confirm_email.html.erb within layouts/finish_installation (Duration: 2.3ms | Allocations: 418)
  Rendered layouts/_head.html.erb (Duration: 7.9ms | Allocations: 1612)
Completed 200 OK in 25ms (Views: 22.1ms | ActiveRecord: 0.0ms | Allocations: 4611)
Delivered mail ea8af868-4a2c-4312-85dd-f57061a3cd90@discuss.mydomain.community (60015.9ms)
Job exception: Net::ReadTimeout

Esperé un poco y luego, desde el navegador, solicité «Reenviar correo de notificación». Lo siguiente se agregó al registro de producción:

Delivered mail 47ca6f15-cd9e-4c96-a670-6646e2bda585@discuss.mydomain.community (60007.9ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
Delivered mail 02367872-af3a-4df4-9a68-4e5e7c5eda60@discuss.mydomain.community (60007.4ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
Delivered mail ee9ee1fc-6fd1-4970-89fa-260efe2dd04c@discuss.mydomain.community (60014.1ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.1ms | Allocations: 31)
Delivered mail 9030f87b-99df-4de2-9a60-2c57f7c752de@discuss.mydomain.community (60007.0ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
Started PUT "/finish-installation/resend-email" for REDACTED-IP at 2020-09-03 06:31:22 +0000
Processing by FinishInstallationController#resend_email as HTML
  Parameters: {"authenticity_token"=>"NE21scxxyZz3/DxDkoF8kwi9GXoNKvnstNJdKZjQs7afigDKWcbw4XK/XnvvRHTApqExqUUghybE1oPfyo3aDA=="}
  Rendering finish_installation/resend_email.html.erb within layouts/finish_installation
  Rendered finish_installation/resend_email.html.erb within layouts/finish_installation (Duration: 0.9ms | Allocations: 163)
  Rendered layouts/_head.html.erb (Duration: 2.5ms | Allocations: 269)
Completed 200 OK in 63ms (Views: 6.5ms | ActiveRecord: 0.0ms | Allocations: 6408)
  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
Delivered mail 127cc350-3fb0-4ef1-8759-391fb407b1cb@discuss.mydomain.community (60008.0ms)
Job exception: Net::ReadTimeout

Delivered mail d9c70dfd-5a8b-4f4c-bafa-5a540fc8ed4f@discuss.mydomain.community (60010.0ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.1ms | Allocations: 31)
Delivered mail e9e67ed1-d7b1-4e8a-ba11-30501c6fae89@discuss.mydomain.community (60012.4ms)
Job exception: end of file reached

  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.2ms | Allocations: 31)
  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.1ms | Allocations: 31)
Delivered mail 82d0361e-0349-4a1a-928e-dcb16dcffdbc@discuss.mydomain.community (60008.6ms)
Job exception: end of file reached

Contacté a mi proveedor de alojamiento para ver si el problema estaba de su lado. Dijeron que, según ellos, esta configuración debería funcionar bien, pero que el VPS no había generado ninguna actividad en el servidor SMTP.

Así que esa es mi situación actual… publicando en Meta.

¿Podría ser que el tráfico saliente hacia el servidor de correo esté bloqueado? ¿Puedes hacer telnet allí? ¿Desde dentro del contenedor?

Sí, puedo conectarme correctamente al servidor SMTP usando telnet desde dentro del contenedor Docker. Sin embargo, no puedo enviar un correo de prueba con telnet, ya que mi proveedor no lo permite (cierra la conexión al recibir más comandos).

La solución pareció sencilla. Aunque mi proveedor indica el puerto anterior, probé con telnet en el 587 y funcionó. Así que modifiqué app.yml, realicé una reconstrucción… y todo funcionó correctamente :smiley:

Antes de ver esto, iba a recomendar este cambio.

El puerto 465 es SMTP sobre SSL, que está obsoleto.
El puerto 587 es el puerto MSA (agente de envío de correo) en el que normalmente se admite STARTTLS (actualización de una conexión sin cifrar a una conexión TLS).

Cuando tenías el puerto 465 en la configuración, Discourse intentaba comunicarse en texto plano con un puerto SSL.

Gracias, @supermathie, he marcado tu respuesta como la solución. Explicación clara.

Hola @supermathie

Al parecer, el puerto 465 ha sido (o está en proceso de ser) desobsoleto según el RFC 8314. Mi proveedor de correo actual (mailfence.com) parece seguir esa recomendación.

¿Existe alguna forma de forzar TLS en la conexión usando el puerto 465? Esto debería resolver mi problema, ya que he verificado con swaks que usar STARTTLS (–tls) falla, mientras que usar --tls-on-connect (–tlsc) funciona correctamente desde dentro del contenedor:

swaks --to user@example.com --from myuser@mailfence.com --server smtp.mailfence.com:465 --auth LOGIN --tlsc --auth-user myuser@mailfence.com

Saludos,

Ah, se está reutilizando como envío sobre TLS, eso tiene sentido.

Por ahora no. Parece que ActionMailer lo soporta cuando configuras :ssl = true en smtp_settings, pero en este momento no tenemos una ruta de código para habilitarlo.

Estoy seguro de que agradeceríamos una PR que añadiera ese soporte.