Discourse SMTP envoie "EHLO localhost" au lieu du domaine, ce qui casse le relais smtp de Google

Voici un peu de contexte : Emails have stopped sending - end of file reached

Il y a environ une semaine (13 janvier 2021), l’envoi d’e-mails a commencé à échouer via le serveur smtp-relay.gmail.com de Google (ce qui est un usage autorisé et prévu pour les utilisateurs de Google Apps).

Sidekiq a signalé les échecs avec des erreurs EOFErrors :

Jobs::HandledExceptionWrapper: Wrapped EOFError: end of file reached

Et /logs a également rapporté les tâches échouées :

Job exception: end of file reached

La trace d’appel est disponible dans l’autre publication.

===================

L’enquête a révélé que les installations à jour de Discourse se connectent aux relais SMTP avec ‘EHLO localhost’ — et Google a commencé à rejeter ces requêtes il y a environ une semaine.

À partir d’un tcpdump sur une instance de production :

0x0030:  d10f f8e4 4548 4c4f 206c 6f63 616c 686f  ....EHLO.localho
	0x0040:  7374 0d0a                                st..
...
	0x0030:  de62 f0c3 3432 3120 342e 372e 3020 5472  .b..421.4.7.0.Tr
	0x0040:  7920 6167 6169 6e20 6c61 7465 722c 2063  y.again.later,.c
	0x0050:  6c6f 7369 6e67 2063 6f6e 6e65 6374 696f  losing.connectio
	0x0060:  6e2e 2028 4548 4c4f 2920 6a31 3673 6d34  n..(EHLO).j16sm4
	0x0070:  3831 3932 3976 736d 2e31 202d 2067 736d  81929vsm.1.-.gsm
	0x0080:  7470 0d0a                                tp..

Et la réplication avec telnet donne le même résultat :

root@conversation:~# telnet smtp-relay.gmail.com 587
Trying 74.125.137.28...
Connected to smtp-relay.gmail.com.
Escape character is '^]'.
220 smtp-relay.gmail.com ESMTP ls8sm507258pjb.6 - gsmtp
ehlo localhost.localdomain
421 4.7.0 Try again later, closing connection. (EHLO) ls8sm507258pjb.6 - gsmtp
Connection closed by foreign host.

Cependant, un ehlo spécifique au domaine fonctionne correctement :

root@conversation:~# telnet smtp-relay.gmail.com 587
Trying 74.125.137.28...
Connected to smtp-relay.gmail.com.
Escape character is '^]'.
220 smtp-relay.gmail.com ESMTP p10sm668563uaw.3 - gsmtp
ehlo conversation.sevarg.net
250-smtp-relay.gmail.com at your service, [64.227.96.27]
250-SIZE 157286400
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

======

Sur la base des journaux, j’ai identifié le fichier à modifier pour tester la correction (dans l’image Docker) :

/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/mail-2.7.1/lib/mail/network/delivery_methods/smtp.rb

En changeant

