Subject: [Jmap] message copying and moving

From: Josef 'Jeff' Sipek <[email-masked]>
Date: Mon, 31 Jul 2017 16:44:53 +0300

There appear to be three different ways in jmap mail to "copy" an email from
one mailbox to another.  That is, duplicating a message but leaving the
original in place (like COPY in IMAP).  They are:

1. setMessages on an existing message's messageId with destination
   mailbox's mailboxId added to mailboxIds
2. importMessages with blobId referencing an existing message's blobId
3. copyMessages with fromAccountId == toAccountId

Based on my reading of the draft, the semantics of these are:

The first method creates a "hardlink" copy - any keyword changes will be
shared by all the copies of the message.

The second method creates a total duplicate of the message and its metadata.
The new copy has a new messageId.  Changes to keywords are not propagated to
other copies.  (The headers and body may be shared by the copies if the
server supports some form of transparent deduplication.)

The third method appears to work similarly to the second.  That is, a new
messageId is created and the new duplicate is *not* "linked" to the original.

When it comes to moving mails from one mailbox to another (like MOVE or
COPY+EXPUNGE in IMAP) the situation is equally complex.  The options are:

1. setMessages on an existing message's messageId with destination
   mailbox's mailboxId replacing the source mailbox's mailboxId in
   mailboxIds
2. importMessages with blobId referencing an existing message's blobId,
   followed by a setMessages on the original message but removing the
   source mailbox's mailboxId from mailboxIds
3. copyMessages with fromAccountId == toAccountId, followed by setMessages
   on the original message but removing the source mailbox's mailboxId from
   mailboxIds

The first method preserves the "links" between the source message and any
other "hardlinks" it may have had.

The second method creates a totally independent copy (much like IMAP COPY +
EXPUNGE).  (The headers and body may be shared with other copies if the
server supports some sort of transparent deduplication.)

The third method has same semantics as the second.

This brings up a number of questions:

The description of copyMessages (jmap mail section 5.5) is confusing.
Instead of describing what the call does, it talks about one potential use
(namely, moving emails between accounts).  Am I understanding the
copyMessages semantics correctly?  Or is it more like IMAP MOVE rather than
COPY?

Is there a limit to how many mailboxes a message may belong to?  I can't
seem to find anything that talks about it.  If the server implements a
limit, what would be the appropriate error to return from setMessages?  What
should a client do when it encounters this error?  Should it try to fall
back to copyMessages?

Does it make sense to allow copyMessages with fromAccountId equal to
toAccountId?

My inclination is to say that there should be only one way to copy emails.
At the same time, I see a reason for both "hardlink" and "copy" flavors of
copying to exist and the server supporting whatever is feasible given the
storage format it uses.  Sadly, that leads to added complexity in the
client.

Thanks,

Jeff.

---

From: Ted Lemon <[email-masked]>
Date: Mon, 31 Jul 2017 10:54:22 -0400

> storage format it uses.  Sadly, that leads to added complexity in the

I think this is right, and is the right way to document it.   Default behavior on the client should be link—it's unlikely that the user ever wants a copy when a link is possible.   The only use case for copy is when the mail client is showing two mail stores on separate servers, or in the rare case where the user _wants_ two copies that are treated differently.   (I'm curious if there is general agreement on this or if folks think I'm crazy, though!)

---

From: अजय डाटा (Ajay DATA) <[email-masked]>
Date: Mon, 31 Jul 2017 21:35:07 +0530

In case of MOVE, how about we just change the owner ID of the message , and  not move the email message at all.

In copy, just hardliNk wirh new UID and do not move the messages at all.

Thanks. 

On July 31, 2017 7:14:53 PM GMT+05:30, Josef 'Jeff' Sipek <[email-masked]> wrote:
>_______________________________________________
>Jmap mailing list
>[email-masked]
>https://www.ietf.org/mailman/listinfo/jmap

-- 
Sent from my Android device with BharatSync Communicator.

---

From: Neil Jenkins <[email-masked]>
Date: Tue, 01 Aug 2017 13:38:35 +1000

On Mon, 31 Jul 2017, at 11:44 PM, Josef 'Jeff' Sipek wrote:
> There appear to be three different ways in jmap mail to "copy" an email> from one mailbox to another.  That is, duplicating a message but leaving the> original in place (like COPY in IMAP).  They are:
> 

Not exactly. JMAP is currently designed so it's optional for servers to support the concept of a single message appearing in multiple mailboxes ("labels" rather than "folders"). This is designated by the mustBeOnlyMailbox property on the mailbox objects, but I think we should re-evaluate this. It seems likely to be the same for every mailbox in the account. A simpler (and better IMO) method would be to add a maxMailboxesPerMessage property to the capabilities given for an account, which would be 1 for simple IMAP proxies and >1 for more sophisticated servers.
> 2. importMessages with blobId referencing an existing message's blobId> 3. copyMessages with fromAccountId == toAccountId

While not intended for this purpose, yes these could be used to copy messages. However, 
> The first method creates a "hardlink" copy - any keyword changes will be> shared by all the copies of the message.

Looking at the spec, this needs to be clarified. However I believe we definitely need to make it so that (2)/(3) MAY return an existing message id if the content is the same as an existing message (or alternatively an error; either works for me). For example, the Cyrus implementation of JMAP uses a secure hash of the message content to generate the message id, so you cannot have two identical messages within the same user with different message ids.
> When it comes to moving mails from one mailbox to another (like MOVE or> COPY+EXPUNGE in IMAP) the situation is equally complex.  The options are:> 

Yes, this is the expected way clients would do it.

> 2. importMessages with blobId referencing an existing message's blobId,>   followed by a setMessages on the original message but removing the
> 3. copyMessages with fromAccountId == toAccountId, followed by
> setMessages on the original message but removing the source mailbox's mailboxId from mailboxIds
Again, what this does depends on whether the server supports multiple copies of the same message content with different ids.
So I think the following would help:
 * Remove mustBeOnlyMailbox property from individual mailbox objects and add a capability for maxMailboxesPerMessage instead. Add an appropriate error for setMailboxes if you try to go over this limit.
 * Allow servers to return an error instead of copy/import if the message already exists, rather than creating a duplicate with separate metadata. (But if it does succeed, then it MUST have separate metadata, be a new message id). 
A lot of this depends on how much flexibility we want to give servers for making it easier to proxy/build-on IMAP. Every extra option does make it harder for clients. I'd be happy to forbid having two copies of the same message in the same user if people think this is reasonable. So something like:
 * maxMailboxesPerMessage MUST be at least 10 (or greater)
 * copyMessages fromAccount MUST be different to toAccount
 * (import|copy)Messages MUST reject attempts to import/copy a message whose content already exists.
Or similar.

On Tue, 1 Aug 2017, at 12:54 AM, Ted Lemon wrote:
> it's unlikely that the user ever wants a copy when a link is possible.
Agreed. The current spec was designed for allowing the possibility that a link is not possible. But maybe we can be more prescriptive about what servers must support.
Neil.