I messaggi email di Discourse sono filettati in modo errato

Mi scuso in anticipo per alcuni toni qui sotto. Sembra che io sia esasperato, perché lo sono un po’.

Di Michael Brown tramite Discourse Meta il 27 luglio 2022 14:06:

Scusa, mi sto mettendo al passo ora, ecco alcuni pensieri, alcuni dei quali sono già stati affrontati…

La difficoltà qui è che ciò che viene inviato da Discourse è un messaggio diverso da quello in arrivo. Ha metadati diversi (a questo scopo, To/From/Reply-to/Unsubscribe/ecc.) e un corpo diverso (è personalizzato per utente (credo? Questo non accade in modalità mailing list?)).

Cos’è esattamente il messaggio? Trattando il 5322 come Vangelo:

Un messaggio è costituito da campi di intestazione, opzionalmente seguiti da un corpo del messaggio.

Il campo “Message-ID:” fornisce un identificatore di messaggio univoco che si riferisce a una versione particolare di un particolare messaggio.
[enfasi mia]

È quella “versione particolare” che mi fa pensare che sarebbe inappropriato reinviare un messaggio in arrivo con un Message-ID diverso. Tuttavia, se cambi il tuo punto di vista da Discourse come “Software per Forum” a Discourse come “Software per Mailing List”, allora ha un certo senso farlo, quindi capisco da dove vieni.

Beh, sfortunatamente questo si basa su una lettura eccessivamente letterale, forse leggendo un contesto che non c’è.

Ogni messaggio e-mail vede i suoi header modificati man mano che il sistema di posta lo elabora. Se non altro, vengono aggiunti header Received: ad ogni passaggio, e diversi sistemi aggiungono vari header che indicano i risultati del filtro antispam e le firme. Nessuno di questi attiva una modifica del message-id, e infatti farlo renderebbe il message-id totalmente disfunzionale.

Per quanto riguarda il contenuto, come già accennato, quasi tutte le mailing list aggiungono contenuto al testo del corpo, solitamente un piè di pagina con un link alla pagina di amministrazione della lista o un link per annullare l’iscrizione. Anche questo non attiva una modifica del message-id.

Infatti, quasi nulla che inoltra un messaggio cambia il message-id. Perché ciò romperebbe il threading e il rilevamento dei duplicati per i client degli utenti finali.

Vedo che continui a citare ciò che stavo per citare anche io :slight_smile:

Il 5322 dice anche:

Ci sono molte istanze in cui i messaggi vengono “modificati”, ma tali modifiche non costituiscono una nuova istanza di quel messaggio, e quindi il messaggio non riceverebbe un nuovo identificatore di messaggio. Ad esempio, quando i messaggi vengono introdotti nel sistema di trasporto, vengono spesso preceduti da campi di intestazione aggiuntivi come campi di traccia (descritti nella sezione 3.6.7) e campi rispediti (descritti nella sezione 3.6.6). L’aggiunta di tali campi di intestazione non cambia l’identità del messaggio e quindi viene mantenuto il campo “Message-ID:” originale. In tutti i casi, è il significato che il mittente del messaggio desidera trasmettere (cioè, se questo è lo stesso messaggio o un messaggio diverso) che determina se il campo “Message-ID:” cambia o meno, non alcuna differenza sintattica particolare che appare (o non appare) nel messaggio.

Suppongo che si riduca a questo: il mittente del messaggio cambia quando Discourse lo invia?

Penso che tu abbia frainteso le cose qui. Lasciami enfatizzare:

In tutti i casi, è il significato che il mittente del messaggio
desidera trasmettere (cioè, se questo è lo stesso messaggio o un messaggio diverso) che determina se il campo “Message-ID:” cambia

Il mittente è l’autore, non un MTA come Discourse.

Se posto su Discourse via e-mail, voglio che il mio messaggio raggiunga i lettori così com’è, semanticamente parlando. Qualsiasi aggiunta come link di annullamento iscrizione non cambia la semantica di ciò che ho detto nel mio messaggio.

È ancora lo stesso messaggio.

Forse dovremmo usare Resent-Message-ID e simili?

Assolutamente no. Sono per un utente che reinvia un messaggio. Ad esempio, se inoltrassi un messaggio a qualcun altro. Non sono per i relay di posta (come liste e Discourse).

