/** * Appends the given messages to the selected folder. This implementation also determines the new * UID of the given message on the IMAP server and sets the Message's UID to the new server UID. */ @Override public void appendMessages(Message[] messages) throws MessagingException { checkOpen(); try { for (Message message : messages) { // Create output count CountingOutputStream out = new CountingOutputStream(); EOLConvertingOutputStream eolOut = new EOLConvertingOutputStream(out); message.writeTo(eolOut); eolOut.flush(); // Create flag list (most often this will be "\SEEN") String flagList = ""; Flag[] flags = message.getFlags(); if (flags.length > 0) { StringBuilder sb = new StringBuilder(); for (int i = 0, count = flags.length; i < count; i++) { Flag flag = flags[i]; if (flag == Flag.SEEN) { sb.append(" " + ImapConstants.FLAG_SEEN); } else if (flag == Flag.FLAGGED) { sb.append(" " + ImapConstants.FLAG_FLAGGED); } } if (sb.length() > 0) { flagList = sb.substring(1); } } mConnection.sendCommand( String.format( ImapConstants.APPEND + " \"%s\" (%s) {%d}", ImapStore.encodeFolderName(mName, mStore.mPathPrefix), flagList, out.getCount()), false); ImapResponse response; do { response = mConnection.readResponse(); if (response.isContinuationRequest()) { eolOut = new EOLConvertingOutputStream(mConnection.mTransport.getOutputStream()); message.writeTo(eolOut); eolOut.write('\r'); eolOut.write('\n'); eolOut.flush(); } else if (!response.isTagged()) { handleUntaggedResponse(response); } } while (!response.isTagged()); // TODO Why not check the response? /* * Try to recover the UID of the message from an APPENDUID response. * e.g. 11 OK [APPENDUID 2 238268] APPEND completed */ final ImapList appendList = response.getListOrEmpty(1); if ((appendList.size() >= 3) && appendList.is(0, ImapConstants.APPENDUID)) { String serverUid = appendList.getStringOrEmpty(2).getString(); if (!TextUtils.isEmpty(serverUid)) { message.setUid(serverUid); continue; } } /* * Try to find the UID of the message we just appended using the * Message-ID header. If there are more than one response, take the * last one, as it's most likely the newest (the one we just uploaded). */ String messageId = message.getMessageId(); if (messageId == null || messageId.length() == 0) { continue; } // Most servers don't care about parenthesis in the search query [and, some // fail to work if they are used] String[] uids = searchForUids(String.format("HEADER MESSAGE-ID %s", messageId)); if (uids.length > 0) { message.setUid(uids[0]); } // However, there's at least one server [AOL] that fails to work unless there // are parenthesis, so, try this as a last resort uids = searchForUids(String.format("(HEADER MESSAGE-ID %s)", messageId)); if (uids.length > 0) { message.setUid(uids[0]); } } } catch (IOException ioe) { throw ioExceptionHandler(mConnection, ioe); } finally { destroyResponses(); } }