Search in sources :

Example 6 with MailboxBlob

use of com.zimbra.cs.store.MailboxBlob 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 7 with MailboxBlob

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

the class Mailbox method createDocument.

public Document createDocument(OperationContext octxt, int folderId, ParsedDocument pd, MailItem.Type type, int flags, MailItem parent, CustomMetadata custom, boolean indexing) throws IOException, ServiceException {
    StoreManager sm = StoreManager.getInstance();
    StagedBlob staged = sm.stage(pd.getBlob(), this);
    SaveDocument redoRecorder = new SaveDocument(mId, pd.getDigest(), pd.getSize(), folderId, flags);
    boolean success = false;
    try {
        long start = System.currentTimeMillis();
        beginTransaction("createDoc", octxt, redoRecorder);
        SaveDocument redoPlayer = (octxt == null ? null : (SaveDocument) octxt.getPlayer());
        int itemId = getNextItemId(redoPlayer == null ? ID_AUTO_INCREMENT : redoPlayer.getMessageId());
        String uuid = redoPlayer == null ? UUIDUtil.generateUUID() : redoPlayer.getUuid();
        Document doc;
        switch(type) {
            case DOCUMENT:
                doc = Document.create(itemId, uuid, getFolderById(folderId), pd.getFilename(), pd.getContentType(), pd, custom, flags, parent);
                break;
            case WIKI:
                doc = WikiItem.create(itemId, uuid, getFolderById(folderId), pd.getFilename(), pd, null);
                break;
            default:
                throw MailServiceException.INVALID_TYPE(type.toString());
        }
        redoRecorder.setMessageId(itemId);
        redoRecorder.setUuid(doc.getUuid());
        redoRecorder.setDocument(pd);
        redoRecorder.setItemType(type);
        redoRecorder.setDescription(pd.getDescription());
        redoRecorder.setFlags(doc.getFlagBitmask());
        // Get the redolog data from the mailbox blob.  This is less than ideal in the
        // HTTP store case because it will result in network access, and possibly an
        // extra write to local disk.  If this becomes a problem, we should update the
        // ParsedDocument constructor to take a DataSource instead of an InputStream.
        MailboxBlob mailboxBlob = doc.setContent(staged, pd);
        redoRecorder.setMessageBodyInfo(new MailboxBlobDataSource(mailboxBlob), mailboxBlob.getSize());
        if (indexing) {
            index.add(doc);
        }
        success = true;
        long elapsed = System.currentTimeMillis() - start;
        ZimbraLog.mailbox.debug("createDocument elapsed=" + elapsed);
        return doc;
    } catch (IOException ioe) {
        throw ServiceException.FAILURE("error writing document blob", ioe);
    } finally {
        endTransaction(success);
        sm.quietDelete(staged);
    }
}
Also used : StagedBlob(com.zimbra.cs.store.StagedBlob) MailboxBlob(com.zimbra.cs.store.MailboxBlob) MailboxBlobDataSource(com.zimbra.cs.store.MailboxBlobDataSource) SaveDocument(com.zimbra.cs.redolog.op.SaveDocument) IOException(java.io.IOException) ParsedDocument(com.zimbra.cs.mime.ParsedDocument) IndexDocument(com.zimbra.cs.index.IndexDocument) SaveDocument(com.zimbra.cs.redolog.op.SaveDocument) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) StoreManager(com.zimbra.cs.store.StoreManager)

Example 8 with MailboxBlob

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

the class Mailbox method createContact.