C’è sempre stato, fin dall’822. Ma come dici più tardi, sì, è stato aggiornato.

Ahi. Pensavo fosse solo USENET a quel punto. Mi correggo.

Il 5322 parla anche direttamente del modo in cui Discourse e Github lo usano:

Il campo “In-Reply-To:” può essere utilizzato per identificare il messaggio (o i messaggi) a cui il nuovo messaggio è una risposta, mentre il campo “References:” può essere utilizzato per identificare un “thread” di conversazione.

Forse in modo leggermente improprio, probabilmente a causa della mancanza di un’intestazione “Thread Identifier” adatta. Ma questa interpretazione potrebbe non essere ciò che gli autori RFC intendevano… non affronta i messaggi con “References” ma senza “In-Reply-To”.

Mi dice che i due campi coprono le stesse informazioni:

  • References mostra un thread lineare (di solito) fino all’OP
  • In-Reply-To mostra il genitore e implica lo stesso thread nell’insieme con i messaggi precedenti fino all’OP

La parte complicata è che non stiamo inviando una e-mail, ne stiamo inviando N - una per destinatario - in modo che i loro metadati individuali (Unsubscribe, ecc.) possano essere corretti.

Questo non è complicato. Il significato dei messaggi è lo stesso, le personalizzazioni sono minori e semanticamente irrilevanti. Non giustificano message-id nuovi o distinti.

E sì, ho visto forti indicazioni durante i test che la determinazione dello spam sarebbe legata a un Message-ID. Se fosse stato visto di nuovo in seguito (stesso utente o utente diverso) sarebbe stato molto più probabile che venisse contrassegnato come spam.

Puoi mostrare alcune di queste istanze? Perché i message-id consentono la deduplicazione alla fine dell’utente. E tieni presente che molte misure “antispam” sono spazzatura fuorviante. Il numero di cose che ho rifiutato come potenziale spam per ragioni del tutto spurie… rompere l’e-mail per aggirare un errato filtraggio antispam è una scelta sbagliata.

Ancora oggi non metto mai in CC persone con indirizzi GMail perché il filtro antispam di GMail mi conosce e lascia cadere le cose. Se invio solo alla lista, le ricevono. Se metto in CC il loro indirizzo GMail, questo (a) lo contrassegna come spam e (b) poi contrassegna anche il messaggio della mailing list come spam (stesso message-id!). L’utente finale non vede il mio messaggio. Questa logica è del tutto spuria e irreparabile.

I benefici qui, ad essere onesti, riguardano interamente il threading corretto delle e-mail in alcuni client di posta a scapito della recapito.

Sospirando. A tutti i client di posta. E un motivo principale per cui le persone in Pythonland dicono che non andranno su Discourse è che il threading lato e-mail è rotto. Molte persone non usano forum, perché ogni forum richiede loro di visitarlo. Le e-mail arrivano a loro, possono usare il loro lettore preferito e il loro editor preferito, e il threading permette alle persone di vedere chiaramente il flusso della discussione. Quando funziona.

L’attuale topic/#{topic_id}/#{post_id}.s#{sender_user_id}r#{receiver_user_id} almeno lo rende coerente per un utente nella sua casella di posta. L’assunzione

La mia preoccupazione più grande è la recapito - è già abbastanza difficile far recapitare le e-mail quando non c’è visibilità da parte dei principali provider.

Vorrei vedere delle prove. Le mailing list fanno questo correttamente in tutto il mondo. Discourse lo rompe in modo definitivo e oggettivo. Sto cercando di farlo sistemare.

Lasciatemi ribadire i due problemi fondamentali qui:

  • L’OP In-Reply-To e References citano un fittizio message-id “pre-OP” del “topic”, quindi nessun utente e-mail ha un thread con un messaggio di partenza (l’OP) - tutto compreso l’OP sembra un follow-up
  • Le e-mail ricevute tramite Discourse e le e-mail ricevute direttamente, ad esempio tramite CC, hanno message-id diversi anche se sono semanticamente lo stesso messaggio; questo rompe il threading e la deduplicazione

Ma vedo un forte argomento per far comportare Discourse più come un software di mailing list in modalità mailing list. @martin Credo che non personalizziamo il corpo del messaggio in modalità mailing list? Pensi che abbia senso adottare un approccio più rigoroso riguardo alla conservazione e al riutilizzo dei Message-ID in modalità mailing list?

