Search in sources :

Example 26 with DeliveryOptions

use of com.zimbra.cs.mailbox.DeliveryOptions in project zm-mailbox by Zimbra.

the class ZimbraLmtpBackend method deliverMessageToLocalMailboxes.

private void deliverMessageToLocalMailboxes(Blob blob, BlobInputStream bis, byte[] data, MimeMessage mm, LmtpEnvelope env) throws ServiceException, IOException {
    List<LmtpAddress> recipients = env.getLocalRecipients();
    String envSender = env.getSender().getEmailAddress();
    boolean shared = recipients.size() > 1;
    List<Integer> targetMailboxIds = new ArrayList<Integer>(recipients.size());
    Map<LmtpAddress, RecipientDetail> rcptMap = new HashMap<LmtpAddress, RecipientDetail>(recipients.size());
    try {
        // Examine attachments indexing option for all recipients and
        // prepare ParsedMessage versions needed.  Parsing is done before
        // attempting delivery to any recipient.  Therefore, parse error
        // will result in non-delivery to all recipients.
        // ParsedMessage for users with attachments indexing
        ParsedMessage pmAttachIndex = null;
        // ParsedMessage for users without attachments indexing
        ParsedMessage pmNoAttachIndex = null;
        // message id for logging
        String msgId = null;
        for (LmtpAddress recipient : recipients) {
            String rcptEmail = recipient.getEmailAddress();
            Account account;
            Mailbox mbox;
            boolean attachmentsIndexingEnabled;
            try {
                account = Provisioning.getInstance().get(AccountBy.name, rcptEmail);
                if (account == null) {
                    ZimbraLog.mailbox.warn("No account found delivering mail to " + rcptEmail);
                    continue;
                }
                mbox = MailboxManager.getInstance().getMailboxByAccount(account);
                if (mbox == null) {
                    ZimbraLog.mailbox.warn("No mailbox found delivering mail to " + rcptEmail);
                    continue;
                }
                attachmentsIndexingEnabled = mbox.attachmentsIndexingEnabled();
            } catch (ServiceException se) {
                if (se.isReceiversFault()) {
                    ZimbraLog.mailbox.info("Recoverable exception getting mailbox for " + rcptEmail, se);
                    rcptMap.put(recipient, new RecipientDetail(null, null, null, false, DeliveryAction.defer));
                } else {
                    ZimbraLog.mailbox.warn("Unrecoverable exception getting mailbox for " + rcptEmail, se);
                }
                continue;
            }
            if (account != null && mbox != null) {
                ParsedMessageOptions pmo;
                if (mm != null) {
                    pmo = new ParsedMessageOptions().setContent(mm).setDigest(blob.getDigest()).setSize(blob.getRawSize());
                } else {
                    pmo = new ParsedMessageOptions(blob, data);
                }
                ParsedMessage pm;
                if (attachmentsIndexingEnabled) {
                    if (pmAttachIndex == null) {
                        pmo.setAttachmentIndexing(true);
                        ZimbraLog.lmtp.debug("Creating ParsedMessage from %s with attachment indexing enabled", data == null ? "file" : "memory");
                        pmAttachIndex = new ParsedMessage(pmo);
                    }
                    pm = pmAttachIndex;
                } else {
                    if (pmNoAttachIndex == null) {
                        pmo.setAttachmentIndexing(false);
                        ZimbraLog.lmtp.debug("Creating ParsedMessage from %s with attachment indexing disabled", data == null ? "file" : "memory");
                        pmNoAttachIndex = new ParsedMessage(pmo);
                    }
                    pm = pmNoAttachIndex;
                }
                msgId = pm.getMessageID();
                if (account.isPrefMailLocalDeliveryDisabled()) {
                    ZimbraLog.lmtp.debug("Local delivery disabled for account %s", rcptEmail);
                    rcptMap.put(recipient, new RecipientDetail(account, mbox, pm, false, DeliveryAction.discard));
                    continue;
                }
                // For non-shared delivery (i.e. only one recipient),
                // always deliver regardless of backup mode.
                DeliveryAction da = DeliveryAction.deliver;
                boolean endSharedDelivery = false;
                if (shared) {
                    if (mbox.beginSharedDelivery()) {
                        endSharedDelivery = true;
                    } else {
                        // Skip delivery to mailboxes in backup mode.
                        da = DeliveryAction.defer;
                    }
                }
                rcptMap.put(recipient, new RecipientDetail(account, mbox, pm, endSharedDelivery, da));
                if (da == DeliveryAction.deliver) {
                    targetMailboxIds.add(mbox.getId());
                }
            }
        }
        ZimbraLog.removeAccountFromContext();
        if (ZimbraLog.lmtp.isInfoEnabled()) {
            ZimbraLog.lmtp.info("Delivering message: size=%s, nrcpts=%d, sender=%s, msgid=%s", env.getSize() == 0 ? "unspecified" : Integer.toString(env.getSize()) + " bytes", recipients.size(), env.getSender(), msgId == null ? "" : msgId);
        }
        DeliveryContext sharedDeliveryCtxt = new DeliveryContext(shared, targetMailboxIds);
        sharedDeliveryCtxt.setIncomingBlob(blob);
        // version each recipient needs.  Deliver!
        for (LmtpAddress recipient : recipients) {
            String rcptEmail = recipient.getEmailAddress();
            LmtpReply reply = LmtpReply.TEMPORARY_FAILURE;
            RecipientDetail rd = rcptMap.get(recipient);
            if (rd.account != null)
                ZimbraLog.addAccountNameToContext(rd.account.getName());
            if (rd.mbox != null)
                ZimbraLog.addMboxToContext(rd.mbox.getId());
            boolean success = false;
            try {
                if (rd != null) {
                    switch(rd.action) {
                        case discard:
                            ZimbraLog.lmtp.info("accepted and discarded message from=%s,to=%s: local delivery is disabled", envSender, rcptEmail);
                            if (rd.account.getPrefMailForwardingAddress() != null) {
                                // mail forwarding is set up
                                for (LmtpCallback callback : callbacks) {
                                    ZimbraLog.lmtp.debug("Executing callback %s", callback.getClass().getName());
                                    callback.forwardWithoutDelivery(rd.account, rd.mbox, envSender, rcptEmail, rd.pm);
                                }
                            }
                            reply = LmtpReply.DELIVERY_OK;
                            break;
                        case deliver:
                            Account account = rd.account;
                            Mailbox mbox = rd.mbox;
                            ParsedMessage pm = rd.pm;
                            List<ItemId> addedMessageIds = null;
                            ReentrantLock lock = mailboxDeliveryLocks.get(mbox.getId());
                            boolean acquiredLock;
                            try {
                                // Wait for the lock, up to the timeout
                                acquiredLock = lock.tryLock(LC.zimbra_mailbox_lock_timeout.intValue(), TimeUnit.SECONDS);
                            } catch (InterruptedException e) {
                                acquiredLock = false;
                            }
                            if (!acquiredLock) {
                                ZimbraLog.lmtp.info("try again for message from=%s,to=%s: another mail delivery in progress.", envSender, rcptEmail);
                                reply = LmtpReply.TEMPORARY_FAILURE;
                                break;
                            }
                            try {
                                if (dedupe(pm, mbox)) {
                                    // message was already delivered to this mailbox
                                    ZimbraLog.lmtp.info("Not delivering message with duplicate Message-ID %s", pm.getMessageID());
                                } else if (mbox.dedupeForSelfMsg(pm)) {
                                    ZimbraLog.mailbox.info("not delivering message, because it is a duplicate of sent message %s", pm.getMessageID());
                                } else if (recipient.getSkipFilters()) {
                                    msgId = pm.getMessageID();
                                    int folderId = Mailbox.ID_FOLDER_INBOX;
                                    if (recipient.getFolder() != null) {
                                        try {
                                            Folder folder = mbox.getFolderByPath(null, recipient.getFolder());
                                            folderId = folder.getId();
                                        } catch (ServiceException se) {
                                            if (se.getCode().equals(MailServiceException.NO_SUCH_FOLDER)) {
                                                Folder folder = mbox.createFolder(null, recipient.getFolder(), new Folder.FolderOptions().setDefaultView(MailItem.Type.MESSAGE));
                                                folderId = folder.getId();
                                            } else {
                                                throw se;
                                            }
                                        }
                                    }
                                    int flags = Flag.BITMASK_UNREAD;
                                    if (recipient.getFlags() != null) {
                                        flags = Flag.toBitmask(recipient.getFlags());
                                    }
                                    DeliveryOptions dopt = new DeliveryOptions().setFolderId(folderId);
                                    dopt.setFlags(flags).setTags(recipient.getTags()).setRecipientEmail(rcptEmail);
                                    Message msg = mbox.addMessage(null, pm, dopt, sharedDeliveryCtxt);
                                    addedMessageIds = Lists.newArrayList(new ItemId(msg));
                                } else if (!DebugConfig.disableIncomingFilter) {
                                    // Get msgid first, to avoid having to reopen and reparse the blob
                                    // file if Mailbox.addMessageInternal() closes it.
                                    pm.getMessageID();
                                    addedMessageIds = RuleManager.applyRulesToIncomingMessage(null, mbox, pm, (int) blob.getRawSize(), rcptEmail, env, sharedDeliveryCtxt, Mailbox.ID_FOLDER_INBOX, false, true);
                                } else {
                                    pm.getMessageID();
                                    DeliveryOptions dopt = new DeliveryOptions().setFolderId(Mailbox.ID_FOLDER_INBOX);
                                    dopt.setFlags(Flag.BITMASK_UNREAD).setRecipientEmail(rcptEmail);
                                    Message msg = mbox.addMessage(null, pm, dopt, sharedDeliveryCtxt);
                                    addedMessageIds = Lists.newArrayList(new ItemId(msg));
                                }
                                success = true;
                                if (addedMessageIds != null && addedMessageIds.size() > 0) {
                                    addToDedupeCache(pm, mbox);
                                }
                            } finally {
                                lock.unlock();
                            }
                            if (addedMessageIds != null && addedMessageIds.size() > 0) {
                                // Execute callbacks
                                for (LmtpCallback callback : callbacks) {
                                    for (ItemId id : addedMessageIds) {
                                        if (id.belongsTo(mbox)) {
                                            // Message was added to the local mailbox, as opposed to a mountpoint.
                                            ZimbraLog.lmtp.debug("Executing callback %s", callback.getClass().getName());
                                            try {
                                                Message msg = mbox.getMessageById(null, id.getId());
                                                callback.afterDelivery(account, mbox, envSender, rcptEmail, msg);
                                            } catch (Throwable t) {
                                                if (t instanceof OutOfMemoryError) {
                                                    Zimbra.halt("LMTP callback failed", t);
                                                } else {
                                                    ZimbraLog.lmtp.warn("LMTP callback threw an exception", t);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            reply = LmtpReply.DELIVERY_OK;
                            break;
                        case defer:
                            // Delivery to mailbox skipped.  Let MTA retry again later.
                            // This case happens for shared delivery to a mailbox in
                            // backup mode.
                            ZimbraLog.lmtp.info("try again for message from=%s,to=%s: mailbox skipped", envSender, rcptEmail);
                            reply = LmtpReply.TEMPORARY_FAILURE;
                            break;
                    }
                } else {
                    // Account or mailbox not found.
                    ZimbraLog.lmtp.info("rejecting message from=%s,to=%s: account or mailbox not found", envSender, rcptEmail);
                    reply = LmtpReply.PERMANENT_FAILURE;
                }
            } catch (DeliveryServiceException e) {
                ZimbraLog.lmtp.info("rejecting message from=%s,to=%s: sieve filter rule", envSender, rcptEmail);
                reply = LmtpReply.PERMANENT_MESSAGE_REFUSED;
            } catch (ServiceException e) {
                if (e.getCode().equals(MailServiceException.QUOTA_EXCEEDED)) {
                    ZimbraLog.lmtp.info("rejecting message from=%s,to=%s: overquota", envSender, rcptEmail);
                    if (config.isPermanentFailureWhenOverQuota()) {
                        reply = LmtpReply.PERMANENT_FAILURE_OVER_QUOTA;
                    } else {
                        reply = LmtpReply.TEMPORARY_FAILURE_OVER_QUOTA;
                    }
                } else if (e.isReceiversFault()) {
                    ZimbraLog.lmtp.info("try again for message from=%s,to=%s", envSender, rcptEmail, e);
                    reply = LmtpReply.TEMPORARY_FAILURE;
                } else {
                    ZimbraLog.lmtp.info("rejecting message from=%s,to=%s", envSender, rcptEmail, e);
                    reply = LmtpReply.PERMANENT_FAILURE;
                }
            } catch (Exception e) {
                reply = LmtpReply.TEMPORARY_FAILURE;
                ZimbraLog.lmtp.warn("try again for message from=%s,to=%s", envSender, rcptEmail, e);
            } finally {
                if (rd.action == DeliveryAction.deliver && !success) {
                    // Message was not delivered.  Remove it from the dedupe
                    // cache so we don't dedupe it on LMTP retry.
                    removeFromDedupeCache(msgId, rd.mbox);
                }
                recipient.setDeliveryStatus(reply);
                if (shared && rd != null && rd.esd) {
                    rd.mbox.endSharedDelivery();
                    rd.esd = false;
                }
            }
        }
        // If this message is being streamed from disk, cache it
        ParsedMessage mimeSource = pmAttachIndex != null ? pmAttachIndex : pmNoAttachIndex;
        MailboxBlob mblob = sharedDeliveryCtxt.getMailboxBlob();
        if (mblob != null && mimeSource != null) {
            if (bis == null) {
                bis = mimeSource.getBlobInputStream();
            }
            if (bis != null) {
                try {
                    // Update the MimeMessage with the blob that's stored inside the mailbox,
                    // since the incoming blob will be deleted.
                    Blob storedBlob = mblob.getLocalBlob();
                    bis.fileMoved(storedBlob.getFile());
                    MessageCache.cacheMessage(mblob.getDigest(), mimeSource.getOriginalMessage(), mimeSource.getMimeMessage());
                } catch (IOException e) {
                    ZimbraLog.lmtp.warn("Unable to cache message for " + mblob, e);
                }
            }
        }
    } finally {
        // called, we check and fix those here.
        if (shared) {
            for (RecipientDetail rd : rcptMap.values()) {
                if (rd.esd && rd.mbox != null)
                    rd.mbox.endSharedDelivery();
            }
        }
    }
}
Also used : Account(com.zimbra.cs.account.Account) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) Message(com.zimbra.cs.mailbox.Message) MimeMessage(javax.mail.internet.MimeMessage) HashMap(java.util.HashMap) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) Folder(com.zimbra.cs.mailbox.Folder) ItemId(com.zimbra.cs.service.util.ItemId) DeliveryServiceException(com.zimbra.common.service.DeliveryServiceException) Mailbox(com.zimbra.cs.mailbox.Mailbox) DeliveryContext(com.zimbra.cs.mailbox.DeliveryContext) DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Blob(com.zimbra.cs.store.Blob) MailboxBlob(com.zimbra.cs.store.MailboxBlob) ParsedMessageOptions(com.zimbra.cs.mime.ParsedMessageOptions) MailboxBlob(com.zimbra.cs.store.MailboxBlob) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) IOException(java.io.IOException) MessagingException(javax.mail.MessagingException) LmtpProtocolException(com.zimbra.common.lmtp.LmtpProtocolException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) DeliveryServiceException(com.zimbra.common.service.DeliveryServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ServiceException(com.zimbra.common.service.ServiceException) DeliveryServiceException(com.zimbra.common.service.DeliveryServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException)

Example 27 with DeliveryOptions

use of com.zimbra.cs.mailbox.DeliveryOptions in project zm-mailbox by Zimbra.

the class AppendMessage method store.

private int store(Mailbox mbox, Folder folder) throws ImapSessionClosedException, ServiceException, IOException {
    boolean idxAttach = mbox.attachmentsIndexingEnabled();
    Long receivedDate = date != null ? date.getTime() : null;
    ParsedMessage pm = new ParsedMessage(content, receivedDate, idxAttach);
    try {
        if (!pm.getSender().isEmpty()) {
            InternetAddress ia = new JavaMailInternetAddress(pm.getSender());
            if (AccountUtil.addressMatchesAccountOrSendAs(mbox.getAccount(), ia.getAddress())) {
                flags |= Flag.BITMASK_FROM_ME;
            }
        }
    } catch (Exception e) {
    }
    DeliveryOptions dopt = new DeliveryOptions().setFolderId(folder).setNoICal(true).setFlags(flags).setTags(tags);
    Message msg = mbox.addMessage(handler.getContext(), pm, dopt, null);
    if (msg != null && sflags != 0 && handler.getState() == ImapHandler.State.SELECTED) {
        ImapFolder selectedFolder = handler.getSelectedFolder();
        //   (note that this leaves session flags unset on remote appended messages)
        if (selectedFolder != null) {
            ImapMessage i4msg = selectedFolder.getById(msg.getId());
            if (i4msg != null) {
                i4msg.setSessionFlags(sflags, selectedFolder);
            }
        }
    }
    return msg == null ? -1 : msg.getId();
}
Also used : InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) Message(com.zimbra.cs.mailbox.Message) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions) MessagingException(javax.mail.MessagingException) ServiceException(com.zimbra.common.service.ServiceException) ParseException(java.text.ParseException) IOException(java.io.IOException)

Example 28 with DeliveryOptions

use of com.zimbra.cs.mailbox.DeliveryOptions in project zm-mailbox by Zimbra.

the class RemoveAttachments method removeAttachmentOperation.

public static Message removeAttachmentOperation(Mailbox mbox, OperationContext octxt, ParsedMessage pm, Message msg) throws IOException, ServiceException {
    if (msg.isDraft()) {
        msg = mbox.saveDraft(octxt, pm, msg.getId());
    } else {
        int itemId = msg.getId();
        DeliveryOptions dopt = new DeliveryOptions();
        dopt.setFolderId(msg.getFolderId()).setNoICal(true);
        dopt.setFlags(msg.getFlagBitmask()).setTags(msg.getTags());
        if (msg.getConversationId() > 0)
            dopt.setConversationId(msg.getConversationId());
        msg = mbox.addMessage(octxt, pm, dopt, null);
        // Activesync fails to add new mail_item as it has all the details of old mail_item, so it considers it as a change in mail_item Bug:102084
        // Hence, set previous folder field to the mail_item with dummy folder, because of which activesync code thinks it is moved item and adds it on device.
        String prevFolders = msg.getModifiedSequence() + ":" + Mailbox.ID_FOLDER_USER_ROOT;
        mbox.setPreviousFolder(octxt, msg.getId(), prevFolders);
        msg.getUnderlyingData().setPrevFolders(prevFolders);
        // and clean up the existing message...
        mbox.delete(octxt, itemId, MailItem.Type.MESSAGE);
    }
    return msg;
}
Also used : DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions)

Example 29 with DeliveryOptions

use of com.zimbra.cs.mailbox.DeliveryOptions in project zm-mailbox by Zimbra.

the class ArchiveFormatter method addItem.

private void addItem(UserServletContext context, Folder fldr, Map<Object, Folder> fmap, FolderDigestInfo digestInfo, Map<Integer, Integer> idMap, int[] ids, Set<MailItem.Type> types, Resolve r, ItemData id, ArchiveInputStream ais, ArchiveInputEntry aie, List<ServiceException> errs) throws ServiceException {
    try {
        Mailbox mbox = fldr.getMailbox();
        MailItem mi = MailItem.constructItem(mbox, id.ud);
        MailItem newItem = null, oldItem = null;
        OperationContext octxt = context.opContext;
        String path;
        ParsedMessage pm;
        boolean root = fldr.getId() == Mailbox.ID_FOLDER_ROOT || fldr.getId() == Mailbox.ID_FOLDER_USER_ROOT || id.path.startsWith(fldr.getPath() + '/');
        if ((ids != null && Arrays.binarySearch(ids, id.ud.id) < 0) || (types != null && !types.contains(MailItem.Type.of(id.ud.type))))
            return;
        if (id.ud.getBlobDigest() != null && aie == null) {
            addError(errs, FormatterServiceException.MISSING_BLOB(id.path));
            return;
        }
        if (root) {
            path = id.path;
        } else {
            path = fldr.getPath() + id.path;
        }
        if (path.endsWith("/") && !path.equals("/")) {
            path = path.substring(0, path.length() - 1);
        }
        if (mbox.isImmutableSystemFolder(id.ud.folderId))
            return;
        switch(mi.getType()) {
            case APPOINTMENT:
            case TASK:
                CalendarItem ci = (CalendarItem) mi;
                fldr = createPath(context, fmap, path, ci.getType() == MailItem.Type.APPOINTMENT ? MailItem.Type.APPOINTMENT : MailItem.Type.TASK);
                if (!root || r != Resolve.Reset) {
                    CalendarItem oldCI = null;
                    try {
                        oldCI = mbox.getCalendarItemByUid(octxt, ci.getUid());
                    } catch (Exception e) {
                    }
                    if (oldCI != null && r == Resolve.Replace) {
                        mbox.delete(octxt, oldCI.getId(), oldCI.getType());
                    } else {
                        oldItem = oldCI;
                    }
                }
                if (oldItem == null || r != Resolve.Skip) {
                    CalendarItem.AlarmData ad = ci.getAlarmData();
                    byte[] data = readArchiveEntry(ais, aie);
                    Map<Integer, MimeMessage> blobMimeMsgMap = data == null ? null : CalendarItem.decomposeBlob(data);
                    SetCalendarItemData defScid = new SetCalendarItemData();
                    SetCalendarItemData[] exceptionScids = null;
                    Invite[] invs = ci.getInvites();
                    MimeMessage mm;
                    if (invs != null && invs.length > 0) {
                        defScid.invite = invs[0];
                        if (blobMimeMsgMap != null && (mm = blobMimeMsgMap.get(defScid.invite.getMailItemId())) != null) {
                            defScid.message = new ParsedMessage(mm, mbox.attachmentsIndexingEnabled());
                        }
                        if (invs.length > 1) {
                            exceptionScids = new SetCalendarItemData[invs.length - 1];
                            for (int i = 1; i < invs.length; i++) {
                                SetCalendarItemData scid = new SetCalendarItemData();
                                scid.invite = invs[i];
                                if (blobMimeMsgMap != null && (mm = blobMimeMsgMap.get(defScid.invite.getMailItemId())) != null) {
                                    scid.message = new ParsedMessage(mm, mbox.attachmentsIndexingEnabled());
                                }
                                exceptionScids[i - 1] = scid;
                            }
                        }
                        newItem = mbox.setCalendarItem(octxt, oldItem != null && r == Resolve.Modify ? oldItem.getFolderId() : fldr.getId(), ci.getFlagBitmask(), ci.getTags(), defScid, exceptionScids, ci.getAllReplies(), ad == null ? CalendarItem.NEXT_ALARM_KEEP_CURRENT : ad.getNextAt());
                    }
                }
                break;
            case CHAT:
                Chat chat = (Chat) mi;
                byte[] content = readArchiveEntry(ais, aie);
                pm = new ParsedMessage(content, mi.getDate(), mbox.attachmentsIndexingEnabled());
                fldr = createPath(context, fmap, path, MailItem.Type.CHAT);
                if (root && r != Resolve.Reset) {
                    Chat oldChat = null;
                    try {
                        oldChat = mbox.getChatById(octxt, chat.getId());
                        if (oldChat.getFolderId() != fldr.getId()) {
                            oldChat = null;
                        }
                    } catch (Exception e) {
                    }
                    if (oldChat != null && chat.getSender().equals(oldChat.getSender()) && chat.getSubject().equals(oldChat.getSubject())) {
                        if (r == Resolve.Replace) {
                            mbox.delete(octxt, oldChat.getId(), oldChat.getType());
                        } else {
                            oldItem = oldChat;
                            if (r == Resolve.Modify)
                                newItem = mbox.updateChat(octxt, pm, oldItem.getId());
                        }
                    }
                }
                if (oldItem == null)
                    newItem = mbox.createChat(octxt, pm, fldr.getId(), chat.getFlagBitmask(), chat.getTags());
                break;
            case CONVERSATION:
                Conversation cv = (Conversation) mi;
                if (r != Resolve.Reset && r != Resolve.Skip) {
                    try {
                        oldItem = mbox.getConversationByHash(octxt, Mailbox.getHash(cv.getSubject()));
                    } catch (Exception e) {
                    }
                }
                break;
            case CONTACT:
                Contact ct = (Contact) mi;
                fldr = createPath(context, fmap, path, Folder.Type.CONTACT);
                if (root && r != Resolve.Reset) {
                    Contact oldContact = null;
                    oldContact = findContact(octxt, mbox, ct, fldr);
                    if (oldContact != null) {
                        String email = string(ct.get(ContactConstants.A_email));
                        String first = string(ct.get(ContactConstants.A_firstName));
                        String name = string(ct.get(ContactConstants.A_fullName));
                        String oldemail = string(oldContact.get(ContactConstants.A_email));
                        String oldfirst = string(oldContact.get(ContactConstants.A_firstName));
                        String oldname = string(oldContact.get(ContactConstants.A_fullName));
                        if (email.equals(oldemail) && first.equals(oldfirst) && name.equals(oldname)) {
                            if (r == Resolve.Replace) {
                                mbox.delete(octxt, oldContact.getId(), oldContact.getType());
                            } else {
                                oldItem = oldContact;
                                if (r == Resolve.Modify) {
                                    mbox.modifyContact(octxt, oldItem.getId(), new ParsedContact(ct.getFields(), readArchiveEntry(ais, aie)));
                                }
                            }
                        }
                    }
                }
                if (oldItem == null) {
                    newItem = mbox.createContact(octxt, new ParsedContact(ct.getFields(), readArchiveEntry(ais, aie)), fldr.getId(), ct.getTags());
                }
                break;
            case DOCUMENT:
            case WIKI:
                Document doc = (Document) mi;
                Document oldDoc = null;
                Integer oldId = idMap.get(mi.getId());
                fldr = createParent(context, fmap, path, doc.getType() == MailItem.Type.DOCUMENT ? MailItem.Type.DOCUMENT : MailItem.Type.WIKI);
                if (oldId == null) {
                    try {
                        for (Document listDoc : mbox.getDocumentList(octxt, fldr.getId())) {
                            if (doc.getName().equals(listDoc.getName())) {
                                oldDoc = listDoc;
                                idMap.put(doc.getId(), oldDoc.getId());
                                break;
                            }
                        }
                    } catch (Exception e) {
                    }
                } else {
                    oldDoc = mbox.getDocumentById(octxt, oldId);
                }
                if (oldDoc != null) {
                    if (r == Resolve.Replace && oldId == null) {
                        mbox.delete(octxt, oldDoc.getId(), oldDoc.getType());
                    } else if (doc.getVersion() < oldDoc.getVersion()) {
                        return;
                    } else {
                        oldItem = oldDoc;
                        if (doc.getVersion() > oldDoc.getVersion()) {
                            newItem = mbox.addDocumentRevision(octxt, oldDoc.getId(), doc.getCreator(), doc.getName(), doc.getDescription(), doc.isDescriptionEnabled(), ais.getInputStream());
                        }
                        if (r != Resolve.Skip) {
                            mbox.setDate(octxt, oldDoc.getId(), doc.getType(), doc.getDate());
                        }
                    }
                }
                if (oldItem == null) {
                    if (mi.getType() == MailItem.Type.DOCUMENT) {
                        newItem = mbox.createDocument(octxt, fldr.getId(), doc.getName(), doc.getContentType(), doc.getCreator(), doc.getDescription(), ais.getInputStream());
                    } else {
                        WikiItem wi = (WikiItem) mi;
                        newItem = mbox.createWiki(octxt, fldr.getId(), wi.getWikiWord(), wi.getCreator(), wi.getDescription(), ais.getInputStream());
                    }
                    mbox.setDate(octxt, newItem.getId(), doc.getType(), doc.getDate());
                    idMap.put(doc.getId(), newItem.getId());
                }
                break;
            case FLAG:
                return;
            case FOLDER:
                String aclParam = context.params.get("acl");
                boolean doACL = aclParam == null || !aclParam.equals("0");
                Folder f = (Folder) mi;
                ACL acl = f.getACL();
                Folder oldF = null;
                MailItem.Type view = f.getDefaultView();
                if (view == MailItem.Type.CONVERSATION || view == MailItem.Type.FLAG || view == MailItem.Type.TAG)
                    break;
                try {
                    oldF = mbox.getFolderByPath(octxt, path);
                } catch (Exception e) {
                }
                if (oldF != null) {
                    oldItem = oldF;
                    if (r != Resolve.Skip) {
                        if (!f.getUrl().equals(oldF.getUrl())) {
                            mbox.setFolderUrl(octxt, oldF.getId(), f.getUrl());
                        }
                        if (doACL) {
                            ACL oldACL = oldF.getACL();
                            if ((acl == null && oldACL != null) || (acl != null && (oldACL == null || !acl.equals(oldACL)))) {
                                mbox.setPermissions(octxt, oldF.getId(), acl);
                            }
                        }
                    }
                }
                if (oldItem == null) {
                    fldr = createParent(context, fmap, path, Folder.Type.UNKNOWN);
                    Folder.FolderOptions fopt = new Folder.FolderOptions();
                    fopt.setDefaultView(f.getDefaultView()).setFlags(f.getFlagBitmask()).setColor(f.getColor()).setUrl(f.getUrl());
                    newItem = fldr = mbox.createFolder(octxt, f.getName(), fldr.getId(), fopt);
                    if (doACL && acl != null) {
                        mbox.setPermissions(octxt, fldr.getId(), acl);
                    }
                    fmap.put(fldr.getId(), fldr);
                    fmap.put(fldr.getPath(), fldr);
                }
                break;
            case MESSAGE:
                Message msg = (Message) mi;
                Message oldMsg = null;
                fldr = createPath(context, fmap, path, Folder.Type.MESSAGE);
                if (root && r != Resolve.Reset) {
                    try {
                        oldMsg = mbox.getMessageById(octxt, msg.getId());
                        if (!msg.getDigest().equals(oldMsg.getDigest()) || oldMsg.getFolderId() != fldr.getId()) {
                            oldMsg = null;
                        }
                    } catch (Exception e) {
                    }
                }
                if (oldMsg == null) {
                    Integer digestId = digestInfo.getIdForDigest(fldr, mi.getDigest());
                    if (digestId != null) {
                        oldMsg = mbox.getMessageById(octxt, digestId);
                        if (!msg.getDigest().equals(oldMsg.getDigest())) {
                            oldMsg = null;
                        }
                    }
                }
                if (oldMsg != null) {
                    if (r == Resolve.Replace) {
                        ZimbraLog.misc.debug("Deleting old msg with id=%s as has same digest='%s'", oldMsg.getId(), mi.getDigest());
                        mbox.delete(octxt, oldMsg.getId(), oldMsg.getType());
                    } else {
                        oldItem = oldMsg;
                    }
                }
                if (oldItem != null) {
                    ZimbraLog.misc.debug("Message with id=%s has same digest='%s' - not re-adding", oldItem.getId(), mi.getDigest());
                } else {
                    DeliveryOptions opt = new DeliveryOptions().setFolderId(fldr.getId()).setNoICal(true).setFlags(msg.getFlagBitmask()).setTags(msg.getTags());
                    newItem = mbox.addMessage(octxt, ais.getInputStream(), (int) aie.getSize(), msg.getDate(), opt, null, id);
                }
                break;
            case MOUNTPOINT:
                Mountpoint mp = (Mountpoint) mi;
                MailItem oldMP = null;
                try {
                    oldMP = mbox.getItemByPath(octxt, path);
                    if (oldMP.getType() == mi.getType()) {
                        oldMP = null;
                    }
                } catch (Exception e) {
                }
                if (oldMP != null) {
                    if (r == Resolve.Modify || r == Resolve.Replace) {
                        mbox.delete(octxt, oldMP.getId(), oldMP.getType());
                    } else {
                        oldItem = oldMP;
                    }
                }
                if (oldItem == null) {
                    fldr = createParent(context, fmap, path, Folder.Type.UNKNOWN);
                    newItem = mbox.createMountpoint(context.opContext, fldr.getId(), mp.getName(), mp.getOwnerId(), mp.getRemoteId(), mp.getRemoteUuid(), mp.getDefaultView(), mp.getFlagBitmask(), mp.getColor(), mp.isReminderEnabled());
                }
                break;
            case NOTE:
                Note note = (Note) mi;
                Note oldNote = null;
                fldr = createPath(context, fmap, path, MailItem.Type.NOTE);
                try {
                    for (Note listNote : mbox.getNoteList(octxt, fldr.getId())) {
                        if (note.getSubject().equals(listNote.getSubject())) {
                            oldNote = listNote;
                            break;
                        }
                    }
                } catch (Exception e) {
                }
                if (oldNote != null) {
                    if (r == Resolve.Replace) {
                        mbox.delete(octxt, oldNote.getId(), oldNote.getType());
                    } else {
                        oldItem = oldNote;
                        if (r == Resolve.Modify) {
                            mbox.editNote(octxt, oldItem.getId(), new String(readArchiveEntry(ais, aie), UTF8));
                        }
                    }
                    break;
                }
                if (oldItem == null) {
                    newItem = mbox.createNote(octxt, new String(readArchiveEntry(ais, aie), UTF8), note.getBounds(), note.getColor(), fldr.getId());
                }
                break;
            case SEARCHFOLDER:
                SearchFolder sf = (SearchFolder) mi;
                MailItem oldSF = null;
                try {
                    oldSF = mbox.getItemByPath(octxt, path);
                    if (oldSF.getType() == mi.getType()) {
                        oldSF = null;
                    }
                } catch (Exception e) {
                }
                if (oldSF != null) {
                    if (r == Resolve.Modify) {
                        mbox.modifySearchFolder(octxt, oldSF.getId(), sf.getQuery(), sf.getReturnTypes(), sf.getSortField());
                    } else if (r == Resolve.Replace) {
                        mbox.delete(octxt, oldSF.getId(), oldSF.getType());
                    } else {
                        oldItem = oldSF;
                    }
                }
                if (oldItem == null) {
                    fldr = createParent(context, fmap, path, MailItem.Type.UNKNOWN);
                    newItem = mbox.createSearchFolder(octxt, fldr.getId(), sf.getName(), sf.getQuery(), sf.getReturnTypes(), sf.getSortField(), sf.getFlagBitmask(), sf.getColor());
                }
                break;
            case TAG:
                Tag tag = (Tag) mi;
                try {
                    Tag oldTag = mbox.getTagByName(octxt, tag.getName());
                    oldItem = oldTag;
                } catch (Exception e) {
                }
                if (oldItem == null) {
                    newItem = mbox.createTag(octxt, tag.getName(), tag.getColor());
                }
                break;
            case VIRTUAL_CONVERSATION:
                return;
        }
        if (newItem != null) {
            if (mi.getColor() != newItem.getColor()) {
                mbox.setColor(octxt, newItem.getId(), newItem.getType(), mi.getColor());
            }
            if (!id.flags.equals(newItem.getFlagString()) || !id.tagsEqual(newItem)) {
                mbox.setTags(octxt, newItem.getId(), newItem.getType(), Flag.toBitmask(id.flags), getTagNames(id), null);
            }
        } else if (oldItem != null && r == Resolve.Modify) {
            if (mi.getColor() != oldItem.getColor()) {
                mbox.setColor(octxt, oldItem.getId(), oldItem.getType(), mi.getColor());
            }
            if (!id.flags.equals(oldItem.getFlagString()) || !id.tagsEqual(oldItem)) {
                mbox.setTags(octxt, oldItem.getId(), oldItem.getType(), Flag.toBitmask(id.flags), getTagNames(id), null);
            }
        }
    } catch (MailServiceException e) {
        if (e.getCode() == MailServiceException.QUOTA_EXCEEDED) {
            throw e;
        } else if (r != Resolve.Skip || e.getCode() != MailServiceException.ALREADY_EXISTS) {
            addError(errs, e);
        }
    } catch (Exception e) {
        String path = id.path;
        // When importing items into, e.g. the Inbox, often path is just "/Inbox" which isn't that useful
        if ((aie != null) && !Strings.isNullOrEmpty(aie.getName())) {
            path = aie.getName();
        }
        addError(errs, FormatterServiceException.UNKNOWN_ERROR(path, e));
    }
}
Also used : MimeMessage(javax.mail.internet.MimeMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) Message(com.zimbra.cs.mailbox.Message) Conversation(com.zimbra.cs.mailbox.Conversation) Document(com.zimbra.cs.mailbox.Document) SearchFolder(com.zimbra.cs.mailbox.SearchFolder) Folder(com.zimbra.cs.mailbox.Folder) SetCalendarItemData(com.zimbra.cs.mailbox.Mailbox.SetCalendarItemData) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) ParsedContact(com.zimbra.cs.mime.ParsedContact) Mailbox(com.zimbra.cs.mailbox.Mailbox) MimeMessage(javax.mail.internet.MimeMessage) Chat(com.zimbra.cs.mailbox.Chat) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) OperationContext(com.zimbra.cs.mailbox.OperationContext) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) SearchFolder(com.zimbra.cs.mailbox.SearchFolder) ACL(com.zimbra.cs.mailbox.ACL) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ExportPeriodNotSpecifiedException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodNotSpecifiedException) ServiceException(com.zimbra.common.service.ServiceException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ExportPeriodTooLongException(com.zimbra.cs.mailbox.MailServiceException.ExportPeriodTooLongException) UserServletException(com.zimbra.cs.service.UserServletException) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) ParsedContact(com.zimbra.cs.mime.ParsedContact) Contact(com.zimbra.cs.mailbox.Contact) MailItem(com.zimbra.cs.mailbox.MailItem) WikiItem(com.zimbra.cs.mailbox.WikiItem) Note(com.zimbra.cs.mailbox.Note) Tag(com.zimbra.cs.mailbox.Tag) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 30 with DeliveryOptions