DEFAULTS = {
      :address              => 'localhost',
      :port                 => 25,
      :domain               => 'localhost.localdomain',

en

    DEFAULTS = {
      :address              => 'conversation.sevarg.net',
      :port                 => 25,
      :domain               => 'conversation.sevarg.net',

le problème a été résolu (après un redémarrage de l’instance). L’EHLO est maintenant envoyé avec la chaîne de domaine, et les e-mails sont maintenant envoyés correctement depuis mon instance.

================

Comportement souhaité : Lors de l’envoi d’e-mails, l’installation par défaut de Discourse utilise le nom de domaine configuré pour la connexion initiale au serveur SMTP. Alternativement, une option de configuration existe pour remplacer le domaine envoyé. Si cela existe, je n’ai pas réussi à le trouver en effectuant une recherche.

5 « J'aime »

Je pense avoir déjà vu cette même erreur chez d’autres personnes (qui n’utilisaient peut-être pas non plus Google Domains).

Une solution à plus long terme consisterait à ajouter une astuce dans votre app.yml pour effectuer cette réécriture automatiquement. Mais espérons qu’une véritable correction sera bientôt disponible.

S’il existe un moyen de le corriger via app.yml, je suis tout à fait intéressé. Le fait d’écrire en dur mon domaine dans le code pour que l’envoi d’e-mails fonctionne n’est clairement pas une solution « appropriée », mais cela montre où résoudre le problème de manière plus permanente.

Y a-t-il une raison pour laquelle il n’utilise pas simplement le domaine configuré pour l’EHLO ? Ce serait « plus correct » que localhost.

Excellent travail d’enquête @Syonyk !

Pourriez-vous s’il vous plaît partager les paramètres SMTP de votre fichier app.yml ?

2 « J'aime »

Il n’y a rien d’autre que les paramètres requis habituels.

  DISCOURSE_SMTP_ADDRESS: smtp-relay.gmail.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: [nom d'utilisateur]
  DISCOURSE_SMTP_PASSWORD: [mot de passe]

Pouvez-vous s’il vous plaît essayer d’ajouter une nouvelle ligne avec

DISCOURSE_SMTP_DOMAIN: conversation.sevarg.net

et réessayer ?

3 « J'aime »

J’ai ajouté cette ligne et reconstruit l’application (existe-t-il un moyen de contourner cette étape ?).

Je vois maintenant « domain » dans mes paramètres de messagerie, le fichier smtp.rb est revenu à localhost par défaut, et les e-mails semblent être envoyés correctement : je peux envoyer des messages de test et ils sont bien transmis.

Cela résout donc le problème, autant que je puisse en juger. Serait-il possible d’ajouter cela à la documentation ou au flux de configuration quelque part ? J’ai cherché pendant un moment ce paramètre sans le trouver. Même en connaissant l’option de configuration, il y a très peu de mentions à ce sujet.

2 « J'aime »

Cela peut être ajouté dans ce bloc du fichier d’exemple app.yml par défaut :

Pensez-vous que cela soit utile ?

1 « J'aime »

Tant que cela est documenté quelque part, je suis ravi.

Cependant, si ce n’est pas défini, le code pourrait-il utiliser la valeur de DISCOURSE_HOSTNAME (ce qui serait correct dans presque tous les cas simples) ? Envoyer ‘localhost’ dans EHLO est généralement incorrect (du moins lors de la communication avec un serveur qui n’est pas sur localhost).

Je pense qu’il est judicieux de l’ajouter à standalone.yml et web_only.yml.

Je suis d’accord pour dire qu’il devrait probablement prendre par défaut DISCOURSE_HOSTNAME. Cela semble sûrement mieux que localhost. Est-ce que cela a changé récemment ?

Le problème ici est que cela fonctionne pour toutes les dizaines de milliers d’instances Discourse qui ne reposent pas actuellement sur Google pour l’envoi d’e-mails. Changer une telle valeur par défaut peut casser le fonctionnement pour tout le monde, alors que cela ne corrige le problème que pour les utilisateurs de Google Apps, qui sont comparativement peu nombreux.

Je vais l’ajouter à l’exemple, et nous devrions également avoir un sujet howto intitulé « Utilisation de Google Apps pour l’envoi d’e-mails » qui documente cela. Quelqu’un peut-il s’en charger ?

4 « J'aime »

D’accord. Je conviens qu’il est probablement préférable de privilégier la prudence, mais je suppose que n’importe quel serveur de messagerie qui accepte localhost acceptera aussi DISCOURSE_HOSTNAME. Je n’ai malheureusement aucune donnée à ce sujet. :wink: Le fait de l’inclure dans les modèles standards est probablement suffisant.

1 « J'aime »

Oui, mais envoyer ‘localhost’ (à un hôte distant) est également incorrect selon le RFC.

C’est moi qui ai mis l’accent.

Les anciens RFC indiquent que le serveur ne devrait pas rejeter les clients en fonction de la chaîne EHLO, ce que Google semble faire, mais je ne vois pas cette formulation dans le 5321.

Je m’attends à ce que tout serveur de messagerie distant qui tolère localhost tolère (et préfère) un FQDN tel que requis par le RFC. Je comprends la volonté de ne rien casser, mais selon ma lecture des RFC pertinents, Discourse est simplement incorrect par défaut, et le fait que cela fonctionne est le résultat de serveurs SMTP distants excessivement permissifs.

1 « J'aime »

Je serais ravi de fusionner une PR vers ./discourse-setup qui la définit par défaut comme étant identique à DISCOURSE_HOSTNAME, à condition qu’il soit prouvé que cela ne pose aucun problème avec les services SMTP les plus courants que nous recommandons aux utilisateurs d’utiliser.

2 « J'aime »

Je ne peux pas tester l’envoi complet de bout en bout car je n’ai pas de comptes, mais :

Mailgun

% nc smtp.mailgun.com 587
220 Mailgun Influx prêt
ehlo conversation.sevarg.net
250-smtp-out-n04.prod.us-west-2.postgun.com
250-AUTH PLAIN LOGIN
...

Sendgrid

% nc smtp.sendgrid.net 587
220 SG ESMTP service prêt sur ismtpd0021p1las1.sendgrid.net
ehlo conversation.sevarg.net
250-smtp.sendgrid.net
250-8BITMIME
...

Mailjet

 % nc smtp.mailjet.com 587
220 in.mailjet.com ESMTP Mailjet
ehlo conversation.sevarg.net
250-smtpin.mailjet.com
250-PIPELINING
...

ElasticMail

… ne répond pas vraiment à un helo ou ehlo d’aucune sorte. o.O Que ce soit depuis localhost ou avec de vrais domaines.

Je pense que le définir lors de la configuration est la bonne solution, car au moins les utilisateurs seront informés et pourront le modifier si nécessaire.

6 « J'aime »

Il existe un autre problème connexe : discourse-doctor ne semble pas définir correctement le domaine et échouera toujours lorsque l’installation réelle pourra envoyer des courriels.

Avec la configuration fonctionnelle, discourse-doctor signale toujours l’échec de fin de fichier.

======================================== ERREUR ========================================
                                    ERREUR INATTENDUE

fin de fichier atteinte

====================================== SOLUTION =======================================
Il s'agit d'une erreur peu courante. Aucune solution recommandée n'existe !

Veuillez signaler le message d'erreur exact ci-dessus à https://meta.discourse.org/
(Et une solution, si vous en trouvez une !)
=======================================================================================

Il n’est fait aucune mention de SMTP_DOMAIN dans le script de test.

root@conversation:/var/discourse# grep SMTP_DOMAIN discourse-doctor
root@conversation:/var/discourse#

Et tcpdump indique que l’exécution de discourse-doctor envoie toujours « localhost » dans l’EHELO. Cela doit également être corrigé.

	0x0030:  cccd b12c 4548 4c4f 206c 6f63 616c 686f  ...,EHLO.localho
	0x0040:  7374 0d0a                                st..
...
	0x0030:  e247 1aa5 3432 3120 342e 372e 3020 5472  .G..421.4.7.0.Tr
	0x0040:  7920 6167 6169 6e20 6c61 7465 722c 2063  y.again.later,.c
	0x0050:  6c6f 7369 6e67 2063 6f6e 6e65 6374 696f  losing.connectio
	0x0060:  6e2e 2028 4548 4c4f 2920 6e6d 3773 6d31  n..(EHLO).nm7sm1
	0x0070:  3032 3832 3139 706a 622e 3620 2d20 6773  028219pjb.6.-.gs
	0x0080:  6d74 700d 0a                             mtp..

Ce n’est pas discourse-doctor mais emails.rake :

Ah, et il semble qu’il utilise localhost. Je suppose qu’il devrait faire référence à #{ENV["DISCOURSE_SMTP_PORT"]}—ou DISCOURSE_SMTP_DOMAIN pour l’instant.

@falco sommes-nous sûrs que cela a toujours été le cas et qu’il ne s’agit pas d’une régression récente ?

Je me souviens de problèmes liés à l’envoi de

ehlo {domaine invalide}

depuis très longtemps, donc je serais très surpris que nous ayons envoyé incorrectement

ehlo localhost
pendant une longue période ?

1 « J'aime »

Désolé, je ne fais que signaler ce que je vois. Je suis presque certain que ‘localhost’ là aussi est incorrect. Mon développement web est surtout ancien ; cela fait plus de dix ans que je n’ai plus travaillé professionnellement avec ce genre de choses. Aller aussi loin m’a pris du temps, Docker, Ruby et tout ça sont assez nouveaux pour moi. En revanche, tcpdump… je connais cet outil. :wink:

Je reste convaincu que l’envoi de ‘localhost’ à un serveur distant, dans n’importe quelle situation, est un comportement erroné.

1 « J'aime »

Pour ce que cela vaut, nous rencontrons exactement le même problème depuis le 13 janvier. Le dernier e-mail envoyé avec succès l’a été le 13 janvier, et nous utilisons également smtp-relay.gmail.com — nous n’avons pas encore trouvé de solution (sans modifier le code source).