Ci sono persone in Pythonland che hanno trovato la “modalità mailing list” troppo caotica. Vogliono ricevere e-mail per argomenti mirati ma non per tutto. La gestione del message-id dovrebbe essere la stessa per tutto il lato e-mail.

Sono una persona da “modalità mailing list” su discuss.python.org. Ma l’ho attivata qui (discourse.org) e l’ho _immediatamente disattivata di nuovo. Ho bisogno della modalità mirata qui.

4 Mi Piace

Di Michael Brown tramite Discourse Meta alle 27/07/2022 22:37:

ah! Pensavo stessimo già facendo: topic/#{topic_id}/#{post_id}.s#{sender_user_id}r#{receiver_user_id}

{receiver_user_id} ti inserisce in ID di messaggi distinti per utente finale per lo stesso post di origine. Questo è negativo non appena gli utenti finali comunicano al di fuori di discourse o ricevono copie non tramite discourse.

Sarei propenso a, nell’interesse di bilanciare le preoccupazioni di unicità e recapito delle email rispetto a quelle della modalità mailing list, fare \(2) per la modalità mailing list disabilitata e (3) per la modalità mailing list abilitata.

E come menzionato nel mio recente post, la modalità mailing list copre solo un tipo di ricezione email di Discourse. Tutte le stesse preoccupazioni si applicano sia che il destinatario dell’email sia in modalità mailing list o semplicemente in modalità email-per-alcuni-argomenti/tag.

Allo stesso modo, con l’header References, sarei propenso a farlo assente per il post n. 1 in un argomento

Allo stesso modo In-Reply-To. nessuno dei due dovrebbe essere presente, perché per essere presenti devono fare riferimento a un messaggio fittizio per-OP.

