Sul sito discuss python org stiamo discutendo dell’aspetto email di Discourse. La lamentela più grande è la mancanza di threading. Ho fatto qualche ricerca negli header e sembra che:
l’header Message-ID sia almeno univoco
gli header Reply-To e Referencesnon si riferiscano ai Message-ID di altri messaggi, tanto meno all’ID del messaggio a cui si sta rispondendo
invece si riferiscano a un ID messaggio fittizio basato sul numero dell’argomento
Ciò significa che gli utenti che utilizzano l’email vedono (a) discussioni completamente piatte e non thread e (b) il messaggio radice sembra mancante, perché gli header In-Reply-To e References si riferiscono a un ID messaggio che in realtà non appare mai in nessun messaggio.
Questo è grave e viola la RFC 5322. E rende l’esperienza via email molto peggiore di quanto potrebbe facilmente essere.
Ad esempio, c’è un thread lì la cui prima messaggio ha questi header:
Ancora, un Message-ID ok, ma In-Reply-To e References completamente insensati.
Questo dovrebbe essere facile da correggere. Il primo messaggio non dovrebbe avere né header In-Reply-To né References. Il secondo messaggio dovrebbe avere l’Message-ID del primo messaggio negli header In-Reply-To e References.
Si prega di consultare la sezione 3.6.4 della RFC5322 per i dettagli:
Così come stanno le cose, gli utenti di posta elettronica vedono discussioni piatte e non strutturate. Con queste correzioni, possono avere una visualizzazione thread sensata e facile da seguire.
Sto solo dando un’occhiata alla differenza tra HEAD e quella correzione.
Mi sembra che current imposti ancora sempre References, anche se non c’è un antecedente - topic_canonical_reference_id viene usato come fallback. Penso ancora che sia sbagliato, perché non c’è nessun messaggio email con quell’id.
In-Reply-To è un po’ più corretto, in quanto viene impostato solo se post.post_number!=1, ma fa ancora fallback a topic_canonical_reference_id:
il fallback dovrebbe essere il Message-ID del post #1 se non ci sono referenced_post_message_ids, e nontopic_canonical_reference_id
qualcosa nel codice receipt-of-reply-emails deve far cadere l’header In-Reply-To dei messaggi di risposta, perché avrebbero dovuto popolare correttamente l’array referenced_post_message_ids (“lista”? Sono nuovo a Ruby)
Cameron, grazie per aver aperto questo argomento di discussione e per aver fornito molti dettagli nei tuoi post. Sono responsabile di questo “vaso di Pandora”, da questi due commit:
Siamo consapevoli di alcuni problemi relativi al threading da un po’ di tempo nei client di posta elettronica come Thunderbird, ma non rappresentava un gran numero di consumatori di threading via email da Discourse, quindi è stato rimandato. Ora che questo viene alla luce, dobbiamo dedicare del tempo a riesaminare il problema e a lavorare su una soluzione.
È interessante notare che abbiamo aggiunto questa intestazione References alla prima email inviata e a tutte quelle successive al momento, poiché fa funzionare correttamente il threading in Gmail, ma concordo sul fatto che non sia l’ideale e stia probabilmente causando i problemi di threading, insieme al mancato utilizzo del Message-ID originale nelle intestazioni In-Reply-To e References delle email successive.
Ti prego di avere pazienza mentre esamino vecchie discussioni e il codice e lavoro su questo. Nel frattempo, sei a conoscenza di altri client di posta elettronica che vengono utilizzati e stanno riscontrando problemi? Ad esempio, so che questo è un problema in Thunderbird, ma in altri? Grazie.
Ci dispiace, ma il tuo messaggio email a
["incoming+8349bd9eb1f2b582df4f32dbe85c3363@meta.discoursemail.com"]
(intitolato Re: [Discourse Meta] [bug] I messaggi email di Discourse sono
erroneamente in thread) non ha funzionato.
Motivo:
Spiacenti, i nuovi utenti possono inserire solo 2 link in un post.
Se riesci a correggere il problema, riprova.
Lo inserirò nel forum dove potrò recuperarlo e revisionarlo…
Cameron, grazie per aver aperto questo argomento di discussione e per aver fornito
molti dettagli nei tuoi post. Sono responsabile di questo vaso di Pandora,
da questi due commit:
3b13f1146b2a406238c50d6b45bc9aa721094f46
Questo sembra a posto. Salva questo id con il record del database in modo che le risposte in arrivo possano essere collegate al messaggio del forum antecedente?
Inoltre, vuoi che verifichi che il suffisso sia sintatticamente legale per RFC5322, in termini di caratteri consentiti?
82cb67e67b83c444f068fd6b3006d8396803454f
Questo secondo commit sembra affrontare un altro problema che abbiamo riscontrato: se un post proviene da un’e-mail, il message-id in uscita inviato agli utenti di posta elettronica non è il message-id del messaggio sorgente dell’autore. Ciò si traduce in due messaggi diversi dal punto di vista di un client di posta elettronica e probabilmente interrompe le risposte fatte all’originale anziché alla copia inviata dal forum. Ad esempio:
A: il forum
CC: uno dei partecipanti
Il partecipante riceverà (beh, forse) una copia dal forum e una copia diretta dall’autore, e questi saranno messaggi distinti dalla loro parte perché avranno message-id diversi.
Stavo per creare un secondo bug report su questo problema dopo aver risolto il problema degli header in-reply-to e references, che è molto più importante.
Siamo consapevoli di alcuni problemi relativi al threading da un po’ di tempo nei client di posta elettronica come Thunderbird, ma non ha rappresentato un gran numero di consumatori di threading via email da Discourse, quindi è stato rimandato, ma ora che questo sta venendo alla luce dobbiamo dedicare del tempo a riesaminare il problema e lavorare su una soluzione.
Io e diversi altri usiamo mutt. Sono felice di fare tutto il necessario per aiutare nel debug e nella revisione del codice. Sono stato anche un sysadmin di posta per un sacco di tempo in vite precedenti.
[quote=“Cameron Simpson, post:1, topic:233499,
username:cameron-simpson”]
È il primo messaggio. Non dovrebbe avere un header References, perché non c’è nessun messaggio da nessuna parte con quell’id.
[/quote]
Interessante, abbiamo aggiunto questo header References alla prima email inviata e a tutte le successive al momento poiché rende il threading funzionante correttamente in Gmail,
Penso che un header References corretto (assente nel primo post, come in-reply-to nelle risposte) dovrebbe funzionare anche. Ma GMail ha un rapporto piuttosto lasco con gli standard di posta elettronica a volte. Ho un accordo con gmail; posso fare anche del debug lì. E in linea di principio possiamo usare questa stessa discussione come banco di prova, forse.
ma concordo sul fatto che non sia l’ideale e che probabilmente stia causando i problemi di threading
insieme al mancato utilizzo del Message-ID originale nei successivi header In-Reply-To e References dell’email.
Per favore, abbiate pazienza mentre esamino vecchie discussioni e il codice e lavoro su questo.
Nessun problema.
Nel frattempo, sei a conoscenza di altri client di posta elettronica che vengono
utilizzati e stanno riscontrando problemi? Ad esempio, so che questo è un
problema in Thunderbird, ma in altri? Grazie.
Sicuramente mutt. Almeno con mutt è molto facile vedere gli header e anche vedere la catena dell’albero delle risposte, che è spesso oscurata in altri client.
Il threading della posta è interamente definito dagli header Message-ID e In-Reply-To. L’header References è iniziato con USENET per i follow-up, e supportava (lì) più message-id; l’In-Reply-To supporta solo uno. Sembra che References sia ora presente anche in RFC5322, e ne verificherò la semantica.
Va bene, è una cosa piuttosto importante, ti prego di avere pazienza. Innanzitutto, grazie per un’altra risposta dettagliata e per l’offerta di debug/revisione, è molto utile In realtà ci stavo lavorando stamattina e, sorprendentemente, l’organizzazione in thread in una vista unificata funziona in Thunderbird per la maggior parte dei casi, e penso che l’header References che punta costantemente all’OP aiuti in questo (ad esempio, l’argomento Reference in questa catena che è sempre presente è \u003ctopic/53@discoursehosted.martin-brennan.com\u003e).
Il caso in cui l’organizzazione in thread non funziona come previsto è:
Viene creato un post all’interno di Discourse e viene inviata un’email a coloro che seguono l’argomento poi
Qualcun altro risponde a quel post e viene inviata un’email a coloro che seguono l’argomento
Nel caso della seconda email, ottiene un header In-Reply-To e References errato poiché ne genera uno su questa riga discourse/lib/email/sender.rb at 98bacbd2c6b9fe57167cd32af5eb4839b4a5d1f6 · discourse/discourse · GitHub piuttosto che utilizzarne uno esistente. Dovrebbe utilizzare il Message-ID per l’email inviata per prima. Nello screenshot, è qui che i messaggi che seguono questo schema dovrebbero essere posizionati:
La risposta è: dipende. Se un post viene creato in Discourse da un’email in arrivo, come questo tuo, utilizziamo il Message-ID originale in arrivo di quel post quando qualcuno risponde ad esso per gli header In-Reply-To e References come da:
Altrimenti stiamo solo utilizzando il riferimento all’OP dell’argomento e generando un nuovo riferimento, il che ovviamente è ciò che sta causando tutti i problemi. In tutti i casi generiamo un nuovo Message-ID ogni volta che viene inviata un’email in uscita, il che sembra corretto e in linea con altri client di posta.
Penso di aver capito cosa intendi, va così:
cameron invia un’email a Discourse da mutt che ottiene Message-ID: 74398756983476983@mail.com
Discourse crea un post e memorizza il Message-ID contro il post con un record IncomingEmail
johndoe sta seguendo l’argomento, quindi gli viene inviata un’email da Discourse con un Message-ID: topic/222/44@discourse.com e nessun riferimento all’Message-ID originale 74398756983476983@mail.com
Corretto, dovremmo semplicemente “passare” quel Message-ID a coloro che seguono l’argomento invece di generarne uno nostro dato che è già univoco? Cosa succede poi nel client di posta di johndoe se cameron lo ha anche messo in CC su quel messaggio in uscita originale? Questo sembra un problema separato, quindi sarebbe bene aprire un altro argomento di bug per esso.
Configurerò un client mutt localmente per vedere cosa stai riscontrando anche tu, non ho mai testato questa funzionalità in un client basato su testo (solo Gmail e Thunderbird) quindi sono ansioso di vedere come appare comunque.
La mia idea per affrontare questi problemi stamattina è stata quella di eliminare i suffissi generati casualmente quando inviamo gli header Message-ID nelle email e invece passare a uno schema in cui utilizziamo l’user_id sia dell’utente che invia che di quello che riceve. Il vantaggio di questo è che non è necessario memorizzare il Message-ID da nessuna parte (a parte quando un’email in arrivo crea un post) e quindi gli header References e In-Reply-To saranno sempre coerenti. Lascia che ti dia un esempio. Supponiamo di avere questi utenti:
martin - user_id 25
cameron - user_id 44
sam - user_id 78
bob - user_id 999
E poi abbiamo questo argomento, topic_id 233499, con post a partire da post_id 100 come OP. Il formato diventerebbe topic/#{topic_id}/#{post_id}.s#{sender_user_id}r#{receiver_user_id}. L’ordine delle operazioni sarebbe il seguente:
bob crea il post 103 nell’argomento, non in risposta a nessuno (notare che i References qui includono il Message-ID inviato a entrambi gli utenti per l’email dell’OP)
bob - risposta nell’argomento non a un post specifico
INVIATO → a: discourse, RE: post di bob
casella di posta di sam
martin - OP dell’argomento
cameron - secondo post
INVIATO → a: discourse, RE: secondo post
bob - risposta nell’argomento non a un post specifico
Penso che sia corretto, puoi dare un’occhiata a ciò che ho scritto in questi header e verificare che sia quello che ti aspetteresti da questo scenario? L’unica cosa di cui sono un po’ insicuro è se ho coperto tutti i References, e ovviamente testerei questo su un set di email live in un branch di sviluppo prima di implementarlo. Non ho ancora testato nulla in mutt.
Come nota a margine, ho anche esaminato cosa fa GitHub con le sue email di notifica e ho notato che fanno una cosa simile dove hanno un Reference onnipresente (discourse/discourse/pull/252@github.com) che viene utilizzato in tutte le email relative a quell’“argomento” che in questo caso è una pull request di GitHub:
By Martin Brennan via Discourse Meta at 22Jul2022 06:34:
Okay this is kind of huge, please bear with me. First, thanks for
another detailed reply and the offer of debugging / review, it is
really helpful I’ve actually been looking into this this morning
and, surprisingly, the threading in a unified view works in Thunderbird
for most cases, and I think the References header consistently
pointing to the OP helps with that (for example the topic Reference
in this chain which is always present is <topic/53@discoursehosted.martin-brennan.com>.
I’ve just reread RFC5322 section 3.6.4 closely. It has moved on from
earlier versions (822 and 2822), and has merged the email In-Reply-To
headers, USENET References headers and modern
reply-citing-more-that-one previous messages.
The short summary:
The Message-ID is a single persisent identifier for a message
The In-Reply-To contains all the message-ids of which this message
is a direct reply, so if I reply to a pair of messages it will have
those 2 message-ids
The References is a reply chain of antecedant message-ids from the
OP to the preceeding message. So indeed it should always start with
the OP message-id.
So for a discussions like this, pretending that labels are message-ids:
It is also leagel to include “reply1 reply2” in the references (the
other chain to reply5) but the RFC explicitly recommends against that
becaause some clients expect the references to be a single linear chain
of replies, not some flattened digraph.
So my recommendation for constructing the references is to use the
references of the “primary” antecedant message with the primary
antecedant message’s message-id appended. That way you always get a
linear chain in the correct order.
Interestingly there seems to be some threading there.
But notice: the top post has a little “is a reply” arrow. Even though it
is post 1. I expect that is because of the “topic” references entry,
which make TB think there was a earlier message (which of course there
was not).
In mutt-land we see almost no threading at all:
23Jul2022 06:24 Olha via Discus - ┌>[Py] [Users] I need an advise discuss-users 5.7K
22Jul2022 17:12 Paul Jurczak vi - ├>[Py] [Users] I need an advise discuss-users 5.5K
22Jul2022 13:21 Rob via Discuss - ├>[Py] [Users] I need an advise discuss-users 6.8K
22Jul2022 12:53 vasi-h via Disc - ├>[Py] [Users] I need an advise discuss-users 5.5K
22Jul2022 11:38 Cameron Simpson - ├>[Py] [Users] I need an advise discuss-users 14K
22Jul2022 10:27 Rob via Discuss - ├>[Py] [Users] I need an advise discuss-users 6.6K
22Jul2022 06:14 vasi-h via Disc r ┴>[Py] [Users] I need an advise discuss-users 6.5K
which is because every message’s In-Reply-To points directly at the
fictitious “topic” message-id. Mutt probably ignores the References
because it is a mail reader, and References originates in USENET news.
Maybe Thunderbird is using the references or augumenting the in-reply-to
with references information.
You only need to consult one of In=-Reply-To or References to do
threading; the former comes from email and the latter from USENET.
You’re supporting both (which is great!) so we need to make them
consistent.
(Aside: there’s also discussion about USENET mirroring, because several
python people consume the lists via a USENET interface. Again, a
separate topic.)
[…]
[quote=“Cameron Simpson, post:8, topic:233499,
username:cameron-simpson”]
This looks fine. Does it save this id with the db record so that inbound
replies can be tied to the antecedant forum message?
[/quote]
The answer is – it depends. If a post is created in Discourse from an inbound email, such as this one of yours, we use that post’s original inbound Message-ID when someone replies to it for the In-Reply-To and References headers as per:
Otherwise we are just using the topic OP reference and just generating a new reference, which obviously is what is causing all the issues. In all cases we generate a new Message-ID every time an outbound email is sent, which seems correct and on par with other mail clients.
Alas, not quite. If you’re the origin of the message (i.e. authored in
Discourse), generating the message-id is fine. If there’s no message-id
(illegal) generating one is standard practice (usually by MTAs). But if
you’re passing a message on (authored in email), the existing message-id
should be preserved.
To my mind you need to be doing 3 things:
having a stable message-id and not replacing the message-id from an
inbound message
generating correct In-Reply-To, which is easily computed from the
immediate antecedant message(s) i.e. antecedant(s)-Message-ID
generating correct References, which is easily computed as
antecedant-References + antecedant-Message-ID
For point 1, looking at the code you cite, you probably want the email
message id to be (Pythonish syntax, sorry):
def message_id(post):
return post.incoming_email.message_id or discourse_message_id(post)
i.e. to be the post’s email message-id if it originated from email,
otherwise the Discourse message-id using something like the algorithm
you outline later in this message: anything (a) stable and (b)
syntacticly valid.
Then computing the In-Reply-To and References fields is simple
mechanical stuff as in points 2 and 3.
I think I see what you mean, does it go like this:
cameron sends email to Discourse from mutt which gets Message-ID: 74398756983476983@mail.com
Discourse creates a post and stores the Message-ID with against the post with an IncomingEmail record
Correct.
johndoe is watching the topic, so they get sent an email from Discourse with a Message-ID: topic/222/44@discourse.com and no reference to the original Message-ID: 74398756983476983@mail.com
No. You really want to pass through IncomingEmail.message_id as the Message-ID in the email to johndoe. It’s the same message.
Does that sound correct, that we should just “pass on” that Message-ID to those watching the topic instead of generating our own since it’s already unique? What then happens in johndoe’s mail client if
cameron also CC’d him on that original outbound message? This does sound like a separate issue so it would be good to open another bug topic for it.
By passing it on, the original message (cameron->cc:johndoe) and the
Discourse forwarded message (cameron->Discourse->johndoe) have the same
message-id and the same message contents. The receiving mail system
stores both. The mail reader sees both, and either presents both or
keeps just one (this is a policy decision of the mail reader - keeping
just one is common). Because they’re the same message, in general it
does not matter which is kept.
If we ignored discourse and considered a message which was
a copy of the message via the list and also via direct email. They’re
the same message, with the same message-id.
I will set up a mutt client locally to see what you are also seeing, I have never tested this functionality in a text-based client (only Gmail and Thunderbird) so I am keen to see how it looks anyway.
Happy to help with settings. For threaded view you need to set the
sorting to threadeed. Mutt is very configurable.
My line of thinking to address these issues this morning was to dispose
with the randomly generated suffixes generated when we send Message-ID headers in emails and instead change to a scheme where we
use the user_id of both the sending and receiving user. The benefit
of this is that there is no need to store the Message-ID anywhere
(apart from when an inbound email creates a post) and so References
and In-Reply-To headers will always be consistent.
Yes, that is much better. Noting that the inbound email message-id
should override the Discourse derived message-id for the outbound email.
(Most mail systems use random strings because there’s no surrounding
context such as the discourse topic message structure - messages are
considered alone; but the only real requirement is persistent
uniqueness.)
Let me give an example. Say we have these users:
martin - user_id 25
cameron - user_id 44
sam - user_id 78
bob - user_id 999
And then we have this topic, topic_id 233499, with posts starting from post_id 100 as the OP. The format would become topic/#{topic_id}/#{post_id}.s#{sender_user_id}r#{receiver_user_id}.
There should not be a References header in the OP. It isn’t
needed for threading and effectively pretends there’s some “post 0”
which doesn’t exist. It meeans every OP (a) looks like a reply, which it
is not and (b) looks like the thing to which it is a reply is missing
from the reader’s mailbox.
This makes different message-ids for each outbound copy of the OP.
That’s bad. They need to be the same. Supposing sam CCs cameron
directly in a reply. The In-Reply-To will cite a mesage-id cameron
has never received.
You can just drop the sender_user_id and receiver_user_id from the
message-id field and get a single unique id which every receiver sees.
The uniqueness constraint is the post itself, not the individual
email-level “message” object.
Re the References, the OP should not have one. TB and everything else
will be fine. If they’re threading using References instead of In-Reply-To, the References in the reply messages are enough.
Here’s the start of a mailing list discussion thread in Mutt:
16Jul2022 01:09 Rob Boehne - │├>[Python-Dev] Re: [SPAM] Re: Swit python-dev 9.2K
16Jul2022 01:33 Peter Wang - │├> python-dev 3.0K
16Jul2022 00:24 Skip Montanaro - ├>[Python-Dev] Re: Switching to Dis python-dev 4.2K
16Jul2022 04:49 Erlend Egeberg - ├>[Python-Dev] Re: Switching to Dis python-dev 10K
16Jul2022 04:20 Mariatta - ├>[Python-Dev] Re: Switching to Dis python-dev 10K
15Jul2022 21:18 Petr Viktorin - [Python-Dev] Switching to Discourse python-dev 4.2K
Ignore that I sort my email newest-on-top. See that there’s no arrow on
the initial post (at the bottom). That messgae has no References and
no In-Reply-To. All the others have In-Reply-To (and possibly References, but this is an email mailing list so not necessarily; as I
mentioned before they’re complimentary.)
If I repeat my Discourse example from earlier:
23Jul2022 06:24 Olha via Discus - ┌>[Py] [Users] I need an advise discuss-users 5.7K
22Jul2022 17:12 Paul Jurczak vi - ├>[Py] [Users] I need an advise discuss-users 5.5K
22Jul2022 13:21 Rob via Discuss - ├>[Py] [Users] I need an advise discuss-users 6.8K
22Jul2022 12:53 vasi-h via Disc - ├>[Py] [Users] I need an advise discuss-users 5.5K
22Jul2022 11:38 Cameron Simpson - ├>[Py] [Users] I need an advise discuss-users 14K
22Jul2022 10:27 Rob via Discuss - ├>[Py] [Users] I need an advise discuss-users 6.6K
22Jul2022 06:14 vasi-h via Disc r ┴>[Py] [Users] I need an advise discuss-users 6.5K
See they all have a leading arrow? That is because the mail client
believes they are all replies to a common (and missing) root message,
which is because of the “topic” message-id in the References header.
Whereas post 1 is actually the bottom message displayed above.
Summary:
your plan is good, provided you drop the sender and receiver from the
message-id - they’re unnecessary and in fact the receiver will cause
trouble (the sender is just redundant).
drop the “topic” pseudo-message-id from the References - it misleads
email clients (including TB, even if it isn’t visually evident)
cameron replies via email
discourse is sent an email with these headers from mutt:
Yes, again with the caveat that there should not be a “topic” reference.
As expected, there is a reference to the OP message-id. Though it should
be the same message-id that sam sees for the OP.
discourse (as cameron, from the above email) creates post 101
sam is sent an email from discourse with these headers:
And here it goes wrong. The Message-ID should be 43585349859734@test.com from the .incoming_post.message_id field.
(Well, in my mind this is post.message_id(), which returns post.incoming_post.message_id for an email generated post and your
Discourse generated one otherwise).
Consider: I compose and send my reply with message-id 43585349859734@test.com. For continuity reasons, I keep a copy of that
in my local folder, where it shows as a reply to the OP. Ideally
Discourse also sends me a copy of my own post (this is a policy setting
on many mailing lists), so I get Discourse’s version also. That should
have the same message-id, because it is the same message, just via a
different route.
Discourse’s message is not “in reply to” my message. It is my
message, just forwarded.
This effect cascades through your following examples. The actual process
should be simpler than you’ve made it.
Think of it this way. If I reply to a post from email, it effectively is
like me emailing sam (and the others) via Discourse. Discourse
forwards my message to the email-receiving subscribers, and
“incidentally” keeps a copy on the forum
As a side note, I also looked into what GitHub do with their
notification emails, and noticed they do a similar thing where they
have an ever-present Reference
(discourse/discourse/pull/252@github.com) that is used in all the
emails related to that “topic” which in this case is a GitHub pull
request:
Hoo, github. What a disaster their issue emails are
However, in their scenario, the PR is the OP. So a reference directly
to the pull is sane. You could use the “topic” message-id for post 1,
provided you didn’t also use the “topic/1” id as well. But there seems
little point - it is extra effort to special case post 1 - I’d just use
“topic/1” myself.
To add some complication. As I understand it, an admin can move a post
or topic. Doesn’t that break the “generate the message-id” scheme,
particularly if they move just a post? I’m somewhat of the opinion that
every post should have a _message_id field, filled in from the
incoming message (from email) or generated (posting via Discourse). Then
it is persistent and stable and robust against any shuffling of posts or
changes of algorithm.
Finally, there’s a small security consideration: you should ignore the
inbound email message-id (and potentially bounce the message) if it
claims the message-id of an existing post. Since as an author, I can put
anything I like in that header I’d go with just dropping the
message-id - accept the post, but don’t let it lie about being some
other post - give your copy the Discourse-generated id and then proceed
as normal.
Grazie ancora per questa risposta meravigliosamente approfondita. Probabilmente mi ci vorrà un po’ per elaborare questo e trasformarlo in azioni concrete, quindi siate pazienti con noi (inoltre, ho altri progetti interni ad alta priorità su cui sto attualmente lavorando). Penso che con queste informazioni saremo in grado di rendere i nostri sistemi di threading molto più robusti e conformi alle specifiche. Potrei avere altre domande man mano che esaminerò il tuo post, grazie Cameron.
Di Martin Brennan tramite Discourse Meta alle 25Lug2022 00:28:
Wow, grazie ancora per questa risposta meravigliosamente approfondita. Probabilmente ci vorrà un po’ di tempo per elaborarla e trasformarla in elementi attuabili, quindi siate pazienti con noi (oltre a questo, ho altri progetti interni ad alta priorità su cui sto attualmente lavorando). Penso che con queste informazioni saremo in grado di rendere i nostri sistemi di threading molto più robusti e conformi alle specifiche. Potrei avere altre domande man mano che esamino il tuo post, grazie Cameron.
Ah, questa è un’osservazione interessante, non avevo notato la piccola freccia.
Anche questo è super interessante. Credo (senza esaminare il codice sorgente) che Thunderbird faccia proprio questo, e probabilmente anche l’interfaccia utente di Gmail, dato che fa la stessa cosa.
Sembra che lo stiamo facendo, ma immagino non in modo coerente? Fondamentalmente dobbiamo assicurarci che:
TODO #1 - Se un post ha un record IncomingEmail associato, usiamo sempre quel Message-ID quando inviamo email.
TODO #2 - Non usare un References quando si inviano email relative all’OP dell’argomento. @cameron-simpson una domanda però: se l’OP è stato creato tramite un’email in entrata, useremmo quel Message-ID in References per l’OP o lo escluderemmo comunque?
Questo è interessante, pensavo che ogni destinatario dell’email dovesse avere un Message-ID univoco? Infatti credo che sia per questo che abbiamo intrapreso la strada di aggiungere unicità al Message-ID di ogni destinatario, per evitare comportamenti di spam, ripensando al nostro argomento interno. Forse @supermathie, che fa parte del nostro team infrastrutturale e ha fatto molti test con le email all’inizio dell’anno, potrebbe intervenire anche qui?
Quello che stai dicendo è che è più il post a determinare un singolo Message-ID per tutti i destinatari. Quindi forse ne generiamo uno per ogni post che genera un’email? Allora potremmo anche spostare qui l’IncomingEmail.message_id. Provvisoriamente, la modifica che dovremmo apportare è:
TODO #3 - Aggiungere un outbound_message_id alla tabella Post. Generarlo una volta quando un’email viene inviata per la prima volta in relazione al post. Usarlo per gli header References e In-Reply-To successivi. Impostare il suo valore quando un post viene creato da un IncomingEmail. Il formato dovrebbe essere topic/:topic_id/:post_id/:stringa_alfanumerica_casuale@host ad esempio topic/233499/33545/gvy8475y7c45y87554c@meta.discourse.org
Dopo questa modifica, il mio primo esempio diventerebbe questo:
Con la considerazione anche che l’OP non ha una gestione speciale, non sarà più nel formato topic/:topic_id@hostname.
TODO #4 - Assicurarsi che vengano generati header In-Reply-To e References corretti basati sui PostReply records e sulla nuova colonna outbound_message_id nella tabella Post
Penso che abbiamo qualche considerazione per questo, controllerò.
Sembra decisamente così
Puoi confermare che i TODO qui sembrano ragionevoli, Cameron? Non sembra molto ora che ci guardo. Mi chiedo anche, quando mi occuperò di questo lavoro, saresti disponibile a unirti a me su un’istanza di Discourse di test su cui verranno distribuite le modifiche WIP, in modo da poterci scambiare email e testare che le cose funzionino correttamente? Ovviamente farò dei test per conto mio prima di coinvolgerti.
Se no, va bene lo stesso – ho Thunderbird e configurerò mutt e potrò testare tutto lì
@cameron-simpson una cosa che volevo chiarire qui è lo scope di “message_id”.
La cosa che ha dato il via a tutto questo è stato il forte sospetto di @supermathie che i nostri message_id non univoci stessero causando problemi.
Discourse genera email univoche per utente per ogni email che invia. Quindi, ad esempio, diciamo che 2 utenti stanno seguendo questo argomento:
L’utente 1 riceve il payload 1 con un link di annullamento dell’iscrizione distinto rivolto all’utente 1
L’utente 2 riceve il payload 2 con un link di annullamento dell’iscrizione distinto rivolto all’utente 2
Se in entrambi i casi il nostro message id fosse, ad esempio, discourse_topic_100/23 (topic_id/post_number), allora diremmo agli MTA che discourse_topic_100/23 può avere 2 payload distinti, l’ipotesi è che li trattino come un segnale di spam.
Ehi Discourse… hai appena inviato due email chiamate discourse_topic_100/23, che succede?
Poiché Discourse controlla tutto il trasporto delle email e le email non vengono aggiunte a una lista BCC o CC come le mailing list tradizionali, possiamo permetterci link di annullamento dell’iscrizione puliti per utente.
Cosa ne pensi? Che ne dici del semplice cambiamento di utilizzare discourse_topic_100/23/7333 ad esempio (topic_id, post_number, user_id) come identificatore univoco per la posta, è certamente un payload univoco e possiamo facilmente farvi riferimento quando generiamo email per un utente.
By Martin Brennan via Discourse Meta at 26Jul2022 00:27:
[quote=“Cameron Simpson, post:11, topic:233499,
username:cameron-simpson”]
Mutt probably ignores the References
because it is a mail reader, and References originates in USENET news.
Maybe Thunderbird is using the references or augumenting the in-reply-to
with references information.
You only need to consult one of In=-Reply-To or References to do
threading; the former comes from email and the latter from USENET.
You’re supporting both (which is great!) so we need to make them
consistent.
[/quote]
This is also super interesting. I believe (without examining the source) Thunderbird does do that, and likely the Gmail UI as well since it does the same thing.
I think mutt will use both, but probably just In-Reply-To if present, falling back to References. I’d need to check the source.
With References you do at least know the full chain to the OP; with In-Reply-To you more or less need the antecedant messages around to
stitch things together. For mailing lists I usually keep the whole
thread locally until it’s done anyway, and I expect that is common.
We do seem to be doing this but I guess not consistently? Basically we need to make sure that:
TODO #1 - If a post has an associated IncomingEmail record, we always use that Message-ID when sending email.
Yes. This is why I was thinking it might be sanest to have an explicit
field for the message-id, and to fill it in once. Then use that from
then on always, regardless of any changes to the process in which the
message-id is manufactured in the code later.
TODO #2 - Do not use a References when sending out emails related to the OP of the topic .
Yes. The OP has no antecedant, so there’s no References or In-Reply-To.
@cameron-simpson one question though – if the OP was created via an
inbound email, would we use that Message-ID in References for the
OP or still exclude it?
Still exclude. But use it as the persistent message-id for the OP.
So a message authored by email (OP or reply) gets its message-id from
the email. One authored on the web gets one when the user presses
Submit, generated by Discourse. From then on, that’s the message-id,
however created.
[quote=“Cameron Simpson, post:11, topic:233499,
username:cameron-simpson”]
You can just drop the sender_user_id and receiver_user_id from the
message-id field and get a single unique id which every receiver sees.
The uniqueness constraint is the post itself, not the individual
email-level “message” object.
[/quote]
This is interesting, I thought every recipient of the email had to have a unique Message-ID?
No. The message-id identifies the “message”. Not the individual copy. I
might post to the forum and CC someone directly. If that someone gets a
copy direct from me and also via the forum, they should have the same
message-id.
In fact I believe this is why we went down the path of adding
uniqueness to each recipient’s Message-ID, to avoid spam behaviours,
looking back on our internal topic. Perhaps @supermathie , who is on
our infra team and was doing a bunch of testing with email earlier in
the year, could weigh in here too?
Maybe. But on that face of it, threading is indeed broken. Certainly
sending the same message to many people should have the same message-id,
and generally, as a forwarder (email->discourse->email-recipients)
discourse shoud not be modifying the message-ids.
What you are saying is that it’s more that the post should be the thing determining a single Message-ID for all recipients. So perhaps we just generate one for each post that generates an email?
Every post should have one stable unique message-id for use in the email
side. If the post originated from an email, that original message-id
should be used. Otherwise (via the web interface) Discourse should be
generating a message-id and storing it with the post.
Then we could also move the IncomingEmail.message_id to here as well.
Sure. Having a distinct set of fields (message-id seems enough)
containing the email-side state should do it.
Tentatively, the change we would need to make is:
TODO #3 - **Add a outbound_message_id to the Post table. Generate
it once when an email is first sent in relation to the post.
If you got the post from an email, you should be using that, not
generating a new one.
Use if for subsequent References and In-Reply-To headers. Set its
value when a post is created from an IncomingEmail.
Yes. To the message-id from the email.
Format should be topic/:topic_id/:post_id/:random_alphanumeric_string@host e.g. topic/233499/33545/gvy8475y7c45y87554c@meta.discourse.org**
For ones you generate yourselves, this looks good to me.
After this change my first example would become this:
But note: the message-id only needs to be stable and unique. If the topic/:topid_id/:post_id@host is stable and will never be regenerated,
that will do. But if you’re concerned about that (eg db restores or
migrations or imports bringing those same numbers) then the random
string will make it robust against collision.
Note that the message-id left part is dot-atom-text, defined here:
which is alphas and digits and a limited set of punctuation characters
(which includes “/”).
Note the angle brackets. The message-id is formally the bit between the
angle brackets, and the angle brackets are mandatory. Syntax here:
With the consideration also that the OP does not have special handling, it will no longer be in the format topic/:topic_id@hostname.
Sounds good.
TODO #4 - Ensure that correct In-Reply-To and References headers are generated based on PostReply records and the new outbound_message_id column on the Post table
Thanks.
I think we have some consideration for this, I will double-check.
+1
It definitely seems that way
Can you confirm the TODOs here sound reasonable Cameron?
They seem correct to me.
It really doesn’t seem like much now that I look at it. I also wonder,
when I get to this work would you be open to joining a testing
Discourse instance with me that will have the WIP changes deployed to
it so we can email back and forth and test that things are working
correctly? I will of course do testing of my own before I involve you.
Certainly. Happy to help in whatever way.
If not, that’s fine too – I have Thunderbird and will be setting up mutt and I can test it all out there
Penso che tu possa ancora inviare messaggi distinti con lo stesso message-id, anche con piccole differenze come questa.
Le mailing list ordinarie fanno questo continuamente, in misura maggiore o minore. Almeno una manipolazione dell’intestazione avviene sempre. Ma anche il corpo del messaggio viene talvolta modificato. Un esempio eclatante è python-list, che scarta gli allegati non testuali. Il messaggio passa comunque con lo stesso message-id. E quasi tutte le liste aggiungono una nota in fondo con, ad esempio, un link alla pagina di amministrazione della lista o un link per annullare l’iscrizione. Quella non sarà stata sul messaggio quando è arrivato.
E ci sono state lunghe discussioni sulla firma dei contenuti che ruotano attorno a ciò che dovrebbe essere coperto da una firma.
Quindi sarei assolutamente d’accordo con te nell’aggiungere il tuo link di annullamento iscrizione specifico per il destinatario e nel preservare il message-id originale. I benefici superano di gran lunga la perdita del threading se tu dessi a ciascuna copia del messaggio un message-id individuale.
Ancora una volta, considera l’utente di posta elettronica. Posso rispondere a un messaggio di discourse e aggiungere un CC a una persona esterna interessata. Forse ne riceve una copia da discourse, forse no. Ma se lo facesse, dovrebbe avere il message-id sorgente su di esso anche con il tuo rider aggiuntivo. Altrimenti avrà 2 copie del mio messaggio, ma il suo sistema di posta non saprà che sono copie dello stesso messaggio. Ne consegue il caos.
Quindi, in breve: non penso che il tuo testo aggiuntivo di annullamento iscrizione, molto minore, giustifichi message-id distinti. Mantieni solo quello unico.
Mi dispiace, mi sto aggiornando 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 ingresso. Ha metadati diversi (a tal fine, A/Da/Rispondi a/Annulla iscrizione/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, facoltativamente seguiti da un corpo del messaggio.
Il campo “Message-ID:” fornisce un identificatore univoco del messaggio che fa riferimento a una particolare versione di un particolare messaggio.
[enfasi mia]
È proprio “particolare versione” 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 Forum” a Discourse come “Software Mailing List”, allora ha un certo senso farlo, quindi capisco da dove vieni. 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, pertanto, 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 modifica l’identità del messaggio e, pertanto, viene mantenuto il campo “Message-ID:” originale. In tutti i casi, è il significato che il mittente del messaggio desidera trasmettere (cioè, se si tratta dello stesso
messaggio o di 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?
Forse dovremmo usare Resent-Message-ID e simili?
È sempre stato lì, fin dall’822. Ma come dici più tardi, sì, è stato aggiornato.
5322 parla anche direttamente del modo in cui Discourse e Github lo utilizzano:
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 “filo” di conversazione.
Probabilmente in modo leggermente improprio, probabilmente a causa della mancanza di un “Thread Identifier” adatto. Ma questa interpretazione potrebbe non essere ciò che gli autori dell’RFC intendevano… non affronta i messaggi con un “References” ma senza “In-Reply-To”.
La parte difficile di questo è che non stiamo inviando una e-mail, ne stiamo inviando N - una per destinatario - in modo che i loro metadati individuali (Annulla iscrizione, ecc.) possano essere corretti.
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 fosse contrassegnato come spam.
I benefici qui, ad essere onesti, riguardano interamente il threading corretto delle e-mail in alcuni client di posta, a scapito della recapitalità.
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 più grande preoccupazione è la recapitalità: è già abbastanza difficile far recapitare le e-mail quando non c’è alcuna visibilità da parte dei principali provider.
Ma vedo un forte argomento per far sì che Discourse si comporti 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 nel preservare e riutilizzare i Message-ID in modalità mailing list?
Non voglio trovarmi in una situazione in cui il perfetto è nemico del sufficientemente buono.
Ora utilizziamo un “suffisso casuale” nei messaggi e questo sta innegabilmente causando problemi.
Abbiamo 3 opzioni sul tavolo:
ID messaggio casuali a cui non è possibile fare riferimento
ID messaggio stabili per argomento/post/utente
ID messaggio stabili per coppia argomento/post
Attualmente siamo nel pianeta (1) che sta causando scompiglio.
Temo che potremmo raggiungere la paralisi decisionale tra (2) e (3).
Forse possiamo semplicemente iniziare con (2) riconoscendo che l’aggiunta di CC extra a un’email da Discourse potrebbe causare comportamenti imprevisti, e almeno fermare la maggior parte dei problemi qui?
ah! Pensavo stessimo già facendo: topic/#{topic_id}/#{post_id}.s#{sender_user_id}r#{receiver_user_id}
Sarei propenso a, nell’interesse di bilanciare le preoccupazioni di unicità ed efficacia della consegna 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.
Allo stesso modo, con l’intestazione References, sarei propenso a farla assente per il post #1 in un argomento e farla fare riferimento all’argomento (quindi topic/#{topic_id}) e al post a cui si sta rispondendo, se presente.