use of com.zimbra.cs.mailbox.DeliveryOptions in project zm-mailbox by Zimbra.

the class NativeFormatter method saveCallback.

@Override
public void saveCallback(UserServletContext context, String contentType, Folder folder, String filename) throws IOException, ServiceException, UserServletException {
    if (filename == null) {
        Mailbox mbox = folder.getMailbox();
        try {
            ParsedMessage pm = new ParsedMessage(context.getPostBody(), mbox.attachmentsIndexingEnabled());
            DeliveryOptions dopt = new DeliveryOptions().setFolderId(folder).setNoICal(true);
            mbox.addMessage(context.opContext, pm, dopt, null);
            return;
        } catch (ServiceException e) {
            throw new UserServletException(HttpServletResponse.SC_BAD_REQUEST, "error parsing message");
        }
    }
    InputStream is = context.getRequestInputStream();
    try {
        Blob blob = StoreManager.getInstance().storeIncoming(is);
        saveDocument(blob, context, contentType, folder, filename, is);
    } finally {
        is.close();
    }
}
Also used : Blob(com.zimbra.cs.store.Blob) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) UserServletException(com.zimbra.cs.service.UserServletException) PushbackInputStream(java.io.PushbackInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) MemoryCacheImageInputStream(javax.imageio.stream.MemoryCacheImageInputStream) InputStream(java.io.InputStream) DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions)