e farlo fare riferimento all’argomento (quindi topic/#{topic_id}) e al post

a cui sta rispondendo, se presente.

Non puoi fare riferimento all’ID del messaggio “argomento” a meno che non ci sia stato un post con quell’ID messaggio che è stato inviato via email. Se vuoi andare in quella direzione, gestisci in modo speciale l’ID del messaggio dell’OP in modo che sia l’ID del messaggio “argomento” invece di ...../1.

3 Mi Piace

Questo dovrebbe essere “prima dell’OP”. Mi dispiace, Cameron Simpson

Come dici tu, questo è esattamente il problema che ci frustra:

Concordo che questo dovrebbe essere cambiato. Il message-id dell’OP dovrebbe essere (in assenza di uno proveniente via email) (semplificato) topic/1 e non fare riferimento a un altro messaggio.

Il message ID non cambierebbe, anche se fosse solo un post di Discourse e mai un’email.

Messaggi ulteriori possono fare riferimento a quello.

Perché deve esistere un’email? Semanticamente, avere solo il post soddisfa i criteri. Il messaggio a cui si risponde esiste, solo che non è nella cartella email di quella persona. Siamo giunti alla conclusione che il messaggio è ciò che è importante, sia esso il corpo del post o il corpo dell’email. Ne consegue che topic/#{topic_id}/1@site è un message ID univoco che fa riferimento a quel post, indipendentemente dal fatto che sia in un messaggio email o meno.

Non è diverso dal ricevere una risposta a un’email che fa riferimento a un’email non presente nella tua casella di posta. È comunque una risposta, quindi References è legittimo e corretto.

Fondamentalmente sono d’accordo con te. Il purista in me vuole che questo sia corretto. Ma la praticità di dover far arrivare le email nelle caselle di posta della gente è ciò che ha portato a questo. Nel bene e nel male, molte persone usano gmail e non addestrano mai i suoi filtri, lo usano correttamente e si “disiscrivono” segnalandolo come spam[1].

Sono d’accordo, penso che siamo stati un po’ troppo letterali nel leggere

Un identificatore di messaggio si riferisce esattamente a una istanza di un particolare messaggio

Dopo averci riflettuto per un po’, penso che dovremmo tornare a quello che avevamo prima (rimuovere la randomizzazione) e bloccare un singolo message-id per post e dovrebbe essere:

  • message_id_from_incoming_email || topic/#{topic_id}/#{post_num}@site (il post_num dell’OP è 1)

E ogni volta che inviamo un’email, penso sia corretto aggiungere References ai genitori fino all’OP e impostare In-Reply-To all’appropriato post message-ID stabile (o all’OP se si risponde all’argomento) poiché il Messaggio è il post. Ma quei campi per l’OP dovrebbero essere vuoti, sì.


  1. non che gmail ce lo segnali, nonostante abbiamo implementato il feedback-loop. ↩︎

5 Mi Piace

Grazie per le vostre risposte @supermathie e @cameron-simpson, credo che abbiamo raggiunto un consenso. Estrapolando i TODO in un unico post, e spero di poter iniziare a lavorarci abbastanza presto:

  1. Modificare il formato generato di Message-ID in modo che sia sempre \u003cdiscourse/post/:post_id@:hostname\u003e, questo è sufficientemente univoco, è fondamentalmente un ritorno a quello che facevamo prima. Fare riferimento all’OP utilizzerà ora il primo ID del post invece del semplice ID del topic.
  2. Se un post ha un record IncomingEmail associato, utilizziamo sempre quel Message-ID quando inviamo un’email, altrimenti ne generiamo uno utilizzando il formato sopra.
  3. Non utilizzare un References quando si inviano email per l’OP del topic, non c’è nulla a cui fare Reference poiché è la prima email nella conversazione.
  4. Assicurarsi che vengano generati gli header In-Reply-To e References corretti in base ai record PostReply.

Questo ha il potenziale di lasciare le cose in uno stato un po’ confuso per quanto riguarda il threading per le email già inviate, ma farò del mio meglio per consentire il formato da cui ci stiamo allontanando per un periodo di transizione. Grazie per la vostra pazienza!

3 Mi Piace

Solo per chiarire… questo non sarebbe il hostname del server da cui è originato, ma l’url del sito? Se è hostname, allora perdiamo tutta la stabilità quando 3 host diversi servono lo stesso sito.

1 Mi Piace

Mi dispiace, sì, intendo il dominio del sito, ad esempio meta.discourse.org, che proviene da Email::Sender.host_for(Discourse.base_url), quello che usiamo già.

2 Mi Piace

Buona idea, non avevo pensato agli spostamenti. :post_id è l’ID del post (post.id) o il numero (all’interno dell’argomento)?

Se è l’ID del post, possiamo semplificare e usare semplicemente \u003cpost/:post_id@:hostname\u003e dato che non cambierà mai, quindi non è necessario memorizzare il Message-ID a meno che non venga sovrascritto rispetto al default.

Se no… tanto vale usare l’ID del post qui? non c’è motivo per cui questa parte debba essere lunga, deve solo essere unica.

2 Mi Piace

È l’ID effettivo, non il numero del post.

Questo è un buon punto, <post/:post_id@:hostname> probabilmente funzionerà benissimo ed evita il requisito della colonna aggiuntiva. Forse per renderlo più specifico per Discourse potremmo aggiungere discourse all’inizio, ad esempio <discourse/post/543563@meta.discourse.org> (tenendo presente che molti siti non avranno alcuna menzione di Discourse nell’hostname). A questo punto sono pignolerie.

Sto solo pensando ad alta voce, dovrebbe andare bene, coprirò queste cose quando testerò le modifiche comunque :+1:

2 Mi Piace

L’argomento a favore dell’inclusione di topic_id è che è possibile interrompere deliberatamente il threading se le persone separano un post da un argomento in un altro argomento.

Sono combattuto. Può andare in entrambi i modi. Ma questa sarebbe l’idea.

1 Mi Piace

L’argomento a favore dell’utilizzo del solo ID del post è che è più statico, il che è ciò che vogliamo, poiché se sposti un post in un altro argomento, l’ID del post sarà lo stesso nel Message-ID, ma l’argomento non sarà lo stesso.

Penso che se finiremo per spostare il post e inviare email dal nuovo argomento, il nuovo thread verrà comunque creato correttamente nel client di posta, poiché le catene degli header References e In-Reply-To saranno diverse. In ogni caso, mi assicurerò di testare questo scenario e vedere se fa ciò che ci aspettiamo. Nulla verrà unito al core finché i vari scenari non funzioneranno come previsto.

1 Mi Piace

Sulla base di queste ulteriori discussioni @cameron-simpson ho aggiornato i TODO a questo, pubblicandoli qui in modo che tu riceva l’aggiornamento poiché le modifiche di Discourse non arriveranno via email:

  1. Modifica il formato del Message-ID generato in modo che sia sempre \u003cdiscourse/post/:post_id@:hostname\u003e, questo è sufficientemente unico, è essenzialmente un ritorno a ciò che facevamo prima. Fare riferimento all’OP utilizzerà ora l’ID del primo post invece del solo ID dell’argomento.
  2. Se un post ha un record IncomingEmail associato, utilizziamo sempre quel Message-ID quando inviamo email, altrimenti ne generiamo uno utilizzando il formato sopra.
  3. Aggiungi una nuova colonna outbound_message_id ai record Post che sarà riempita da a) il Message-ID dell’email in arrivo se sta creando il post o b) l’Message-ID in uscita che generiamo nel caso di post creati dall’interfaccia web di Discourse
  4. Non utilizzare gli header References o In-Reply-To quando si inviano email per l’OP dell’argomento, non c’è nulla a cui fare Reference o a cui rispondere ancora perché è la prima email nella conversazione.
  5. Assicurati che gli header In-Reply-To e References corretti siano generati in base ai record PostReply.
