Threading for email notifications
I'd love it if TalkYard would make it possible for email clients to create email threads that matched the forum threads.
So if I had email notifications enabled, and there were 5 posts in topic A, and 3 posts in topic B, and 6 posts in Topic C, I'd have 14 total emails, but my email client could group them into three email threads (one thread for each topic).
So in my email client, the threads would look something like this:
To do this, TY would have to use subject lines that matched the forum thread and set the In-Reply-To
and References
email headers to tell the email client which emails are associated with which forum threads.
When I'm reading TY notification emails, I'd like to follow the thread, but the current implementation makes each notification totally independent, so it creates a lot of clutter. I often see the last message in a thread where the user says their issue is resolved, but then I have to go through all the emails to find all the notifications that were associated with that particular forum thread.
It looks like part of the motivation for the current implementation was to address needs of users like @chrscheuer, but I'd love to find a way to manage noise from email notifications while also enabling email clients to organize them well.
Linked from:
- CChristian Scheuer @chrscheuer
I'd love this as well :)
- CChristian Scheuer @chrscheuer
My issue was with the email threads being based on "notification type" which made no sense. Having an option to send emails with subjects matching each Talkyard page would be a great option.
Ideally each user could decide which format of the two they prefer.
- In reply tomichael⬆:KajMagnus @KajMagnus2022-06-22 12:40:03.339Z
This would be nice for me too. And then, with one email thread per forum topic, it'd be simpler to implement Reply-via-email too (later if anyone wants this).
Thanks for the mockup, and link to the header docs — I didn't know about
In-Reply-To
andReferences
. (I've been surprised by how my email client (Gmail) groups emails seemingly by looking at[server.addr]
only but I suppose these headers help it to do the right thing)- Michael Lynch @michael
Just wanted to check in to see if there's been any forward progress or timeline for this issue.
Our posting volume has increased, and threaded email conversations would make it a lot easier to manage these conversations.
- KajMagnus @KajMagnus2022-08-25 12:18:35.275Z
Not yet started. Will have been fixed in the middle of September I think. I just posted a mini roadmap: Mini roadmap, fall 2022
(Sorry for the noisy threads)
- In reply tomichael⬆:KajMagnus @KajMagnus2022-09-06 18:53:18.150Z2022-09-06 19:01:08.992Z
Threading for emails — here's what's on my mind, implementation wise:
For each [new page notification] being sent, Ty generates a SMTP
Message-ID
, and includes in the email. Later, when notifications are sent about comments on that page, then, for each person being notified,[LKP:]
Ty looks up all previous notifications s/he got, about that page, gets theirMessage-ID
s, sorts by time, and includes in theReferences
SMTP header.The lookup
[LKP:]
above could be done slightly differently: Ty could look up only all ancestor comments, and include only those in theReferences: ...
header. Instead of all comments on the same page. — That is, sub threads on the same page. I wonder what mail clients do then: different "threads", but all of them starting with the same Message-ID (for the Orig Post).And Ty also sets
In-Reply-To: ...
to the Message-ID about the parent comment (which would also ... always? be last in theReferences: ...
list), or the whole page's Message-ID if it's the Orig Post.And the subject line would, I suppose, have to include the original title of the page, even if, later on, it got renamed, because apparently Gmail groups by email subject line instead (see: https://stackoverflow.com/a/23482109). — So, for each person getting notified, maybe Ty would need to remember the original title of that email thread ?
***
I wonder if there are security implications from generating these
Message-ID
s per post, or [per person getting notified]. If it matters if everyone who gets notified about a post, gets the sameMessage-ID
. Or if it's somehow better, if everyone see uniqueMessage-ID
s. ... ?Any thoughts?
One thing could be that if both person P and person Q got notified about comment C, then, Q could send a handcrafted email to P, with a
Message-ID
specifying comment C (if P and Q see the same ID). In this way, Q could try to inject Q's own email in the email thread as seen by P. Then, maybe maybe an email client shows Q's message as part of the email thread, and P mistakenly thinks that it got sent by the Ty server but it's from Q.( @chrscheuer I'll do the may-
@mention
-me thing first, just nice to start thinking about this threading stuff now directly :- ))- Michael Lynch @michael
Ty looks up all previous notifications s/he got, about that page, gets their Message-IDs, sorts by time, and includes in the References SMTP header.
I don't think you'd have to keep track of which messages each recipient has received. It should be sufficient for Ty to store a unique
Message-ID
for each message in a thread, and then whenever there's a reply, you walk up the tree of responses and add theirMessage-ID
to theReferences
header until you get to the root post of the thread.If a mail client has never seen some of the message IDs referenced in a
References
header, that should be fine. I think mail clients will just ignore the unrecognized ones.I wonder if there are security implications from generating these Message-IDs per post, or per person. If it matters if everyone who gets notified about a post, gets the same Message-ID. Or if it's somehow better, if everyone see unique Message-IDs. ... ?
That doesn't strike me as a security liability, but you could try sending messages from Google Groups / Mailchimp / Topicbox and see if they generate a unique
Message-ID
per recipient. If they don't, it's likely pretty low risk.One thing could be that if both person P and person Q got notified about comment C, then, Q could send a handcrafted email to P, with a Message-ID specifying comment C. In this way, Q could try to inject Q's own email in P's email thread. Then, maybe maybe an email client shows Q's message as part of the email thread, and P mistakenly thinks that it got sent by the Ty server.
Yeah, but there's not much advantage in doing that. Q can already send the same email to P by posting a real comment to Ty, which will generate a message to victim P. That attack also requires Q to know P's email address.
And the subject line would, I suppose, have to include the original title of the page, even if, later on, it got renamed, because apparently Gmail groups by email subject line instead (see: https://stackoverflow.com/a/23482109). — So, for each person getting notified, maybe Ty would need to remember the original title of that email thread ?
This is unnecessary (for my use case, at least). If I change the subject of the thread on Ty, I'm fine with that breaking the threading in my mail client.
- KajMagnus @KajMagnus2022-09-06 20:01:53.514Z
Thanks! Yes, reading about
Message-ID
it seems the servers usually send the same ID to everyone. At the same time, someone wrote: "the message id may be the only information your get back from spam notifications or bounces" https://stackoverflow.com/a/831560 so I guess that could be a good thing. Anyway implementation wise, it barely matters.Google Groups / Mailchimp / Topicbox and see if they generate a unique Message-ID per recipient
Sounds like a good idea.
Q can already send the same email to P by posting a real comment to Ty, which will generate a message to victim P.
Yes, at the same time, in the future the Ty server might have some dangerous-link detection and block such messages. Or Q might send a message with angry words to P, which the server staff cannot see, but P might think they read and approved Q's angry message. But this seems a bit far fetched, at least today.
Edit: Hmm, using per-email unique Message-IDs, to simplify [looking into bounces], seems to be a thing, here's Postmarkapp:
https://postmarkapp.com/blog/using-messageid-to-retrieve-bounces
users can use the messageID field on the Bounces API to retrieve a specific bounce [...]
The messageID is the string returned for each successfully sent email through the API- Michael Lynch @michael
Edit: Hmm, using per-email unique Message-IDs, to simplify [looking into bounces], seems to be a thing, here's Postmarkapp:
https://postmarkapp.com/blog/using-messageid-to-retrieve-bounces
The
messageID
they're talking about is a Postmark-specific field that they add to the JSON payload for email notifications. It's independent from theMessage-ID
header in the actual message.
- In reply tomichael⬆:KajMagnus @KajMagnus2022-11-17 16:03:36.980Z
Now threaded emails are live here at Ty .io, however, turns out that Amazon SES (which Ty uses) replaces Message-ID with its own id. So the SMTP headers I'm getting when testing, look like:
Message-ID: <010001848635c685-b8f4ebfa-13e3-4c69-a552-314db32215ba-000000@email.amazonses.com> In-Reply-To: <123.1.273.1234@forum.talkyard.io> References: <123.1.273.1234@forum.talkyard.io> Subject: [forum.talkyard.io] Threads test 001
This breaks threading, at least in Gmail — Gmail even starts a new thread, per comment, even though the subject line is the same (when on the same page).
What's on my mind is to switch to Postmarkapp, which Ty uses already anyway for handling incoming emails.
Postmarkapp keeps the Message-ID (in addition to adding its own
MessageID
(without a-
), like you noted. I wonder why they didn't choose a more different name).
But only if the sender includes an extra headerX-PM-KeepID: true
(so I'll make Ty add that extra header).- Michael Lynch @michael
Oh, frustrating about SES.
I've used Postmark for threaded messages in a different app I developed, and I can confirm the threading works. Postmark doesn't overwrite any of the
Message-ID
,In-Reply-To
orReferences
headers, so it works as you'd expect.- KajMagnus @KajMagnus2022-11-19 17:42:25.451Z
Ok thanks for the info. I switched to Postmarkapp yesterday, and it still didn't work not even with the
X-PM-KeepID
header. Apparently this is because the Java library I'm using (Apache Commons Email), also overwrites the Message-ID header (but leaves References and In-Reply-To intact). So I'll fix that and try again- Michael Lynch @michael
Sorry, I realized I was misremembering. In the other app I'm using with Postmark, I'm not setting the
Message-ID
header.Do you need to set the
Message-ID
header? As long as you can determine the message ID that the system generated for the first message in the thread, can't you achieve threading by settingIn-Reply-To
andReferences
on subsequent emails in the thread?- KajMagnus @KajMagnus2022-11-21 05:35:05.939Z
I think it works now :- ) see the separate threads Test 01 and 02. I'll upgrade Prod tomorrow.
Do you need to set the Message-ID header? [...] determine the message ID that the system generated
Yes that would work as well, however, then the message ID would end up with the wrong
....@domain
suffix. Now instead I could set it to...@forum.talkyard.io
or whatever the address of the site is. (Javax.mail doesn't know what hostname to use, when many sites hosted by the same server).(It was javax.mail, not Apache Commons Mail, that was behaving in (I think) odd ways)
- Michael Lynch @michael
Awesome, the test threads are working for me!
- CChristian Scheuer @chrscheuer
FWIW this entire thread has worked threaded for me in Gmail.
- KajMagnus @KajMagnus2022-11-21 14:32:13.015Z
Ok :- ) Good to know. I think it's because Gmail groups emails based on the subject line or the Message-ID. So I think Gmail started threading sooner, before email clients that only use Message-ID.
Here's Google's docs: https://support.google.com/mail/answer/5900?hl=en&co=GENIE.Platform%3DDesktop#zippy=%2Chow-gmail-groups-automated-emails
Emails are grouped if each message meets the following:
- The same recipients, senders, or subject as a previous message
- A reference header with the same IDs as a previous message
- Sent within one week of a previous message
(I'm surprised about that last point (!). New threads after a week? Hmm, maybe that's only for automated emails.)
- In reply tomichael⬆:KajMagnus @KajMagnus2022-11-22 08:16:26.976Z
Now I've upgraded Prod. (Finally :- ))
- Michael Lynch @michael
Thanks! My team is very excited. I just saw TalkYard thread two email notifications in the same thread and was delighted!
- In reply tomichael⬆:Michael Lynch @michael
Threaded emails are working great! It's so much easier to manage our discussions now.
I have a small request for a tweak. Is it possible to use a tag other than
blockquote
for the reply contents? In Fastmail (perhaps in other clients too), it thinks thatblockquote
tags are strictly for quoting text from earlier in the thread, so it collapses them by default:- KajMagnus @KajMagnus2022-12-06 17:21:03.971Z
I'll fix, I could change to a
<div>
, maybe indented (what do you think?).I suppose
<q>
tags might look odd — maybe the email client then adds quotation marks at the start and end of each paragraph (I suppose each paragraph should be wrapped in a<q>
, since it's an inline element, hmm). I could experiment a bit with that.***
In a way, the text in the reply, it's not a quote, but the actual main message, so ... I guess in some ways it makes sense, what Fastmail is doing, hmm. Gmail doesn't collapse.
- Michael Lynch @michael
Yeah, I'm not sure how Fastmail handles the
<q>
tags. It might have the same problem. I think<div>
tag is safest because it's hard for Fastmail to confuse that with a quoted reply.- KajMagnus @KajMagnus2022-12-19 09:59:16.889Z
Now the
<blockquote>
is gone ( & Prod updated). The reply is in a<p style="padding-left:2em">
instead, and a<hr>
above and below (in casepadding-left=...
didn't work in some email client. A bit unnecessary with both<hr>
andpadding-left=...
I guess, hmm).- Michael Lynch @michael
Great, the new version fixes the issue. Thanks!
- Progresswith doing this idea