Discourse SMTP invia "EHLO localhost" invece del dominio, rompendo Google smtp-relay

Alcuni contesti qui: Emails have stopped sending - end of file reached

Circa una settimana fa (13 gennaio 2021), l’invio di email ha iniziato a fallire tramite il server smtp-relay.gmail.com di Google (che è un uso consentito e previsto per gli utenti Google Apps).

Sidekiq ha segnalato i fallimenti con EOFErrors:

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

E /logs ha riportato anche i task falliti:

Job exception: end of file reached

Il backtrace è disponibile nell’altro post.

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

L’indagine ha rivelato che le installazioni di Discourse aggiornate si connettono ai relay SMTP con ‘EHLO localhost’ e Google ha iniziato a rifiutarle circa una settimana fa.

Da tcpdump su un’istanza di produzione:

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..

E la replica con telnet dà lo stesso risultato:

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.

Tuttavia, un ehlo specifico del dominio funziona correttamente:

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

======

Sulla base dei log, ho identificato il file da modificare per testare la correzione (nell’immagine docker):

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

Cambiando

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

in

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

ha risolto il problema (dopo un riavvio dell’istanza). L’EHLO ora viene inviato con la stringa del dominio e le email vengono inviate correttamente dalla mia istanza.

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

Comportamento desiderato: Durante l’invio di email, l’installazione predefinita di Discourse utilizza il nome di dominio configurato per la connessione iniziale al server SMTP. In alternativa, esiste un’opzione di configurazione per sovrascrivere il dominio inviato. Se questa esiste, non sono riuscito a trovarla cercando.

5 Mi Piace

Credo di aver visto lo stesso errore da parte di altre persone (che potrebbero non aver utilizzato anche Google Domains).

Una soluzione a lungo termine consiste nell’aggiungere una funzionalità magica al tuo app.yml che esegua automaticamente questa riscrittura. Ma speriamo che arrivi presto una soluzione definitiva.

Se esiste un modo per risolvere il problema tramite app.yml, sono certamente interessato: hardcodare il mio dominio nel codice per far funzionare l’email è chiaramente non una soluzione “corretta”, ma dimostra dove risolvere il problema in modo più permanente.

C’è una ragione per cui non utilizza semplicemente il dominio configurato per l’ehlo? Sarebbe “più corretto” rispetto a localhost.

Ottimo lavoro investigativo @Syonyk!

Puoi condividere le impostazioni SMTP del tuo file app.yml?

2 Mi Piace

Non c’è nulla oltre alle impostazioni standard richieste.

  DISCOURSE_SMTP_ADDRESS: smtp-relay.gmail.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: [nome utente email]
  DISCOURSE_SMTP_PASSWORD: [password]

Puoi provare ad aggiungere una nuova riga con

DISCOURSE_SMTP_DOMAIN: conversation.sevarg.net

e riprovare?

3 Mi Piace

Ho aggiunto quella riga e ricompilato l’app (c’è un modo per evitare questo passaggio?).

Ora vedo “domain” nelle impostazioni della mia email, il file smtp.rb è stato ripristinato con localhost come valore predefinito, e le email sembrano essere inviate correttamente: riesco a inviare messaggi di prova e vengono trasmessi senza problemi.

Quindi, per quanto ne so, questo risolve il problema. Si potrebbe aggiungere questa informazione alla documentazione o al flusso di configurazione da qualche parte? Ho cercato a lungo una simile impostazione, ma non sono riuscito a trovare questa opzione: anche conoscendo l’opzione di configurazione, c’è pochissimo che ne parli.

2 Mi Piace

Può essere aggiunto a questo blocco nel file di esempio predefinito app.yml:

Lo ritieni utile?

1 Mi Piace

Finché è documentato da qualche parte, sono contento.

Tuttavia, se non è impostato, il codice potrebbe utilizzare il valore di DISCOURSE_HOSTNAME (che sarebbe corretto nella maggior parte dei casi semplici)? Inviare ‘localhost’ in EHLO è generalmente errato (almeno quando si comunica con un server non in locale).

Penso che aggiungerlo a standalone.yml e web_only.yml sia una buona idea.

Sono d’accordo che dovrebbe probabilmente predefinito su DISCOURSE_HOSTNAME. Sicuramente sembra meglio di localhost. È cambiato qualcosa di recente?

Il punto qui è che funziona per tutte le decine di migliaia di istanze di Discourse che al momento non si affidano a Google per l’invio di email. Cambiare un valore predefinito del genere potrebbe rompere tutto per tutti, mentre si risolve il problema per gli utenti di Google Apps, che sono relativamente pochi.