Aggregations

DeliveryOptions (com.zimbra.cs.mailbox.DeliveryOptions)59 Mailbox (com.zimbra.cs.mailbox.Mailbox)50 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)46 Message (com.zimbra.cs.mailbox.Message)45 Test (org.junit.Test)44 Account (com.zimbra.cs.account.Account)18 OperationContext (com.zimbra.cs.mailbox.OperationContext)14 MimeMessage (javax.mail.internet.MimeMessage)12 ItemId (com.zimbra.cs.service.util.ItemId)11 Volume (com.zimbra.cs.volume.Volume)11 ServiceException (com.zimbra.common.service.ServiceException)10 Element (com.zimbra.common.soap.Element)9 IOException (java.io.IOException)9 Folder (com.zimbra.cs.mailbox.Folder)7 BlobReference (com.zimbra.cs.store.file.BlobReference)7 DeliveryContext (com.zimbra.cs.mailbox.DeliveryContext)6 ZMimeMessage (com.zimbra.common.zmime.ZMimeMessage)5 MailItem (com.zimbra.cs.mailbox.MailItem)5 MailboxBlobInfo (com.zimbra.cs.store.MailboxBlob.MailboxBlobInfo)5 BlobConsistencyChecker (com.zimbra.cs.store.file.BlobConsistencyChecker)5