2

Is there any limits on how many concurrent clients you can connect to one mail account?

I have an app that opens a new ImapClient on each request. The ImapClient will open INBOX and FolderA, and move a mail by UID from one to another. The multiple clients will never access the same mail concurrent, but probably move multiple mails in same account concurrent.

Errors seems to occur once I hit about 5+ clients simultanious, using Exchange, and response with a lot of different errors as: "The IMAP server replied to the 'COPY' command with a 'NO' response." "The IMAP server replied to the 'EXPUNGE' command with a 'NO' response."

When I'm moving mails I do following sequence:

  1. Using a new ImapClient
  2. Connect and auth the client
  3. GetFolderAsync of INBOX and FolderA, then wait for the response
  4. Open the INBOX with OpenSync() with ReadWrite, and wait for the task.
  5. Fetch INBOX with FetchAsync(), looping through the result to find the wanted UID based on MessageID
  6. Calling MoveToAsync() moving the mail based on uid to the FolderA, and waiting
  7. FolderA.SetFlagAsync() with new UID, and flagging the mail with SEEN
  8. Waiting on 6. & 7.
  9. INBOX.SetFlagAsync() with the previous UID, and flagging the mail with DELETED, wait for the operation
  10. Closing IMAP folders using INBOX.CloseAsync and FolderA.CloseAsync
grmihel
  • 784
  • 3
  • 15
  • 40

1 Answers1

2

There is no standard that defines the maximum number of clients an IMAP server will allow. I've read that Thunderbird uses a max of 5 concurrent connections (which probably suggests they found that worked well for most IMAP servers in the wild), so that might explain what you are seeing.

jstedfast
  • 35,744
  • 5
  • 97
  • 110
  • Actually some further investigation shown, that MailKit had no problem creating like 15 async connections (connecting, auth'ing, selecting INBOX and FolderA) and even fetch inbox for all 15 connections. But as soon as I start to use MoveTo() in the sequence of all 15 connections, and start to flag the mail in the previous folder as deleted, and if the dest folder is inbox, then as unseen, then troubles seems to occur with the Exchange responding NO to COPY. And in the Imap protocol log I see the following line in the end "C: COPY 29,33 INBOX S: NO COPY failed or partially completed." – grmihel Apr 11 '16 at 07:51
  • So the question is, are there any forbidden or dangerous steps in the move mail sequence written in the initial question? – grmihel Apr 11 '16 at 08:00
  • Did another client move any of the same messages? – jstedfast Apr 11 '16 at 11:11
  • 1
    I just noticed this, but it seems that you are using the index-based APIs rather than the UniqueID-based APIs. This can present a real problem if you have multiple clients acting on the same folder because it'll change index offsets of messages. – jstedfast Apr 11 '16 at 12:37
  • I think that's exactly what goes wrong. But I'm not sure how I get the UID based instead of index based. I Fetch the folders to get all messages, since I don't know the UID (only the MessageID). And as I need the UID to make a MoveTo / COPY, then I need to figure out the UID based on the known MessageID, or did I miss a better way to do this? – grmihel Apr 11 '16 at 16:20
  • How are you getting the index? – jstedfast Apr 11 '16 at 17:46
  • source.FetchAsync(0, -1, MessageSummaryItems.Envelope | MessageSummaryItems.UniqueId, cancelToken) an then loop them over to match messageid – grmihel Apr 12 '16 at 10:22
  • Okay, then you already have the UniqueId... when you find the item with the matching `item.Envelope.MessageId`, you can use `item.UniqueId` instead of `item.Index`. – jstedfast Apr 12 '16 at 13:21
  • Already doing so by following foreach (var summary in fetchTask.Result.Where(summary => summary.Envelope.MessageId == messageId)) { uid = summary.UniqueId; break; } – grmihel Apr 12 '16 at 13:54