1 Mi Piace

Questo copre anche le citazioni (ad esempio, un post che cita 10 altri post diversi, quindi li referenzia?)

1 Mi Piace

Di Sam Saffron tramite Discourse Meta il 29Lug2022 02:31:

Questo copre anche le citazioni (ad esempio, un post che cita altri 10 post, quindi li referenzia?)

In-Reply-To può citare un solo antecedente, quindi scegline uno. References può far riferimento a più di uno, ma la RFC lo sconsiglia esplicitamente perché non tutte le app client potrebbero aspettarsi altro che una catena lineare da questo post all’OP.

Andrei bene con entrambi per References, ma propenderei per quello conservativo. Il calcolo semplice è:

  • In-Reply-To: usa l’ID del messaggio del primo messaggio citato (o qualsiasi altra citazione singola tu scelga in base a una qualche politica)
  • References: i References dello stesso singolo antecedente scelto sopra più l’ID del messaggio di quello stesso post

Questi sarebbero stabili, prevedibili e corretti.

Saluti,
Cameron Simpson cs@cskk.id.au

2 Mi Piace

References è scoraggiato dall’essere utilizzato in questo modo:

Nota: Alcune implementazioni analizzano il campo “References:” per visualizzare il “filo della discussione”. Queste implementazioni presuppongono che ogni nuovo messaggio sia una risposta a un singolo genitore e quindi che possano risalire all’indietro attraverso il campo “References:” per trovare il genitore di ogni messaggio elencato lì. Pertanto, si sconsiglia di tentare di formare un campo “References:” per una risposta che ha più genitori; come farlo non è definito in questo documento.

2 Mi Piace

Di Martin Brennan tramite Discourse Meta alle 29Jul2022 01:57:

Basandomi su queste ulteriori discussioni @cameron-simpson ho aggiornato i TODO
in questo modo, pubblicandoli qui in modo che tu riceva l’aggiornamento poiché le modifiche a Discourse
non arriveranno via email:

  1. Cambia il formato del Message-ID generato in modo che sia sempre \u003cdiscourse/post/:post_id@:hostname\u003e, è sufficientemente univoco, è praticamente un ritorno a ciò che facevamo prima. Fare riferimento all’OP utilizzerà ora l’ID del primo post invece del solo ID dell’argomento.
  2. Se un post ha un record IncomingEmail associato, utilizziamo sempre quel Message-ID quando inviamo email, altrimenti ne generiamo uno utilizzando il formato sopra.
  3. Non utilizzare un References quando si inviano email per l’OP dell’argomento, non c’è nulla a cui fare Reference poiché è la prima email nella conversazione.

Ometterei anche l’In-Reply-To nelle email dell’OP.

  1. Assicurati che vengano generati correttamente gli header In-Reply-To e References
    in base ai record PostReply.

Sì.

Personalmente, farei un passo in più avendo una colonna per il message-id lato email. In questo modo, una volta che hai assegnato un message-id per il post (dall’email sorgente se proviene da email, o generato se proviene dall’interfaccia web), rimane stabile indipendentemente da qualsiasi altra cosa possa accadere nel codice ora o in futuro. Cioè, anche se non c’è IncomingEmail, la generazione del message-id avviene solo una volta, piuttosto che essere ricalcolata (il che potrebbe quindi cambiare).