Aggiungerò questa nota all’esempio, e dovremmo anche creare un argomento howto intitolato “Utilizzo di Google Apps per l’invio di email” che documenti questa procedura. Qualcuno può occuparsene?

4 Mi Piace

OK. Concordo sul fatto che probabilmente ha senso procedere con cautela, ma immagino che qualsiasi server di posta che accetta localhost accetterà anche DISCOURSE_HOSTNAME, anche se non ho dati a supporto. :wink: Includerlo nei template standard è probabilmente più che sufficiente.

1 Mi Piace

Sì, ma inviare ‘localhost’ (a un host remoto) è comunque errato, secondo l’RFC.

L’enfasi è mia.

Gli RFC più vecchi affermano che il server non dovrebbe rifiutare i client in base alla stringa EHLO, cosa che Google sembra fare, ma non vedo questa formulazione nell’RFC 5321.

Mi aspetto che qualsiasi server di posta remoto che tollera localhost tolleri (e preferisca) un FQDN come richiesto dall’RFC. Comprendo il desiderio di non rompere nulla, ma leggendo gli RFC pertinenti, Discourse è semplicemente errato di default, e il fatto che funzioni è dovuto a server SMTP remoti eccessivamente permissivi.

1 Mi Piace

Sarei felice di unire una PR a ./discourse-setup che lo imposti di default allo stesso valore di DISCOURSE_HOSTNAME, a condizione che sia stato dimostrato innocuo con i servizi SMTP più comuni che consigliamo alle persone di utilizzare.

2 Mi Piace

Non posso testare l’intera consegna della posta da un capo all’altro perché non ho account, ma:

Mailgun

% nc smtp.mailgun.com 587
220 Mailgun Influx ready
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 ready at 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

… non risponde a un helo o ehlo di alcun tipo, davvero. o.O Localhost o qualsiasi dominio reale.

Penso che impostarlo durante la configurazione sia la soluzione giusta, perché almeno è presente per permettere alle persone di conoscerlo e modificarlo se necessario.

6 Mi Piace

C’è un’altra questione correlata: discourse-doctor non sembra impostare correttamente il dominio e continuerà a fallire anche quando l’installazione effettiva sarà in grado di inviare email.

Con la configurazione funzionante, discourse-doctor segnala comunque l’errore di fine file.

======================================== ERRORE ========================================
                                    ERRORE INASPETTATO

fine file raggiunta

====================================== SOLUZIONE =======================================
Questo non è un errore comune. Non esiste una soluzione consigliata!

Si prega di segnalare il messaggio di errore esatto sopra a https://meta.discourse.org/
(e una soluzione, se ne trovi una!)
=======================================================================================

Non c’è alcun riferimento a SMTP_DOMAIN nello script di test.

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

Inoltre, tcpdump indica che l’esecuzione di discourse-doctor invia ancora ‘localhost’ nell’EHLO. Anche questo deve essere corretto.

	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..

Non si tratta di discourse-doctor, ma di emails.rake:

Ah, e sembra che utilizzi localhost. Immagino che dovrebbe fare riferimento a #{ENV["DISCOURSE_SMTP_PORT"]}—o, per ora, a DISCOURSE_SMTP_DOMAIN.

@falco siamo sicuri che questo sia sempre stato il caso e non si tratti di una regressione recente?

Ricordo problemi relativi all’invio di

ehlo {invalid domain}

da molto tempo fa, quindi sarei molto sorpreso se avessimo inviato erroneamente

ehlo localhost

per lungo tempo?

1 Mi Piace

Scusa, sto solo riportando ciò che vedo. Sono quasi sicuro che anche ‘localhost’ lì sia sbagliato. Il mio sviluppo web è per lo più antico, è passato più di un decennio da quando ho lavorato professionalmente con queste cose. Arrivare fino a dove sono arrivato ha richiesto del tempo; Docker, Ruby e simili sono tutti piuttosto nuovi per me. tcpdump, d’altro canto… conosco quel tool. :wink:

Tuttavia, penso ancora che inviare ‘localhost’ a un server remoto, in qualsiasi situazione, sia un comportamento errato.

1 Mi Piace

Per quanto ne sappiamo, stiamo riscontrando lo stesso identico problema dal 13 gennaio. L’ultimo email inviata con successo è stata il 13 gennaio e stiamo anche utilizzando smtp-relay.gmail.com — non abbiamo ancora capito come aggirare il problema (senza modificare il codice sorgente)