Search in sources :

Example 11 with NoSuchItemException

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

the class ExportAndDeleteItems method handle.

@Override
public Element handle(Element requst, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    checkRight(zsc, context, null, AdminRight.PR_SYSTEM_ADMIN_ONLY);
    // Parse request.
    ExportAndDeleteItemsRequest req = JaxbUtil.elementToJaxb(requst);
    ExportAndDeleteMailboxSpec mailbox = req.getMailbox();
    if (mailbox == null) {
        throw ServiceException.INVALID_REQUEST("empty mbox id", null);
    }
    Mailbox mbox = MailboxManager.getInstance().getMailboxById(mailbox.getId());
    Multimap<Integer, Integer> idRevs = HashMultimap.create();
    for (ExportAndDeleteItemSpec item : mailbox.getItems()) {
        idRevs.put(item.getId(), item.getVersion());
    }
    String dirPath = req.getExportDir();
    String prefix = req.getExportFilenamePrefix();
    // Lock the mailbox, to make sure that another thread doesn't modify the items we're exporting/deleting.
    mbox.lock.lock();
    try {
        DbConnection conn = null;
        try {
            conn = DbPool.getConnection();
            if (dirPath != null) {
                File exportDir = new File(dirPath);
                if (!exportDir.isDirectory()) {
                    DbPool.quietClose(conn);
                    throw ServiceException.INVALID_REQUEST(dirPath + " is not a directory", null);
                }
                String filePath = makePath(dirPath, DbMailItem.TABLE_MAIL_ITEM, prefix);
                export(conn, mbox, DbMailItem.TABLE_MAIL_ITEM, "id", idRevs, filePath);
                filePath = makePath(dirPath, DbMailItem.TABLE_MAIL_ITEM_DUMPSTER, prefix);
                export(conn, mbox, DbMailItem.TABLE_MAIL_ITEM_DUMPSTER, "id", idRevs, filePath);
                filePath = makePath(dirPath, DbMailItem.TABLE_REVISION, prefix);
                export(conn, mbox, DbMailItem.TABLE_REVISION, "item_id", idRevs, filePath);
                filePath = makePath(dirPath, DbMailItem.TABLE_REVISION_DUMPSTER, prefix);
                export(conn, mbox, DbMailItem.TABLE_REVISION_DUMPSTER, "item_id", idRevs, filePath);
                filePath = makePath(dirPath, DbMailItem.TABLE_APPOINTMENT, prefix);
                export(conn, mbox, DbMailItem.TABLE_APPOINTMENT, "item_id", idRevs, filePath);
                filePath = makePath(dirPath, DbMailItem.TABLE_APPOINTMENT_DUMPSTER, prefix);
                export(conn, mbox, DbMailItem.TABLE_APPOINTMENT_DUMPSTER, "item_id", idRevs, filePath);
            }
            // delete item from mail_item and revision table
            for (Integer itemId : idRevs.keySet()) {
                Collection<Integer> revs = idRevs.get(itemId);
                for (int rev : revs) {
                    if (rev == 0) {
                        // delete all revisions to make sure we delete all blobs
                        List<MailItem> list = null;
                        try {
                            list = mbox.getAllRevisions(null, itemId, MailItem.Type.UNKNOWN);
                        } catch (NoSuchItemException ex) {
                            // exception happens when we try to delete a mail_item which is already in mail_item_dumpster
                            continue;
                        }
                        for (MailItem item : list) {
                            if (item.getType() == MailItem.Type.DOCUMENT) {
                                mbox.purgeRevision(null, itemId, item.getVersion(), false);
                            }
                        }
                        mbox.delete(null, itemId, MailItem.Type.UNKNOWN, null);
                        break;
                    } else if (!revs.contains(0)) {
                        try {
                            mbox.purgeRevision(null, itemId, rev, false);
                        } catch (NoSuchItemException ex) {
                            // exception happens when we try to delete a revision which is already in revision_dumpster
                            continue;
                        }
                    }
                }
            }
            // Delete items from mail_item_dumpster & revision_dumpster tables just
            // incase moved to dumpster tables
            DbBlobConsistency.delete(conn, mbox, idRevs);
        } finally {
            conn.commit();
            DbPool.quietClose(conn);
        }
    } finally {
        mbox.lock.release();
    }
    return zsc.createElement(AdminConstants.EXPORT_AND_DELETE_ITEMS_RESPONSE);
}
Also used : ExportAndDeleteItemSpec(com.zimbra.soap.admin.type.ExportAndDeleteItemSpec) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) DbConnection(com.zimbra.cs.db.DbPool.DbConnection) MailItem(com.zimbra.cs.mailbox.MailItem) DbMailItem(com.zimbra.cs.db.DbMailItem) ExportAndDeleteItemsRequest(com.zimbra.soap.admin.message.ExportAndDeleteItemsRequest) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ExportAndDeleteMailboxSpec(com.zimbra.soap.admin.type.ExportAndDeleteMailboxSpec) File(java.io.File)