public Contact createContact(OperationContext octxt, ParsedContact pc, int folderId, String[] tags) throws ServiceException {
    StoreManager sm = StoreManager.getInstance();
    StagedBlob staged = null;
    if (pc.hasAttachment()) {
        // write the contact content directly to the mailbox's blob staging area
        InputStream is = null;
        try {
            staged = sm.stage(is = pc.getContentStream(), (int) pc.getSize(), this);
        } catch (IOException ioe) {
            throw ServiceException.FAILURE("could not save contact blob", ioe);
        } finally {
            ByteUtil.closeStream(is);
        }
    }
    CreateContact redoRecorder = new CreateContact(mId, folderId, pc, tags);
    boolean success = false;
    try {
        beginTransaction("createContact", octxt, redoRecorder);
        CreateContact redoPlayer = (CreateContact) currentChange().getRedoPlayer();
        boolean isRedo = redoPlayer != null;
        Tag.NormalizedTags ntags = new Tag.NormalizedTags(this, tags);
        int contactId = getNextItemId(isRedo ? redoPlayer.getContactId() : ID_AUTO_INCREMENT);
        MailboxBlob mblob = null;
        if (pc.hasAttachment()) {
            try {
                mblob = sm.renameTo(staged, this, contactId, getOperationChangeID());
                markOtherItemDirty(mblob);
            } catch (IOException ioe) {
                throw ServiceException.FAILURE("could not save contact blob", ioe);
            }
        }
        int flags = 0;
        Contact con = Contact.create(contactId, getFolderById(folderId), mblob, pc, flags, ntags, null);
        redoRecorder.setContactId(contactId);
        index.add(con);
        success = true;
        return con;
    } finally {
        endTransaction(success);
        sm.quietDelete(staged);
    }
}
Also used : StagedBlob(com.zimbra.cs.store.StagedBlob) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) MailboxBlob(com.zimbra.cs.store.MailboxBlob) Rfc822ValidationInputStream(com.zimbra.common.mime.Rfc822ValidationInputStream) CopyInputStream(com.zimbra.common.util.CopyInputStream) InputStream(java.io.InputStream) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) CreateContact(com.zimbra.cs.redolog.op.CreateContact) IOException(java.io.IOException) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) StoreManager(com.zimbra.cs.store.StoreManager) ModifyContact(com.zimbra.cs.redolog.op.ModifyContact) ParsedContact(com.zimbra.cs.mime.ParsedContact) CreateContact(com.zimbra.cs.redolog.op.CreateContact)

Example 9 with MailboxBlob

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

the class Mailbox method createChat.

public Chat createChat(OperationContext octxt, ParsedMessage pm, int folderId, int flags, String[] tags) throws IOException, ServiceException {
    if (pm == null) {
        throw ServiceException.INVALID_REQUEST("null ParsedMessage when adding chat to mailbox " + mId, null);
    }
    // write the chat content directly to the mailbox's blob staging area
    StoreManager sm = StoreManager.getInstance();
    StagedBlob staged;
    InputStream is = pm.getRawInputStream();
    try {
        staged = sm.stage(is, this);
    } finally {
        ByteUtil.closeStream(is);
    }
    String digest = staged.getDigest();
    int size = (int) staged.getSize();
    CreateChat redoRecorder = new CreateChat(mId, digest, size, folderId, flags, tags);
    boolean success = false;
    try {
        beginTransaction("createChat", octxt, redoRecorder);
        Tag.NormalizedTags ntags = new Tag.NormalizedTags(this, tags);
        CreateChat redoPlayer = (octxt == null ? null : (CreateChat) octxt.getPlayer());
        redoRecorder.setMessageBodyInfo(new ParsedMessageDataSource(pm), size);
        int itemId = getNextItemId(redoPlayer == null ? ID_AUTO_INCREMENT : redoPlayer.getMessageId());
        Chat chat = Chat.create(itemId, getFolderById(folderId), pm, staged, false, flags, ntags);
        redoRecorder.setMessageId(chat.getId());
        MailboxBlob mblob = sm.link(staged, this, itemId, getOperationChangeID());
        markOtherItemDirty(mblob);
        // when we created the Chat, we used the staged locator/size/digest;
        //   make sure that data actually matches the final blob in the store
        chat.updateBlobData(mblob);
        index.add(chat);
        success = true;
        return chat;
    } finally {
        endTransaction(success);
        sm.quietDelete(staged);
    }
}
Also used : StagedBlob(com.zimbra.cs.store.StagedBlob) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) MailboxBlob(com.zimbra.cs.store.MailboxBlob) Rfc822ValidationInputStream(com.zimbra.common.mime.Rfc822ValidationInputStream) CopyInputStream(com.zimbra.common.util.CopyInputStream) InputStream(java.io.InputStream) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint) StoreManager(com.zimbra.cs.store.StoreManager) ParsedMessageDataSource(com.zimbra.cs.mime.ParsedMessageDataSource) CreateChat(com.zimbra.cs.redolog.op.CreateChat) NormalizedTags(com.zimbra.cs.mailbox.Tag.NormalizedTags) SaveChat(com.zimbra.cs.redolog.op.SaveChat) CreateChat(com.zimbra.cs.redolog.op.CreateChat) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag)

