ombx.saveDraft(new OfflineContext(redo2), pm, id, -1, null);
ombx.saveDraft(new OfflineContext(redo2), pm, id);
    void syncMessage(int id, int folderId) throws ServiceException {        byte[] content = null;        Map<String, String> headers = new HashMap<String, String>();        try {            String hostname = new URL(ombx.getBaseUri()).getHost();            String url = ombx.getBaseUri() + UserServlet.SERVLET_PATH + "/~/?fmt=sync&nohdr=1&id=" + id;            Pair<Header[], byte[]> response = UserServlet.getRemoteResource(ombx.getAuthToken(), hostname, url);            content = response.getSecond();            for (Header hdr : response.getFirst())                headers.put(hdr.getName(), hdr.getValue());        } catch (MailServiceException.NoSuchItemException nsie) {            OfflineLog.offline.info("initial: message " + id + " has been deleted; skipping");            return;        } catch (MalformedURLException e) {            OfflineLog.offline.warn("initial: base URI is invalid; aborting: " + ombx.getBaseUri(), e);            return;        }        // XXX: UserServlet is also inlining these headers into the message body        int received = (int) (Long.parseLong(headers.get("X-Zimbra-Received")) / 1000);        int timestamp = (int) (Long.parseLong(headers.get("X-Zimbra-Modified")) / 1000);        int mod_content = Integer.parseInt(headers.get("X-Zimbra-Revision"));        int changeId = Integer.parseInt(headers.get("X-Zimbra-Change"));        int flags = Flag.flagsToBitmask(headers.get("X-Zimbra-Flags"));        String tags = headers.get("X-Zimbra-Tags");        int convId = Integer.parseInt(headers.get("X-Zimbra-Conv"));        if (convId < 0)            convId = Mailbox.ID_AUTO_INCREMENT;        ParsedMessage pm = null;        String digest = null;        int size;        try {            pm = new ParsedMessage(content, received, false);            digest = pm.getRawDigest();            size = pm.getRawSize();        } catch (MessagingException e) {            throw MailServiceException.MESSAGE_PARSE_ERROR(e);        } catch (IOException e) {            throw MailServiceException.MESSAGE_PARSE_ERROR(e);        }        CreateMessage redo = new CreateMessage(ombx.getId(), null, received, false, digest, size, folderId, true, flags, tags);        redo.setMessageId(id);        redo.setConvId(convId);        redo.setChangeId(mod_content);        redo.start(received * 1000L);        try {            // FIXME: not syncing COLOR            // XXX: need to call with noICal = false            Message msg = ombx.addMessage(new OfflineContext(redo), pm, folderId, true, flags, tags, convId);            ombx.syncChangeIds(sContext, id, MailItem.TYPE_MESSAGE, received, mod_content, timestamp, changeId);            OfflineLog.offline.debug("initial: created message (" + id + "): " + msg.getSubject());            return;        } catch (IOException e) {            throw ServiceException.FAILURE("storing message " + id, e);        } catch (ServiceException e) {            if (e.getCode() != MailServiceException.ALREADY_EXISTS)                throw e;            // fall through...        }        // if we're here, the message already exists; save new draft if needed, then update metadata        try {            Message msg = ombx.getMessageById(sContext, id);            if (!digest.equals(msg.getDigest())) {                pm.analyze();                // FIXME: should check msg.isDraft() before doing this...                SaveDraft redo2 = new SaveDraft(ombx.getId(), id, digest, size);                redo2.setChangeId(mod_content);                redo2.start(received * 1000L);                synchronized (ombx) {                    int change_mask = ombx.getChangeMask(sContext, id, MailItem.TYPE_MESSAGE);                    if ((change_mask & Change.MODIFIED_CONTENT) == 0) {                        ombx.saveDraft(new OfflineContext(redo2), pm, id, -1, null);                        ombx.syncChangeIds(sContext, id, MailItem.TYPE_MESSAGE, received, mod_content, timestamp, changeId);                    }                }                OfflineLog.offline.debug("initial: re-saved draft (" + id + "): " + msg.getSubject());            }        } catch (MailServiceException.NoSuchItemException nsie) {            OfflineLog.offline.debug("initial: message " + id + " has been deleted; no need to sync draft");            return;        } catch (IOException e) {            throw ServiceException.FAILURE("storing message " + id, e);        }        // use this data to generate the XML entry used in message delta sync        Element sync = new Element.XMLElement(MailService.E_MSG).addAttribute(MailService.A_ID, id);        sync.addAttribute(MailService.A_FLAGS, Flag.bitmaskToFlags(flags)).addAttribute(MailService.A_TAGS, tags).addAttribute(MailService.A_CONV_ID, convId);        sync.addAttribute(MailService.A_CHANGE_DATE, timestamp).addAttribute(MailService.A_MODIFIED_SEQUENCE, changeId);        sync.addAttribute(MailService.A_DATE, received * 1000L).addAttribute(MailService.A_REVISION, mod_content);        new DeltaSync(ombx).syncMessage(sync, folderId);    }