Example 12 with NoSuchItemException

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

the class Mailbox method reanalyze.

/** Recalculates the size, metadata, etc. for an existing MailItem and
     *  persists that information to the database.  Maintains any existing
     *  mutable metadata.  Updates mailbox and folder sizes appropriately.
     *
     * @param id    The item ID of the MailItem to reanalyze.
     * @param type  The item's type (e.g. {@link MailItem#TYPE_MESSAGE}).
     * @param data  The (optional) extra item data for indexing (e.g.
     *              a Message's {@link ParsedMessage}. */
void reanalyze(int id, MailItem.Type type, Object data, long size) throws ServiceException {
    boolean success = false;
    try {
        beginTransaction("reanalyze", null);
        MailItem item;
        try {
            item = getItemById(id, type, false);
        } catch (NoSuchItemException e) {
            // fallback to dumpster
            item = getItemById(id, type, true);
        }
        item.reanalyze(data, size);
        success = true;
    } finally {
        endTransaction(success);
    }
}
Also used : DbMailItem(com.zimbra.cs.db.DbMailItem) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)

Example 13 with NoSuchItemException

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

the class ApplyFilterRules method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account account = getRequestedAccount(zsc);
    if (!canAccessAccount(zsc, account))
        throw ServiceException.PERM_DENIED("cannot access account");
    // Get rules.
    String fullScript = getRules(account);
    if (StringUtil.isNullOrEmpty(fullScript)) {
        throw ServiceException.INVALID_REQUEST("Account has no filter rules defined.", null);
    }
    List<Element> ruleElements = request.getElement(MailConstants.E_FILTER_RULES).listElements(MailConstants.E_FILTER_RULE);
    if (ruleElements.size() == 0) {
        String msg = String.format("No %s elements specified.", MailConstants.E_FILTER_RULE);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    // Concatenate script parts and create a new script to run on existing messages.
    StringBuilder buf = new StringBuilder();
    for (Element ruleEl : ruleElements) {
        String name = ruleEl.getAttribute(MailConstants.A_NAME);
        String singleRule = RuleManager.getRuleByName(fullScript, name);
        if (singleRule == null) {
            String msg = String.format("Could not find a rule named '%s'", name);
            throw ServiceException.INVALID_REQUEST(msg, null);
        }
        buf.append(singleRule).append("\n");
    }
    String partialScript = buf.toString();
    ZimbraLog.filter.debug("Applying partial script to existing messages: %s", partialScript);
    Node node = null;
    try {
        node = RuleManager.parse(partialScript);
    } catch (ParseException e) {
        throw ServiceException.FAILURE("Unable to parse Sieve script: " + partialScript, e);
    }
    // Get the ids of the messages to filter.
    Element msgEl = request.getOptionalElement(MailConstants.E_MSG);
    String query = getElementText(request, MailConstants.E_QUERY);
    if (msgEl != null && query != null) {
        String msg = String.format("Cannot specify both %s and %s elements.", MailConstants.E_MSG, MailConstants.E_QUERY);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    Mailbox mbox = getRequestedMailbox(zsc);
    List<Integer> messageIds = new ArrayList<Integer>();
    List<Integer> affectedIds = new ArrayList<Integer>();
    OperationContext octxt = getOperationContext(zsc, context);
    if (msgEl != null) {
        String[] ids = msgEl.getAttribute(MailConstants.A_IDS).split(",");
        for (String id : ids) {
            messageIds.add(Integer.valueOf(id));
        }
    } else if (query != null) {
        ZimbraQueryResults results = null;
        try {
            results = mbox.index.search(octxt, query, EnumSet.of(MailItem.Type.MESSAGE), SortBy.NONE, Integer.MAX_VALUE);
            while (results.hasNext()) {
                ZimbraHit hit = results.getNext();
                messageIds.add(hit.getItemId());
            }
        } catch (Exception e) {
            String msg = String.format("Unable to run search for query: '%s'", query);
            throw ServiceException.INVALID_REQUEST(msg, e);
        } finally {
            Closeables.closeQuietly(results);
        }
    } else {
        String msg = String.format("Must specify either the %s or %s element.", MailConstants.E_MSG, MailConstants.E_QUERY);
        throw ServiceException.INVALID_REQUEST(msg, null);
    }
    int max = account.getFilterBatchSize();
    if (messageIds.size() > max) {
        throw ServiceException.INVALID_REQUEST("Attempted to apply filter rules to " + messageIds.size() + " messages, which exceeded the limit of " + max, null);
    }
    ZimbraLog.filter.info("Applying filter rules to %s existing messages.", messageIds.size());
    long sleepInterval = account.getFilterSleepInterval();
    // Apply filter rules.
    for (int i = 0; i < messageIds.size(); i++) {
        if (i > 0 && sleepInterval > 0) {
            try {
                Thread.sleep(sleepInterval);
            } catch (InterruptedException e) {
            }
        }
        int id = messageIds.get(i);
        try {
            mbox.getMessageById(octxt, id);
            if (RuleManager.applyRulesToExistingMessage(octxt, mbox, id, node)) {
                affectedIds.add(id);
            }
        } catch (NoSuchItemException e) {
            // Message was deleted since the search was done (bug 41609).
            ZimbraLog.filter.info("Skipping message %d: %s.", id, e.toString());
        } catch (ServiceException e) {
            ZimbraLog.filter.warn("Unable to filter message %d.", id, e);
        }
    }
    // Send response.
    Element response = zsc.createElement(getResponseElementName());
    if (affectedIds.size() > 0) {
        response.addElement(MailConstants.E_MSG).addAttribute(MailConstants.A_IDS, StringUtil.join(",", affectedIds));
    }
    return response;
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) ZimbraHit(com.zimbra.cs.index.ZimbraHit) Account(com.zimbra.cs.account.Account) Element(com.zimbra.common.soap.Element) Node(org.apache.jsieve.parser.generated.Node) ArrayList(java.util.ArrayList) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) ServiceException(com.zimbra.common.service.ServiceException) ParseException(org.apache.jsieve.parser.generated.ParseException) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) Mailbox(com.zimbra.cs.mailbox.Mailbox) ServiceException(com.zimbra.common.service.ServiceException) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ZimbraQueryResults(com.zimbra.cs.index.ZimbraQueryResults) ParseException(org.apache.jsieve.parser.generated.ParseException)