Example 10 with MailboxBlob

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

the class TestRedoLog method testTestRestoreMessageToNewAccount.

/**
     * Verifies that redolog replay successfully copies a message from one mailbox
     * to another and leaves the original blob intact.  See bug 22873.
     */
@Test
public void testTestRestoreMessageToNewAccount() throws Exception {
    TestUtil.createAccount(USER_NAME);
    // make sure mailbox is pre-created as well as account
    Mailbox sourceMbox = TestUtil.getMailbox(USER_NAME);
    // Add message to source account.
    long startTime = System.currentTimeMillis();
    Message sourceMsg = TestUtil.addMessage(sourceMbox, NAME_PREFIX + " testRestoreMessageToNewAccount");
    String sourceContent = new String(sourceMsg.getContent());
    assertTrue("Message.getContent() length should not be 0", sourceContent.length() != 0);
    // Replay log to destination account.
    Account destAccount = TestUtil.createAccount(RESTORED_NAME);
    RedoPlayer player = new RedoPlayer(false, true, false, false, false);
    Map<Integer, Integer> idMap = new HashMap<Integer, Integer>();
    Mailbox destMbox = MailboxManager.getInstance().getMailboxByAccount(destAccount);
    idMap.put(sourceMbox.getId(), destMbox.getId());
    ZimbraLog.test.info("Source Mailbox ID=%s Dest ID=%s", sourceMbox.getId(), destMbox.getId());
    player.scanLog(getRedoLogFile(), true, idMap, startTime, Long.MAX_VALUE);
    // Get destination message and compare content.
    List<Integer> destIds = TestUtil.search(destMbox, "in:inbox " + NAME_PREFIX, MailItem.Type.MESSAGE);
    assertEquals("Search should should only find 1 message", 1, destIds.size());
    Message destMsg = destMbox.getMessageById(null, destIds.get(0));
    String destContent = new String(destMsg.getContent());
    assertEquals("Expected=sourceContent Actual=destContent", sourceContent, destContent);
    // Make sure source content is still on disk.
    MailboxBlob blob = sourceMsg.getBlob();
    assertNotNull("Blob for sourceMsg should not be null", blob);
    sourceContent = new String(ByteUtil.getContent(StoreManager.getInstance().getContent(blob), sourceContent.length()));
    assertEquals("From disk Expected=destContent Actual=sourceContent", destContent, sourceContent);
}
Also used : Account(com.zimbra.cs.account.Account) Mailbox(com.zimbra.cs.mailbox.Mailbox) Message(com.zimbra.cs.mailbox.Message) MailboxBlob(com.zimbra.cs.store.MailboxBlob) HashMap(java.util.HashMap) RedoPlayer(com.zimbra.cs.redolog.RedoPlayer) Test(org.junit.Test)

Aggregations

MailboxBlob (com.zimbra.cs.store.MailboxBlob)27 StoreManager (com.zimbra.cs.store.StoreManager)16 StagedBlob (com.zimbra.cs.store.StagedBlob)14 Mailbox (com.zimbra.cs.mailbox.Mailbox)12 Blob (com.zimbra.cs.store.Blob)12 IOException (java.io.IOException)11 ServiceException (com.zimbra.common.service.ServiceException)8 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)7 Test (org.junit.Test)7 ArrayList (java.util.ArrayList)6 InputStream (java.io.InputStream)5 TargetConstraint (com.zimbra.cs.mailbox.MailItem.TargetConstraint)4 CreateMountpoint (com.zimbra.cs.redolog.op.CreateMountpoint)4 AccountServiceException (com.zimbra.cs.account.AccountServiceException)3 DbMailItem (com.zimbra.cs.db.DbMailItem)3 DbTag (com.zimbra.cs.db.DbTag)3 IndexDocument (com.zimbra.cs.index.IndexDocument)3 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)3 Message (com.zimbra.cs.mailbox.Message)3 NormalizedTags (com.zimbra.cs.mailbox.Tag.NormalizedTags)3