[Top] [All Lists]

Re: Multi-message reply and "References:"

2003-06-06 21:03:52

Pete Resnick <presnick(_at_)qualcomm(_dot_)com> wrote:

We've got a new feature we're implementing in Eudora: Replying to
multiple messages.

Mutt does this.

Forming the "In-Reply-To:" is easy. You take the message-id's of all
of the messages to which you're replying and put them in.

That's what mutt does, and what RFC 2822 specifies.

But "References:" is a different problem.

Agreed.  Mutt constructs some list of message-IDs, but it's not obvious
how, and I can't find any documentation (let alone justification) for
the behavior.  RFC 2822 discourages the creation of a References field
for a reply that has multiple parents.

As it is used in usenet and elsewhere now, everything assumes a single
rooted thread.  But when replying to multiple messages, you can end up
with a multi-rooted thread. And if you reply to two messages that have
a common root, you end up with branches re-joining.

If every message is a reply to at most one message, then the full graph
is a tree, and the ancestry of any one message is a linear chain, which
is easily represented by the References field.

But if every message can be a reply to several other messages, then the
full graph is a directed acyclic graph (DAG), and the ancestry of any
one message is also a DAG.

If you want to represent that ancestry graph in the References field
(RFC 2822 notwithstanding), I can't imagine how it could be done with
just a list of message-IDs (unless you have lots of duplicates).  I
think you're going to need additional markers.  If additional markers
are acceptable, then you can use them to eliminate all duplicates.  Here
is the first idea that comes to my mind:

References: *( [parents] message-ID )

Each message-ID is optionally preceeded by a parents marker, which is a
hyphen-separated list of integers.  0 refers the previous message-ID in
the list, 1 refers to the message-ID before that, and so on.  A hyphen
with no integers means no parents (the following message-ID was not a
reply to anything).  If the parents marker is absent, it defaults to
"0", which is equivalent to the current convention.

The list can be constructed by doing a reverse depth-first traversal of
the DAG:

      if msgid is not in the references list then begin
        for each parent of msgid do visit(parent)
        let pset = {}
        for each parent of msgid do begin
          find parent in the references list
          add its position to pset
        if pset is {} then let parents = "-"
        else if pset is {0} then let parents = ""
        else let parents = join(pset, "-")
        append to the references list: parents msgid

    start with an empty references list

It might be better to use a new header field for this.  The References
field was not originally intended to be a reply history, and certainly
not intended to be this structured.