for (ImapMessage i4processed : i4list) i4processed.setGhost(false);
    boolean doCOPY(String tag, String sequenceSet, String folderName, boolean byUID) throws IOException {        if (!checkState(tag, ImapSession.STATE_SELECTED))            return CONTINUE_PROCESSING;        folderName = ImapFolder.importPath(folderName, mSession);        String command = (byUID ? "UID COPY" : "COPY");        String copyuid = "";        List<Pair<MailItem,MailItem>> movedMessages = new ArrayList<Pair<MailItem,MailItem>>();        try {            GetFolderOperation gfOp = new GetFolderOperation(mSession, getContext(), mMailbox, Requester.IMAP, folderName);            gfOp.schedule();            Folder folder = gfOp.getFolder();                        if (!ImapFolder.isFolderVisible(folder, mSession)) {                ZimbraLog.imap.info(command + " failed: folder is hidden: " + folderName);                sendNO(tag, command + " failed");                return CONTINUE_PROCESSING;            } else if (!ImapFolder.isFolderWritable(folder, mSession)) {                ZimbraLog.imap.info(command + " failed: folder is READ-ONLY: " + folderName);                sendNO(tag, command + " failed: target mailbox is READ-ONLY");                return CONTINUE_PROCESSING;            }            Set<ImapMessage> i4set;            synchronized (mMailbox) {                i4set = mSession.getFolder().getSubsequence(sequenceSet, byUID);            }            // RFC 2180 4.4.1: "The server MAY disallow the COPY of messages in a multi-            //                  accessed mailbox that contains expunged messages."            if (!byUID && i4set.contains(null)) {                sendNO(tag, "COPY rejected because some of the requested messages were expunged");                return CONTINUE_PROCESSING;            }            i4set.remove(null);            long checkpoint = System.currentTimeMillis();            List<Integer> srcUIDs = new ArrayList<Integer>(), copyUIDs = new ArrayList<Integer>();            int i = 0;            List<ImapMessage> i4list = new ArrayList<ImapMessage>(ImapCopyOperation.SUGGESTED_BATCH_SIZE);            for (ImapMessage i4msg : i4set) {                i4msg.setGhost(true);                i4list.add(i4msg);                // we're sending 'em off in batches of 50                if (++i % ImapCopyOperation.SUGGESTED_BATCH_SIZE != 0 && i != i4set.size())                    continue;                ImapCopyOperation op = new ImapCopyOperation(mSession, getContext(), mMailbox, Requester.IMAP, i4list, folder.getId());                op.schedule();                for (Pair<MailItem,MailItem> target : op.getMessages()) {                    movedMessages.add(target);                    int id1 = target.getFirst().getImapUid(), id2 = target.getSecond().getImapUid();                    srcUIDs.add(Math.min(id1, id2));  copyUIDs.add(Math.max(id1, id2));                }                // send a gratuitous untagged response to keep pissy clients from closing the socket from inactivity                long now = System.currentTimeMillis();                if (now - checkpoint > MAXIMUM_IDLE_PROCESSING_MILLIS) {                    sendIdleUntagged();  checkpoint = now;                }                for (ImapMessage i4processed : i4list)                    i4processed.setGhost(false);                i4list.clear();            }            if (srcUIDs.size() > 0)                copyuid = "[COPYUID " + ImapFolder.getUIDValidity(folder) + ' ' +                          ImapFolder.encodeSubsequence(srcUIDs) + ' ' +                          ImapFolder.encodeSubsequence(copyUIDs) + "] ";        } catch (IOException e) {            // 6.4.7: "If the COPY command is unsuccessful for any reason, server implementations            //         MUST restore the destination mailbox to its state before the COPY attempt."//            deleteMessages(movedMessages);            ZimbraLog.imap.warn(command + " failed", e);            sendNO(tag, command + " failed");            return CONTINUE_PROCESSING;        } catch (ServiceException e) {            // 6.4.7: "If the COPY command is unsuccessful for any reason, server implementations            //         MUST restore the destination mailbox to its state before the COPY attempt."//            deleteMessages(movedMessages);            String rcode = "";            if (e.getCode() == MailServiceException.NO_SUCH_FOLDER) {                ZimbraLog.imap.info(command + " failed: no such folder: " + folderName);                if (ImapFolder.isPathCreatable('/' + folderName))                    rcode = "[TRYCREATE] ";            } else                ZimbraLog.imap.warn(command + " failed", e);            sendNO(tag, rcode + command + " failed");            return canContinue(e);        }        // RFC 2180 4.4: "COPY is the only IMAP4 sequence number command that is safe to allow        //                an EXPUNGE response on.  This is because a client is not permitted        //                to cascade several COPY commands together."        sendNotifications(true, false);    	sendOK(tag, copyuid + command + " completed");        return CONTINUE_PROCESSING;    }