Search in sources :

Example 71 with AuthToken

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

the class AdminDocumentHandler method defendAgainstServerNameHarvestingWhenAbsent.

protected void defendAgainstServerNameHarvestingWhenAbsent(ServerBy by, String selectorKey, ZimbraSoapContext zsc, AdminRight needed) throws ServiceException {
    AuthToken authToken = zsc.getAuthToken();
    if (authToken.isAdmin()) {
        throw AccountServiceException.NO_SUCH_SERVER(selectorKey);
    } else {
        Entry psedoTarget = PseudoTarget.createPseudoTarget(Provisioning.getInstance(), TargetType.server, null, null, false, null, null);
        checkRight(zsc, psedoTarget, needed);
        throw AccountServiceException.NO_SUCH_SERVER(selectorKey);
    }
}
Also used : NamedEntry(com.zimbra.cs.account.NamedEntry) Entry(com.zimbra.cs.account.Entry) AuthToken(com.zimbra.cs.account.AuthToken)

Example 72 with AuthToken

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

the class AdminFileDownload method doGet.

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
        // check the auth token
        AuthToken authToken = getAdminAuthTokenFromCookie(req, resp);
        if (authToken == null) {
            return;
        }
        resp.sendRedirect("/service/extension/com_zimbra_bulkprovision/bulkdownload?" + req.getQueryString());
    } catch (Exception e) {
        ZimbraLog.webclient.error(e);
        return;
    }
}
Also used : AuthToken(com.zimbra.cs.account.AuthToken) ServletException(javax.servlet.ServletException) IOException(java.io.IOException)

Example 73 with AuthToken

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

the class Search method searchRemoteAccountCalendars.

private static void searchRemoteAccountCalendars(Element parent, SearchParams params, ZimbraSoapContext zsc, Account authAcct, Map<String, List<Integer>> accountFolders) throws ServiceException {
    // mail service soap requests want to see a target account
    String nominalTargetAcctId = null;
    StringBuilder queryStr = new StringBuilder();
    for (Map.Entry<String, List<Integer>> entry : accountFolders.entrySet()) {
        String acctId = entry.getKey();
        if (nominalTargetAcctId == null)
            nominalTargetAcctId = acctId;
        ItemIdFormatter ifmt = new ItemIdFormatter(authAcct.getId(), acctId, false);
        List<Integer> folderIds = entry.getValue();
        for (int folderId : folderIds) {
            if (queryStr.length() > 0)
                queryStr.append(" OR ");
            // must quote the qualified folder id
            queryStr.append("inid:\"").append(ifmt.formatItemId(folderId)).append("\"");
        }
    }
    Element req = zsc.createElement(MailConstants.SEARCH_REQUEST);
    req.addAttribute(MailConstants.A_SEARCH_TYPES, MailItem.Type.toString(params.getTypes()));
    if (params.getSortBy() != null) {
        req.addAttribute(MailConstants.A_SORTBY, params.getSortBy().toString());
    }
    req.addAttribute(MailConstants.A_QUERY_OFFSET, params.getOffset());
    if (params.getLimit() != 0)
        req.addAttribute(MailConstants.A_QUERY_LIMIT, params.getLimit());
    req.addAttribute(MailConstants.A_CAL_EXPAND_INST_START, params.getCalItemExpandStart());
    req.addAttribute(MailConstants.A_CAL_EXPAND_INST_END, params.getCalItemExpandEnd());
    req.addAttribute(MailConstants.E_QUERY, queryStr.toString(), Element.Disposition.CONTENT);
    Account target = Provisioning.getInstance().get(Key.AccountBy.id, nominalTargetAcctId);
    AuthToken authToken = AuthToken.getCsrfUnsecuredAuthToken(zsc.getAuthToken());
    String pxyAuthToken = authToken.getProxyAuthToken();
    ZAuthToken zat = pxyAuthToken == null ? authToken.toZAuthToken() : new ZAuthToken(pxyAuthToken);
    ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
    zoptions.setTargetAccount(nominalTargetAcctId);
    zoptions.setTargetAccountBy(AccountBy.id);
    zoptions.setNoSession(true);
    ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
    Element resp = zmbx.invoke(req);
    for (Element hit : resp.listElements()) {
        hit.detach();
        parent.addElement(hit);
    }
}
Also used : Account(com.zimbra.cs.account.Account) ItemIdFormatter(com.zimbra.cs.service.util.ItemIdFormatter) Element(com.zimbra.common.soap.Element) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ZMailbox(com.zimbra.client.ZMailbox) AuthToken(com.zimbra.cs.account.AuthToken) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map)

