tracker issue : CF-4146098

select a category, or use search below
(searches all categories and all time range)
Title:

[ANeff] Bug for: cfimap movemail creates new connection for each move

| View in Tracker

Status/Resolution/Reason: Closed/Withdrawn/ThirdParty

Reporter/Name(from Bugbase): Aaron Neff / Aaron Neff (Aaron Neff)

Created: 04/28/2016

Components: Net Protocols

Versions: 2016

Failure Type:

Found In Build/Fixed In Build: CF2016_Final /

Priority/Frequency: Major / Some users will encounter

Locale/System: English / Platforms All

Vote Count: 0

cfimap movemail creates new connection for each move. Mail servers can treat this as a DoS attack, when moving many emails.

Repro:

<cfscript>
  emailServer = "mail.domain.com";
  emailAddress = "user@domain.com";
  emailPassword = "password";
  
  for(i=1; i<=6; i++) {//create some test emails
	  cfmail(from=emailAddress, to=emailAddress, subject="cfimap mailmove test") {writeOutput('message ' & i);}
  }
  cfimap(action="open", server=emailServer, username=emailAddress, password=emailPassword, connection="myConnection");
  //cfimap(action="createfolder", connection="myConnection", folder="temp");//ensure temp folder exists
  cfimap(action="getall", connection="myConnection", name="allTestEmails") {//fetch the test emails
	  cfimapfilter(name="subject", value="cfimap mailmove test");
  }
  for(testEmail in allTestEmails) {//move each email to the temp folder
	  cfimap(action="movemail", connection="myConnection", uid=testEmail.uid, newFolder="temp");//see mail server logs show a new connection for each move (bad - all moves should share same session)
  }
  cfimap(action="close", connection="myConnection");
</cfscript>

Actual result: A new connection is created for each move.

Expected result: All moves should share the same connection.

----------------------------- Additional Watson Details -----------------------------

Watson Bug ID:	4146098

External Customer Info:
External Company:  
External Customer Name: Aaron Neff
External Customer Email:  
External Test Config: Verified on Windows 10 and Windows Server 2012 R2 in CF11 Update 7 (build 11,0,07,296330) and CF2016 (build 2016.0.01.298299).

Attachments:

Comments:

Hi Aaron, For moving mails from 2 folders for example from inbox to temp folder both these folders need to be accessed in read write mode. IMAP protocol uses select command to access the IMAP folder and at a time only one folder can be selected for connection. From RFC Only one mailbox may be selected at a time in a session; simultaneous access to multiple mailboxes requires multiple sessions. The SELECT command automatically deselects any currently selected mailbox before attempting the new selection. Consequently, if a mailbox is selected and a SELECT command that fails is attempted, no mailbox is selected. There by the underlying javamail library we are using for cfimap creating an additional connection to access and copy the messages to the destined folder. I have also tried first opening the inbox and reading the messages closing the folder, then opening the destination folder copying the messages and closing it, again opening inbox folder and purge the copied messages. But the such process is not thread safe & inefficient and was getting errors when tried. Because of such inefficiencies in IMAP protocol, a new move extension has been proposed & its spec is at https://tools.ietf.org/html/rfc6851. A simple excerpt form RFC about moving mails. This document defines an IMAP [RFC3501] extension to facilitate moving messages from one mailbox to another. This is accomplished by defining a new MOVE command and extending the UID command to allow UID MOVE. A move function is not provided in the base IMAP specification, so clients have instead had to use a combination of the COPY, STORE, and EXPUNGE commands to perform this very common operation. Implementors have long pointed out some shortcomings with this approach. Because the moving of a message is not an atomic process, interruptions can leave messages in intermediate states. Because multiple clients can be accessing the mailboxes at the same time, clients can see messages in intermediate states even without interruptions. If the source mailbox contains other messages that are flagged for deletion, the third step can have the side effect of expunging more than just the set of moved messages. Additionally, servers with certain types of back-end message stores might have efficient ways of moving messages, which don't involve the actual copying of data. Such efficiencies are often not available to the COPY/STORE/EXPUNGE process. The MOVE extension is present in any IMAP implementation that returns "MOVE" as one of the supported capabilities to the CAPABILITY command. Currently the javamail does not support this extension will file a bug for the same with javamail. Even javamail supports it in future the email server has to implement this extension. Also, the given code can be improved by giving the ids of all mails to be moved as a list to cfimap movemail action, instead of iterating over each mail & moving it to reduce the number of additional connections made to the mail server. Please let me know your thoughts on the same. Thanks, Pavan.
Comment by S V.
3000 | August 01, 2017 10:49:15 AM GMT
Hi Pavan, Thank you very much for your research! I've read thru the RFCs and see the MOVE extension would be nice/useful. If you log a bug at https://github.com/javaee/javamail/issues, would you please let me know the bug# so I can vote it up? Meantime, your suggestion of "giving the ids of all mails to be moved as a list to cfimap movemail action" works very nice! Only 2 connections are created. :) I didn't realize it makes such a difference to pass multiple Uids in 1 move mail vs calling movemail for each Uid. Part of me thinks this should be documented in cfimap's Uid description, but part of me thinks its best to just wait till javamail implements the MOVE extension. For now, I guess this could be closed as "Closed/Deferred/ThirdParty"? Thanks again!, -Aaron
Comment by Aaron N.
3001 | August 04, 2017 07:20:23 AM GMT