Example 14 with NoSuchItemException

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

the class IncomingMessageHandler method fileInto.

@Override
public ItemId fileInto(String folderPath, Collection<ActionFlag> flagActions, String[] tags) throws ServiceException {
    ItemId id = FilterUtil.addMessage(dctxt, mailbox, parsedMessage, recipientAddress, folderPath, false, FilterUtil.getFlagBitmask(flagActions, Flag.BITMASK_UNREAD), tags, Mailbox.ID_AUTO_INCREMENT, octxt);
    // the spam folder (bug 37164).
    try {
        Folder folder = mailbox.getFolderByPath(octxt, folderPath);
        if (folder.getId() == Mailbox.ID_FOLDER_SPAM && id.isLocal()) {
            SpamReport report = new SpamReport(true, "filter", folderPath);
            SpamHandler.getInstance().handle(octxt, mailbox, id.getId(), MailItem.Type.MESSAGE, report);
        }
    } catch (NoSuchItemException e) {
        ZimbraLog.filter.debug("Unable to do spam training for message %s because folder path %s does not exist.", id, folderPath);
    } catch (ServiceException e) {
        ZimbraLog.filter.warn("Unable to do spam training for message %s.", id, e);
    }
    return id;
}
Also used : ServiceException(com.zimbra.common.service.ServiceException) SpamReport(com.zimbra.cs.service.util.SpamHandler.SpamReport) Folder(com.zimbra.cs.mailbox.Folder) ItemId(com.zimbra.cs.service.util.ItemId) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)

Example 15 with NoSuchItemException

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

the class Mailbox method delete.