Example 74 with AuthToken

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

the class ItemActionHelper method executeRemote.

private void executeRemote() throws ServiceException, IOException {
    Account target = Provisioning.getInstance().get(Key.AccountBy.id, mIidFolder.getAccountId());
    AuthToken at = getAuthToken();
    String pxyAuthToken = Provisioning.onLocalServer(target) ? null : at.getProxyAuthToken();
    ZAuthToken zat = null;
    if (pxyAuthToken == null) {
        zat = at.toZAuthToken();
        zat.resetProxyAuthToken();
    } else {
        zat = new ZAuthToken(pxyAuthToken);
    }
    ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
    zoptions.setNoSession(true);
    zoptions.setTargetAccount(target.getId());
    zoptions.setTargetAccountBy(Key.AccountBy.id);
    ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
    // check for mountpoints before going any further...
    ZFolder zfolder = zmbx.getFolderById(mIidFolder.toString(mAuthenticatedAccount));
    if (zfolder instanceof ZMountpoint) {
        ItemId iidTarget = new ItemId(((ZMountpoint) zfolder).getCanonicalRemoteId(), mAuthenticatedAccount.getId());
        if (!mIidFolder.equals(iidTarget)) {
            mIidFolder = iidTarget;
            if (++mHopCount > com.zimbra.soap.ZimbraSoapContext.MAX_HOP_COUNT)
                throw MailServiceException.TOO_MANY_HOPS(mIidRequestedFolder);
            schedule();
            return;
        }
    }
    boolean deleteOriginal = mOperation != Op.COPY;
    String folderStr = mIidFolder.toString();
    mCreatedIds = new ArrayList<String>(itemIds.length);
    boolean toSpam = mIidFolder.getId() == Mailbox.ID_FOLDER_SPAM;
    boolean toMailbox = !toSpam && mIidFolder.getId() != Mailbox.ID_FOLDER_TRASH;
    for (MailItem item : mMailbox.getItemById(mOpCtxt, itemIds, type)) {
        if (item == null) {
            continue;
        }
        List<Message> msgs = null;
        if (item instanceof Conversation) {
            msgs = mMailbox.getMessagesByConversation(mOpCtxt, item.getId(), SortBy.DATE_ASC, -1);
        }
        if (deleteOriginal) {
            if (msgs != null) {
                // determine which of the conversation's component messages are actually able to be moved
                boolean permDenied = false;
                for (Iterator<Message> it = msgs.iterator(); it.hasNext(); ) {
                    Message msg = it.next();
                    if (!TargetConstraint.checkItem(mTargetConstraint, msg)) {
                        it.remove();
                    } else if (!canDelete(msg)) {
                        it.remove();
                        permDenied = true;
                    }
                }
                // stop here if no messages would be moved...
                if (msgs.isEmpty()) {
                    if (permDenied) {
                        throw ServiceException.PERM_DENIED("cannot delete any messages in " + item.getType() + " " + item.getId());
                    }
                    // all messages were excluded by the TargetConstraint, so there's no failure...
                    continue;
                }
            } else {
                if (!canDelete(item)) {
                    throw ServiceException.PERM_DENIED("cannot delete existing copy of " + item.getType() + " " + item.getId());
                }
            }
        }
        boolean fromSpam = item.inSpam();
        if ((fromSpam && toMailbox) || (!fromSpam && toSpam)) {
            try {
                Folder dest = mMailbox.getFolderById(mOpCtxt, mIidFolder.getId());
                SpamReport report = new SpamReport(toSpam, "remote " + mOperation, dest.getPath());
                Folder source = mMailbox.getFolderById(mOpCtxt, item.getFolderId());
                report.setSourceFolderPath(source.getPath());
                report.setDestAccountName(target.getName());
                SpamHandler.getInstance().handle(mOpCtxt, mMailbox, item.getId(), item.getType(), report);
            } catch (OutOfMemoryError e) {
                Zimbra.halt("out of memory", e);
            } catch (Throwable t) {
                ZimbraLog.mailop.info("could not train spam filter: " + new ItemId(item).toString(), t);
            }
        }
        // since we can't apply tags to a remote object, hardwiring "tags" to null below...
        String flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : item.getFlagString());
        String name = ((mOperation == Op.RENAME || mOperation == Op.UPDATE) && mName != null ? mName : item.getName());
        String createdId = null;
        InputStream in = null;
        switch(item.getType()) {
            case CONTACT:
                Contact ct = (Contact) item;
                Map<String, ZMailbox.ZAttachmentInfo> attachments = new HashMap<String, ZMailbox.ZAttachmentInfo>();
                for (Contact.Attachment att : ct.getAttachments()) {
                    String attachmentId = zmbx.uploadAttachment(att.getFilename(), att.getContent(), att.getContentType(), 0);
                    ZMailbox.ZAttachmentInfo info = new ZMailbox.ZAttachmentInfo().setAttachmentId(attachmentId);
                    attachments.put(att.getName(), info);
                }
                Map<String, String> fields = ct.getFields();
                Map<String, String> members = new HashMap<String, String>();
                for (String key : fields.keySet()) {
                    if (ContactConstants.A_groupMember.equals(key)) {
                        String memberEncoded = fields.get(key);
                        ContactGroup group = ContactGroup.init(memberEncoded);
                        for (Member m : group.getMembers()) {
                            members.put(m.getValue(), m.getType().getSoapEncoded());
                        }
                        break;
                    }
                }
                fields.remove(ContactConstants.A_groupMember);
                ZContact contact = zmbx.createContact(folderStr, null, fields, attachments, members);
                createdId = contact.getId();
                mCreatedIds.add(createdId);
                break;
            case MESSAGE:
                try {
                    in = StoreManager.getInstance().getContent(item.getBlob());
                    createdId = zmbx.addMessage(folderStr, flags, null, item.getDate(), in, item.getSize(), true);
                } finally {
                    ByteUtil.closeStream(in);
                }
                mCreatedIds.add(createdId);
                break;
            case VIRTUAL_CONVERSATION:
            case CONVERSATION:
                for (Message msg : msgs) {
                    flags = (mOperation == Op.UPDATE && mFlags != null ? mFlags : msg.getFlagString());
                    try {
                        in = StoreManager.getInstance().getContent(msg.getBlob());
                        createdId = zmbx.addMessage(folderStr, flags, null, msg.getDate(), in, msg.getSize(), true);
                    } finally {
                        ByteUtil.closeStream(in);
                    }
                    mCreatedIds.add(createdId);
                }
                break;
            case DOCUMENT:
                Document doc = (Document) item;
                SoapHttpTransport transport = new SoapHttpTransport(zoptions.getUri());
                try {
                    in = StoreManager.getInstance().getContent(doc.getBlob());
                    String uploadId = zmbx.uploadContentAsStream(name, in, doc.getContentType(), doc.getSize(), 4000, true);
                    // instead of using convenience method from ZMailbox
                    // we need to hand marshall the request and set the
                    // response protocol explicitly to what was requested
                    // from the client.
                    Element req = new XMLElement(MailConstants.SAVE_DOCUMENT_REQUEST);
                    Element edoc = req.addUniqueElement(MailConstants.E_DOC);
                    edoc.addAttribute(MailConstants.A_NAME, name);
                    edoc.addAttribute(MailConstants.A_FOLDER, folderStr);
                    edoc.addAttribute(MailConstants.A_FLAGS, flags);
                    Element upload = edoc.addElement(MailConstants.E_UPLOAD);
                    upload.addAttribute(MailConstants.A_ID, uploadId);
                    transport.setResponseProtocol(mResponseProtocol);
                    transport.setAuthToken(zat);
                    Element response = transport.invoke(req);
                    createdId = response.getElement(MailConstants.E_DOC).getAttribute(MailConstants.A_ID);
                } finally {
                    ByteUtil.closeStream(in);
                    transport.shutdown();
                }
                mCreatedIds.add(createdId);
                break;
            case APPOINTMENT:
            case TASK:
                CalendarItem cal = (CalendarItem) item;
                // private calendar item may not be moved by non-owner unless permission was granted
                if (!cal.isPublic()) {
                    boolean asAdmin = mOpCtxt != null ? mOpCtxt.isUsingAdminPrivileges() : false;
                    if (!cal.allowPrivateAccess(mAuthenticatedAccount, asAdmin))
                        throw ServiceException.PERM_DENIED("you do not have permission to move/copy a private calendar item from the current folder/mailbox");
                }
                // Move the item to remote mailbox using SetAppointmentRequest/SetTaskRequest.
                QName qname = (item.getType() == MailItem.Type.TASK ? MailConstants.SET_TASK_REQUEST : MailConstants.SET_APPOINTMENT_REQUEST);
                Element request = new Element.XMLElement(qname).addAttribute(MailConstants.A_FOLDER, folderStr).addAttribute(MailConstants.A_FLAGS, flags);
                ToXML.encodeAlarmTimes(request, cal);
                Invite invDefault = cal.getDefaultInviteOrNull();
                // Takeover as organizer if we're doing a MOVE and source mailbox is the organizer.
                // Don't takeover in a COPY operation.
                boolean takeoverAsOrganizer = false;
                boolean blockMove = false;
                if (Op.MOVE.equals(mOperation)) {
                    Invite inv = invDefault;
                    if (inv == null) {
                        // no default invite; let's use the first invite
                        Invite[] invs = cal.getInvites();
                        if (invs != null && invs.length > 0)
                            inv = invs[0];
                    }
                    takeoverAsOrganizer = inv != null && inv.isOrganizer();
                    blockMove = takeoverAsOrganizer && inv.hasOtherAttendees();
                }
                if (blockMove) {
                    throw MailServiceException.INVALID_REQUEST("This operation requires change of organizer and it is not permitted", null);
                }
                if (invDefault != null) {
                    addCalendarPart(request.addUniqueElement(MailConstants.A_DEFAULT), cal, invDefault, zmbx, target, takeoverAsOrganizer);
                }
                for (Invite inv : cal.getInvites()) {
                    if (inv == null || inv == invDefault)
                        continue;
                    String elem = inv.isCancel() ? MailConstants.E_CAL_CANCEL : MailConstants.E_CAL_EXCEPT;
                    addCalendarPart(request.addElement(elem), cal, inv, zmbx, target, takeoverAsOrganizer);
                }
                ToXML.encodeCalendarReplies(request, cal);
                createdId = zmbx.invoke(request).getAttribute(MailConstants.A_CAL_ID);
                mCreatedIds.add(createdId);
                break;
            default:
                throw MailServiceException.CANNOT_COPY(item.getId());
        }
        try {
            if (deleteOriginal && !mIdFormatter.formatItemId(item).equals(createdId)) {
                if (msgs == null) {
                    mMailbox.delete(mOpCtxt, item.getId(), item.getType());
                } else {
                    for (Message msg : msgs) mMailbox.delete(mOpCtxt, msg.getId(), msg.getType());
                }
            }
        } catch (ServiceException e) {
            if (e.getCode() != ServiceException.PERM_DENIED)
                throw e;
            // something funky happened permissions-wise between the getEffectivePermissions check and here...
            ZimbraLog.misc.info("could not delete original item " + item.getId() + "; treating operation as a copy instead");
        }
    }
}
Also used : ZMountpoint(com.zimbra.client.ZMountpoint) Account(com.zimbra.cs.account.Account) Message(com.zimbra.cs.mailbox.Message) MimeMessage(javax.mail.internet.MimeMessage) HashMap(java.util.HashMap) Element(com.zimbra.common.soap.Element) XMLElement(com.zimbra.common.soap.Element.XMLElement) Conversation(com.zimbra.cs.mailbox.Conversation) Folder(com.zimbra.cs.mailbox.Folder) ZFolder(com.zimbra.client.ZFolder) Document(com.zimbra.cs.mailbox.Document) XMLElement(com.zimbra.common.soap.Element.XMLElement) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ItemId(com.zimbra.cs.service.util.ItemId) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) ZMailbox(com.zimbra.client.ZMailbox) ZFolder(com.zimbra.client.ZFolder) SoapHttpTransport(com.zimbra.common.soap.SoapHttpTransport) Member(com.zimbra.cs.mailbox.ContactGroup.Member) InputStream(java.io.InputStream) QName(org.dom4j.QName) ZContact(com.zimbra.client.ZContact) Contact(com.zimbra.cs.mailbox.Contact) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) SpamReport(com.zimbra.cs.service.util.SpamHandler.SpamReport) AuthToken(com.zimbra.cs.account.AuthToken) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ContactGroup(com.zimbra.cs.mailbox.ContactGroup) Invite(com.zimbra.cs.mailbox.calendar.Invite) ZContact(com.zimbra.client.ZContact)