Cioè, rendilo stabile una volta creato memorizzandolo.

Hai una relazione IncomingEmail a quanto pare. Forse hai (o potresti usare) una relazione OutgoingEmail per lo stato aggiuntivo per i messaggi di posta in uscita, creata la prima volta che un post viene inoltrato via email.

So che il flusso è fondamentalmente che ciò accade quando viene creato un post, ma posso immaginare alcune funzionalità utente successive come:

  • per favore inoltrarmi email per questo intero argomento, ora che sono interessato
  • se avviene una modifica a un post, considera l’invio del messaggio aggiornato con lo stesso message-id

Il motivo per cui il secondo esempio mi viene in mente è che abbiamo più cose da segnalare :slight_smile: Una è che Discourse sembra fare uno sforzo per eliminare la parte quotata delle risposte postate in alto per mantenere il post conciso, o qualcosa del genere. Ho scritto un lungo post in Python qualche settimana fa che è stato gravemente troncato. Sono entrato e l’ho modificato sul forum con il testo originale dalla mia copia personale. Ma un destinatario ha detto di aver ricevuto l’intero messaggio e mi chiedevo se Discourse inviasse aggiornamenti di modifica come messaggi sostitutivi con lo stesso ID. Il che sarebbe piuttosto carino a seconda della gestione da parte del client dell’utente finale.

1 Mi Piace

Di Martin Brennan tramite Discourse Meta alle 29Lug2022 00:36:

  1. Aggiungere un nuovo outbound_message_id alla tabella Post, in modo da poter essere certi che il thread sopravviva anche se un post si sposta in altri argomenti o cose del genere, memorizzare il Message-ID qui per entrambi i casi di cui sopra.

Sì, penso che sia importante, comunque implementato (relazione o colonna di qualsiasi cosa). Penso di averlo detto nei tuoi TODO rivisti.

  1. Non usare un References quando si inviano email per l’OP dell’argomento, non c’è nulla da Reference ancora perché è la prima email nel thread.
  2. Assicurarsi che le intestazioni In-Reply-To e References corrette siano generate in base ai record PostReply e alla nuova colonna outbound_message_id sulla tabella Post.

Questo ha il potenziale di lasciare le cose in uno stato un po’ confuso a livello di thread per le email già inviate, ma farò del mio meglio per consentire il formato da cui ci stiamo allontanando per un periodo di transizione. Grazie per la pazienza!

Non c’è niente che possiamo fare per le email esistenti. Assicurati solo che le cose siano ben threadate in futuro!

Grazie!
Cameron Simpson cs@cskk.id.au

1 Mi Piace

Abbiamo EmailLog ma quei record vengono eliminati ogni 90 giorni, e non penso che sarebbe una buona soluzione. Farò solo questo:

1 Mi Piace

Si trattava di evitare di memorizzarlo del tutto… ma ripensandoci l’ID del post non cambierà mai, mentre l’hostname potrebbe. Quindi dovremmo memorizzarlo subito dopo il salvataggio in tutti i casi.

Non farebbe male avere messageid come proprietà di ogni Post, immutabile per sempre…

Non sarebbe una versione diversa del messaggio? Dalla specifica:

Il campo “Message-ID:” fornisce un identificatore univoco del messaggio che si riferisce a una particolare versione di un particolare messaggio. … Un identificatore di messaggio si riferisce esattamente a una versione di un particolare messaggio; le revisioni successive del messaggio ricevono ciascuna nuovi identificatori di messaggio.

Quindi probabilmente il nostro message-id generato dovrebbe essere: \u003cdiscourse/post/:post_id/rev/:revision_num\u003e (possibilmente omettendo /rev/:revision_num per la prima revisione). Ciò consentirebbe ai destinatari delle e-mail di ricevere gli aggiornamenti delle modifiche in primo luogo, considerando che

1 Mi Piace

Sì, lo farò. Per quanto riguarda queste altre discussioni su modifiche e revisioni, penso che sia un’altra enorme questione che non dovremmo affrontare adesso… risolviamo prima i nostri peccati di threading :slight_smile:

1 Mi Piace