/**
     * Delete the <tt>MailItem</tt>s with the given ids.  If there is no <tt>MailItem</tt> for a given id, that id is
     * ignored.  If the id maps to an existing <tt>MailItem</tt> of an incompatible type, however, an error is thrown.
     *
     * @param octxt operation context or {@code null}
     * @param itemIds item ids
     * @param type item type or {@link MailItem.Type#UNKNOWN}
     * @param tcon target constraint or {@code null}
     * @param useEmptyForFolders empty folder {@code true} or {@code false}
     * @param nonExistingItems object of {@link ArrayList} or {@code null}
     */
private void delete(OperationContext octxt, int[] itemIds, MailItem.Type type, TargetConstraint tcon, boolean useEmptyForFolders, List<Integer> nonExistingItems) throws ServiceException {
    DeleteItem redoRecorder = new DeleteItem(mId, itemIds, type, tcon);
    List<Integer> folderIds = Lists.newArrayList();
    boolean success = false;
    try {
        beginTransaction("delete", octxt, redoRecorder);
        setOperationTargetConstraint(tcon);
        for (int id : itemIds) {
            if (id == ID_AUTO_INCREMENT) {
                continue;
            }
            MailItem item;
            try {
                item = getItemById(id, MailItem.Type.UNKNOWN);
            } catch (NoSuchItemException nsie) {
                if (nonExistingItems != null) {
                    nonExistingItems.add(id);
                }
                // trying to delete nonexistent things is A-OK!
                continue;
            }
            // however, trying to delete messages and passing in a folder ID is not OK
            if (!MailItem.isAcceptableType(type, item.getType())) {
                throw MailItem.noSuchItem(id, type);
            } else if (!checkItemChangeID(item) && item instanceof Tag) {
                throw MailServiceException.MODIFY_CONFLICT();
            }
            if (useEmptyForFolders && MailItem.Type.FOLDER.equals(item.getType())) {
                // removed later to allow batching delete of contents in there own transactions
                folderIds.add(id);
            } else {
                // delete the item, but don't write the tombstone until we're finished...
                item.delete(false);
            }
        }
        // deletes have already been collected, so fetch the tombstones and write once
        TypedIdList tombstones = collectPendingTombstones();
        if (tombstones != null && !tombstones.isEmpty()) {
            DbMailItem.writeTombstones(this, tombstones);
        }
        success = true;
    } finally {
        endTransaction(success);
    }
    for (Integer folderId : folderIds) {
        emptyFolder(octxt, folderId, true, /* removeTopLevelFolder */
        true, /* removeSubfolders */
        tcon);
    }
}
Also used : DbMailItem(com.zimbra.cs.db.DbMailItem) DeleteItem(com.zimbra.cs.redolog.op.DeleteItem) AlterItemTag(com.zimbra.cs.redolog.op.AlterItemTag) CreateTag(com.zimbra.cs.redolog.op.CreateTag) DbTag(com.zimbra.cs.db.DbTag) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) TypedIdList(com.zimbra.cs.mailbox.util.TypedIdList) RefreshMountpoint(com.zimbra.cs.redolog.op.RefreshMountpoint) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) CreateMountpoint(com.zimbra.cs.redolog.op.CreateMountpoint)

Aggregations

NoSuchItemException (com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)50 Mailbox (com.zimbra.cs.mailbox.Mailbox)21 ServiceException (com.zimbra.common.service.ServiceException)20 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)15 MailItem (com.zimbra.cs.mailbox.MailItem)11 Test (org.junit.Test)11 Account (com.zimbra.cs.account.Account)10 OperationContext (com.zimbra.cs.mailbox.OperationContext)10 ItemId (com.zimbra.cs.service.util.ItemId)10 Folder (com.zimbra.cs.mailbox.Folder)9 MimeMessage (javax.mail.internet.MimeMessage)8 Element (com.zimbra.common.soap.Element)7 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)7 IOException (java.io.IOException)7 AccountServiceException (com.zimbra.cs.account.AccountServiceException)6 ParsedMessage (com.zimbra.cs.mime.ParsedMessage)6 ArrayList (java.util.ArrayList)6 DbMailItem (com.zimbra.cs.db.DbMailItem)5 DbTag (com.zimbra.cs.db.DbTag)5 Document (com.zimbra.cs.mailbox.Document)5