Example 75 with AuthToken

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

the class ItemAction method forceRemoteSession.

private Account forceRemoteSession(ZimbraSoapContext zsc, Map<String, Object> context, OperationContext octxt, String op, Element action) throws ServiceException {
    // only proxying notification from the user's home-server master session
    if (!zsc.isNotificationEnabled()) {
        return null;
    }
    Session session = (Session) context.get(SoapEngine.ZIMBRA_SESSION);
    if (session instanceof SoapSession.DelegateSession) {
        session = ((SoapSession.DelegateSession) session).getParentSession();
    }
    if (!(session instanceof SoapSession) || session.getMailbox() == null) {
        return null;
    }
    SoapSession ss = (SoapSession) session;
    // only have to worry about operations where things can get created in other mailboxes (regular notification works for all other cases)
    if (!op.equals(OP_MOVE) && !op.equals(OP_COPY) && !op.equals(OP_SPAM) && !op.equals(OP_RENAME) && !op.equals(OP_UPDATE)) {
        return null;
    }
    String folderStr = action.getAttribute(MailConstants.A_FOLDER, null);
    if (folderStr == null) {
        return null;
    }
    // recursively dereference mountpoints to find ultimate target folder
    ItemId iidFolder = new ItemId(folderStr, zsc), iidRequested = iidFolder;
    Account owner = null;
    int hopCount = 0;
    ZAuthToken zat = null;
    while (hopCount < ZimbraSoapContext.MAX_HOP_COUNT) {
        owner = Provisioning.getInstance().getAccountById(iidFolder.getAccountId());
        if (Provisioning.onLocalServer(owner)) {
            try {
                Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(owner);
                Folder folder = mbox.getFolderById(octxt, iidFolder.getId());
                if (!(folder instanceof Mountpoint))
                    break;
                iidFolder = ((Mountpoint) folder).getTarget();
            } catch (ServiceException e) {
                // could be a PERM_DENIED, could be something else -- this is not the right place to fail, however
                break;
            }
        } else {
            if (zat == null) {
                AuthToken at = AuthToken.getCsrfUnsecuredAuthToken(zsc.getAuthToken());
                String pxyAuthToken = at.getProxyAuthToken();
                zat = pxyAuthToken == null ? at.toZAuthToken() : new ZAuthToken(pxyAuthToken);
            }
            ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(owner));
            zoptions.setNoSession(true);
            zoptions.setTargetAccount(owner.getId());
            zoptions.setTargetAccountBy(Key.AccountBy.id);
            ZMailbox zmbx = ZMailbox.getMailbox(zoptions);
            ZFolder zfolder = zmbx.getFolderById(iidFolder.toString(zsc.getAuthtokenAccountId()));
            if (!(zfolder instanceof ZMountpoint))
                break;
            iidFolder = new ItemId(((ZMountpoint) zfolder).getCanonicalRemoteId(), zsc.getAuthtokenAccountId());
        }
        hopCount++;
    }
    if (hopCount >= ZimbraSoapContext.MAX_HOP_COUNT) {
        throw MailServiceException.TOO_MANY_HOPS(iidRequested);
    }
    // avoid dereferencing the mountpoint again later on
    action.addAttribute(MailConstants.A_FOLDER, iidFolder.toString());
    // fault in a session to listen in on the target folder's mailbox
    if (iidFolder.belongsTo(session.getAuthenticatedAccountId())) {
        return null;
    } else if (iidFolder.isLocal()) {
        ss.getDelegateSession(iidFolder.getAccountId());
        return null;
    } else {
        try {
            proxyRequest(zsc.createElement(MailConstants.NO_OP_REQUEST), context, owner.getId());
            return owner;
        } catch (ServiceException e) {
            return null;
        }
    }
}
Also used : ZMountpoint(com.zimbra.client.ZMountpoint) Account(com.zimbra.cs.account.Account) ImapFolder(com.zimbra.cs.datasource.imap.ImapFolder) ZFolder(com.zimbra.client.ZFolder) Folder(com.zimbra.cs.mailbox.Folder) ItemId(com.zimbra.cs.service.util.ItemId) ZAuthToken(com.zimbra.common.auth.ZAuthToken) TargetConstraint(com.zimbra.cs.mailbox.MailItem.TargetConstraint) ZMountpoint(com.zimbra.client.ZMountpoint) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) SoapSession(com.zimbra.cs.session.SoapSession) ZMailbox(com.zimbra.client.ZMailbox) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) AuthToken(com.zimbra.cs.account.AuthToken) ZAuthToken(com.zimbra.common.auth.ZAuthToken) ZFolder(com.zimbra.client.ZFolder) ZMountpoint(com.zimbra.client.ZMountpoint) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) SoapSession(com.zimbra.cs.session.SoapSession) Session(com.zimbra.cs.session.Session)

Aggregations

AuthToken (com.zimbra.cs.account.AuthToken)98 ServiceException (com.zimbra.common.service.ServiceException)46 Account (com.zimbra.cs.account.Account)44 ZimbraAuthToken (com.zimbra.cs.account.ZimbraAuthToken)27 AuthTokenException (com.zimbra.cs.account.AuthTokenException)26 Element (com.zimbra.common.soap.Element)24 Provisioning (com.zimbra.cs.account.Provisioning)23 ZMailbox (com.zimbra.client.ZMailbox)19 ZAuthToken (com.zimbra.common.auth.ZAuthToken)18 IOException (java.io.IOException)14 Server (com.zimbra.cs.account.Server)12 ZimbraSoapContext (com.zimbra.soap.ZimbraSoapContext)12 HttpClient (org.apache.commons.httpclient.HttpClient)12 HashMap (java.util.HashMap)11 GetMethod (org.apache.commons.httpclient.methods.GetMethod)11 Test (org.junit.Test)11 SoapHttpTransport (com.zimbra.common.soap.SoapHttpTransport)10 ServletException (javax.servlet.ServletException)10 AuthFailedServiceException (com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException)8 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)8