Search in sources :

Example 46 with MailItem

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

the class ImapPartSpecifier method getContent.

Pair<Long, InputStream> getContent(Object obj) throws IOException, BinaryDecodingException, ServiceException {
    Pair<Long, InputStream> contents;
    if (obj instanceof MimeMessage) {
        contents = getContent((MimeMessage) obj);
    } else if (obj instanceof MailItem) {
        if (!isEntireMessage()) {
            throw ServiceException.FAILURE("called writeMessage on non-toplevel part", null);
        }
        contents = ImapMessage.getContent((MailItem) obj);
    } else {
        throw ServiceException.FAILURE("called write() with unexpected argument: " + (obj == null ? "null" : obj.getClass().getSimpleName()), null);
    }
    if (octetStart >= 0 && contents != null) {
        // if there is a "partial" octet start/length constraint on this
        // part specifier, apply it here
        InputStream is = contents.getSecond();
        long statedLength = contents.getFirst();
        long realLength = Math.max(0, Math.min(statedLength < 0 ? Integer.MAX_VALUE : statedLength, octetEnd) - octetStart);
        try {
            int start = octetStart;
            // don't do skip() correctly
            if (is instanceof com.sun.mail.util.BASE64DecoderStream || is instanceof com.sun.mail.util.QPDecoderStream) {
                ByteUtil.skip(is, start);
                start = 0;
            }
            is = ByteUtil.SegmentInputStream.create(is, start, start + realLength);
        } catch (StartOutOfBoundsException e) {
            //return empty string {0} when start is out of range
            ZimbraLog.imap.warn("IMAP part requested start out of range", e);
            is = new ByteArrayInputStream(new byte[0]);
            statedLength = realLength = 0;
        } catch (IOException ioe) {
            ByteUtil.closeStream(is);
            throw ioe;
        }
        contents = new Pair<Long, InputStream>(statedLength < 0 ? -1 : realLength, is);
    }
    return contents;
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) MailItem(com.zimbra.cs.mailbox.MailItem) MimeMessage(javax.mail.internet.MimeMessage) ByteArrayInputStream(java.io.ByteArrayInputStream) StartOutOfBoundsException(com.zimbra.common.util.StartOutOfBoundsException)

Example 47 with MailItem

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

the class ImapSession method notifyPendingChanges.

@Override
public void notifyPendingChanges(PendingModifications pns, int changeId, Session source) {
    if (!pns.hasNotifications()) {
        return;
    }
    ImapHandler i4handler = handler;
    try {
        synchronized (this) {
            AddedItems added = new AddedItems();
            if (pns.deleted != null) {
                for (Map.Entry<ModificationKey, Change> entry : pns.deleted.entrySet()) {
                    handleDelete(changeId, entry.getKey().getItemId(), entry.getValue());
                }
            }
            if (pns.created != null) {
                for (MailItem item : pns.created.values()) {
                    handleCreate(changeId, item, added);
                }
            }
            if (pns.modified != null) {
                for (Change chg : pns.modified.values()) {
                    handleModify(changeId, chg, added);
                }
            }
            // add new messages to the currently selected mailbox
            if (!added.isEmpty()) {
                mFolder.handleAddedMessages(changeId, added);
            }
            mFolder.finishNotification(changeId);
        }
        if (i4handler != null && i4handler.isIdle()) {
            i4handler.sendNotifications(true, true);
        }
    } catch (IOException e) {
        //   which calls Session.doCleanup, which calls Mailbox.removeListener
        if (ZimbraLog.imap.isDebugEnabled()) {
            // with stack trace
            ZimbraLog.imap.debug("Failed to notify, closing %s", this, e);
        } else {
            // without stack trace
            ZimbraLog.imap.info("Failed to notify (%s), closing %s", e.toString(), this);
        }
        if (i4handler != null) {
            i4handler.close();
        }
    }
}
Also used : MailItem(com.zimbra.cs.mailbox.MailItem) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) IOException(java.io.IOException) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap)

Example 48 with MailItem

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

the class CalListCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications mods, int changeId) {
    ChangeMap changeMap = new ChangeMap(1);
    if (mods.created != null) {
        for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
            MailItem item = entry.getValue();
            if (item instanceof Folder) {
                Folder folder = (Folder) item;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                    changedFolders.created.add(folder.getId());
                }
            }
        }
    }
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            if (whatChanged instanceof Folder) {
                Folder folder = (Folder) whatChanged;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                    int folderId = folder.getId();
                    if ((change.why & Change.FOLDER) != 0) {
                        // moving the calendar folder to another parent folder
                        int parentFolder = folder.getFolderId();
                        changedFolders.created.add(folderId);
                        if (parentFolder == Mailbox.ID_FOLDER_TRASH) {
                            changedFolders.deleted.add(folderId);
                        } else {
                            changedFolders.created.add(folderId);
                        }
                    } else {
                        // not a folder move, but something else changed, either calendar's metadata
                        // or a child item (appointment/task)
                        changedFolders.modified.add(folderId);
                    }
                }
            } else if (whatChanged instanceof Message) {
                Message msg = (Message) whatChanged;
                if (msg.hasCalendarItemInfos()) {
                    if (msg.getFolderId() == Mailbox.ID_FOLDER_INBOX || (change.why & Change.FOLDER) != 0) {
                        // If message was moved, we don't know which folder it was moved from.
                        // Just invalidate the Inbox because that's the only message folder we care
                        // about in calendaring.
                        ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                        changedFolders.modified.add(Mailbox.ID_FOLDER_INBOX);
                    }
                }
            }
        }
    }
    if (mods.deleted != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            MailItem.Type type = (MailItem.Type) entry.getValue().what;
            if (type == MailItem.Type.FOLDER) {
                // We only have item id.  Let's just assume it's a calendar folder id and check
                // against the cached list.
                ChangedFolders changedFolders = changeMap.getAccount(entry.getKey().getAccountId());
                changedFolders.deleted.add(entry.getKey().getItemId());
            }
        // Let's not worry about hard deletes of invite/reply emails.  It has no practical benefit.
        }
    }
    try {
        for (Map.Entry<String, ChangedFolders> entry : changeMap.entrySet()) {
            ChangedFolders changedFolders = entry.getValue();
            if (changedFolders.isEmpty())
                continue;
            String accountId = entry.getKey();
            AccountKey key = new AccountKey(accountId);
            CalList list = mMemcachedLookup.get(key);
            if (list != null) {
                boolean updated = false;
                CalList newList = new CalList(list);
                for (Integer folderId : changedFolders.created) {
                    if (!list.contains(folderId)) {
                        updated = true;
                        newList.add(folderId);
                    }
                }
                for (Integer folderId : changedFolders.modified) {
                    if (list.contains(folderId))
                        updated = true;
                }
                for (Integer folderId : changedFolders.deleted) {
                    if (list.contains(folderId)) {
                        updated = true;
                        newList.remove(folderId);
                    }
                }
                // There was a change.  Increment the version and put back to cache.
                if (updated) {
                    newList.incrementSeq();
                    mMemcachedLookup.put(key, newList);
                }
            }
        }
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify calendar list cache.  Some cached data may become stale.", e);
    }
}
Also used : Message(com.zimbra.cs.mailbox.Message) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) Folder(com.zimbra.cs.mailbox.Folder) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) HashMap(java.util.HashMap) Map(java.util.Map) MemcachedMap(com.zimbra.common.util.memcached.MemcachedMap)

Example 49 with MailItem

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

the class CtagInfoCache method notifyCommittedChanges.

void notifyCommittedChanges(PendingModifications mods, int changeId) {
    int inboxFolder = Mailbox.ID_FOLDER_INBOX;
    Set<CalendarKey> keysToInvalidate = new HashSet<CalendarKey>();
    if (mods.created != null) {
        for (Map.Entry<ModificationKey, MailItem> entry : mods.created.entrySet()) {
            MailItem item = entry.getValue();
            if (item instanceof Message) {
                Message msg = (Message) item;
                if (msg.hasCalendarItemInfos() && msg.getFolderId() == inboxFolder) {
                    CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
                    keysToInvalidate.add(key);
                }
            }
        }
    }
    if (mods.modified != null) {
        for (Map.Entry<ModificationKey, Change> entry : mods.modified.entrySet()) {
            Change change = entry.getValue();
            Object whatChanged = change.what;
            if (whatChanged instanceof Folder) {
                Folder folder = (Folder) whatChanged;
                MailItem.Type viewType = folder.getDefaultView();
                if (viewType == MailItem.Type.APPOINTMENT || viewType == MailItem.Type.TASK) {
                    CalendarKey key = new CalendarKey(folder.getMailbox().getAccountId(), folder.getId());
                    keysToInvalidate.add(key);
                }
            } else if (whatChanged instanceof Message) {
                Message msg = (Message) whatChanged;
                if (msg.hasCalendarItemInfos()) {
                    if (msg.getFolderId() == inboxFolder || (change.why & Change.FOLDER) != 0) {
                        // If message was moved, we don't know which folder it was moved from.
                        // Just invalidate the Inbox because that's the only message folder we care
                        // about in calendaring.
                        CalendarKey key = new CalendarKey(msg.getMailbox().getAccountId(), inboxFolder);
                        keysToInvalidate.add(key);
                    }
                }
            }
        }
    }
    if (mods.deleted != null) {
        for (Entry<ModificationKey, Change> entry : mods.deleted.entrySet()) {
            Type type = (Type) entry.getValue().what;
            if (type == MailItem.Type.FOLDER) {
                // We only have item id.  Assume it's a folder id and issue a delete.
                String acctId = entry.getKey().getAccountId();
                if (acctId == null)
                    // just to be safe
                    continue;
                CalendarKey key = new CalendarKey(acctId, entry.getKey().getItemId());
                keysToInvalidate.add(key);
            }
        // Let's not worry about hard deletes of invite/reply emails.  It has no practical benefit.
        }
    }
    try {
        mMemcachedLookup.removeMulti(keysToInvalidate);
    } catch (ServiceException e) {
        ZimbraLog.calendar.warn("Unable to notify ctag info cache.  Some cached data may become stale.", e);
    }
}
Also used : Message(com.zimbra.cs.mailbox.Message) ModificationKey(com.zimbra.cs.session.PendingModifications.ModificationKey) Change(com.zimbra.cs.session.PendingModifications.Change) ZFolder(com.zimbra.client.ZFolder) Folder(com.zimbra.cs.mailbox.Folder) Type(com.zimbra.cs.mailbox.MailItem.Type) MailItem(com.zimbra.cs.mailbox.MailItem) Type(com.zimbra.cs.mailbox.MailItem.Type) ServiceException(com.zimbra.common.service.ServiceException) HashMap(java.util.HashMap) Map(java.util.Map) MemcachedMap(com.zimbra.common.util.memcached.MemcachedMap) HashSet(java.util.HashSet)

Example 50 with MailItem

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

the class ContentServlet method getCommand.

private void getCommand(HttpServletRequest req, HttpServletResponse resp, AuthToken token) throws ServletException, IOException {
    ItemId iid = null;
    try {
        iid = new ItemId(req.getParameter(PARAM_MSGID), (String) null);
    } catch (ServiceException e) {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errInvalidId, req));
        return;
    }
    String part = req.getParameter(PARAM_PART);
    String fmt = req.getParameter(PARAM_FORMAT);
    String dumpsterParam = req.getParameter(PARAM_DUMPSTER);
    boolean fromDumpster = dumpsterParam != null && !dumpsterParam.equals("0") && !dumpsterParam.equalsIgnoreCase("false");
    try {
        // need to proxy the fetch if the mailbox lives on another server
        if (!iid.isLocal()) {
            // wrong server; proxy to the right one...
            proxyServletRequest(req, resp, iid.getAccountId());
            return;
        }
        String authId = token.getAccountId();
        String accountId = iid.getAccountId() != null ? iid.getAccountId() : authId;
        AccountUtil.addAccountToLogContext(Provisioning.getInstance(), accountId, ZimbraLog.C_NAME, ZimbraLog.C_ID, token);
        if (!accountId.equalsIgnoreCase(authId))
            ZimbraLog.addToContext(ZimbraLog.C_AID, authId);
        Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(accountId);
        if (mbox == null) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errMailboxNotFound, req));
            return;
        }
        ZimbraLog.addMboxToContext(mbox.getId());
        MailItem item = mbox.getItemById(new OperationContext(token), iid.getId(), MailItem.Type.UNKNOWN, fromDumpster);
        if (item == null) {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errMessageNotFound, req));
            return;
        }
        try {
            if (part == null) {
                // they want the entire message...
                boolean sync = "1".equals(req.getParameter(PARAM_SYNC));
                StringBuffer hdr = new StringBuffer();
                if (sync) {
                    // for sync, return metadata as headers to avoid extra SOAP round-trips
                    resp.addHeader("X-Zimbra-Tags", TagUtil.getTagIdString(item));
                    resp.addHeader("X-Zimbra-Tag-Names", TagUtil.encodeTags(item.getTags()));
                    resp.addHeader("X-Zimbra-Flags", item.getFlagString());
                    resp.addHeader("X-Zimbra-Received", Long.toString(item.getDate()));
                    resp.addHeader("X-Zimbra-Modified", Long.toString(item.getChangeDate()));
                    // also return metadata inline in the message content for now
                    hdr.append("X-Zimbra-Tags: ").append(TagUtil.getTagIdString(item)).append("\n");
                    hdr.append("X-Zimbra-Tag-Names: ").append(TagUtil.encodeTags(item.getTags()));
                    hdr.append("X-Zimbra-Flags: ").append(item.getFlagString()).append("\n");
                    hdr.append("X-Zimbra-Received: ").append(item.getDate()).append("\n");
                    hdr.append("X-Zimbra-Modified: ").append(item.getChangeDate()).append("\n");
                }
                if (item instanceof Message) {
                    Message msg = (Message) item;
                    if (sync) {
                        resp.addHeader("X-Zimbra-Conv", Integer.toString(msg.getConversationId()));
                        hdr.append("X-Zimbra-Conv: ").append(msg.getConversationId()).append("\n");
                        resp.getOutputStream().write(hdr.toString().getBytes());
                    }
                    resp.setContentType(MimeConstants.CT_TEXT_PLAIN);
                    InputStream is = msg.getContentStream();
                    ByteUtil.copy(is, true, resp.getOutputStream(), false);
                } else if (item instanceof CalendarItem) {
                    CalendarItem calItem = (CalendarItem) item;
                    if (sync) {
                        resp.getOutputStream().write(hdr.toString().getBytes());
                    }
                    resp.setContentType(MimeConstants.CT_TEXT_PLAIN);
                    if (iid.hasSubpart()) {
                        int invId = iid.getSubpartId();
                        MimeMessage mm = calItem.getSubpartMessage(invId);
                        if (mm == null) {
                            // Backward compatibility for pre-5.0.16 ZDesktop: Build a MIME message on the fly.
                            Invite[] invs = calItem.getInvites(invId);
                            if (invs != null && invs.length > 0) {
                                Invite invite = invs[0];
                                mm = CalendarMailSender.createCalendarMessage(invite);
                            }
                        }
                        if (mm != null)
                            mm.writeTo(resp.getOutputStream());
                    } else {
                        InputStream is = calItem.getRawMessage();
                        if (is != null)
                            ByteUtil.copy(is, true, resp.getOutputStream(), false);
                    }
                }
                return;
            } else {
                MimePart mp = null;
                if (item instanceof Message) {
                    mp = getMimePart((Message) item, part);
                } else {
                    CalendarItem calItem = (CalendarItem) item;
                    if (iid.hasSubpart()) {
                        MimeMessage mbp = calItem.getSubpartMessage(iid.getSubpartId());
                        if (mbp != null)
                            mp = Mime.getMimePart(mbp, part);
                    } else {
                        mp = getMimePart(calItem, part);
                    }
                }
                if (mp != null) {
                    String contentType = mp.getContentType();
                    if (contentType == null) {
                        contentType = MimeConstants.CT_APPLICATION_OCTET_STREAM;
                    }
                    if (contentType.toLowerCase().startsWith(MimeConstants.CT_TEXT_HTML) && (FORMAT_DEFANGED_HTML.equals(fmt) || FORMAT_DEFANGED_HTML_NOT_IMAGES.equals(fmt))) {
                        sendbackDefangedHtml(mp, contentType, resp, fmt);
                    } else {
                        if (!isTrue(Provisioning.A_zimbraAttachmentsViewInHtmlOnly, mbox.getAccountId())) {
                            sendbackOriginalDoc(mp, contentType, req, resp);
                        } else {
                            req.setAttribute(ATTR_MIMEPART, mp);
                            req.setAttribute(ATTR_MSGDIGEST, item.getDigest());
                            req.setAttribute(ATTR_CONTENTURL, req.getRequestURL().toString());
                            RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(CONVERSION_PATH);
                            dispatcher.forward(req, resp);
                        }
                    }
                    return;
                }
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, L10nUtil.getMessage(MsgKey.errPartNotFound, req));
            }
        } catch (MessagingException e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        }
    } catch (NoSuchItemException e) {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND, L10nUtil.getMessage(MsgKey.errNoSuchItem, req));
    } catch (ServiceException e) {
        returnError(resp, e);
    } finally {
        ZimbraLog.clearContext();
    }
/*
         out.println("hello world "+req.getParameter("id"));
         out.println("path info: "+req.getPathInfo());
         out.println("pathtrans: "+req.getPathTranslated());
         */
}
Also used : OperationContext(com.zimbra.cs.mailbox.OperationContext) Message(com.zimbra.cs.mailbox.Message) MimeMessage(javax.mail.internet.MimeMessage) MessagingException(javax.mail.MessagingException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) NoSuchItemException(com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException) RequestDispatcher(javax.servlet.RequestDispatcher) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) MailItem(com.zimbra.cs.mailbox.MailItem) ServiceException(com.zimbra.common.service.ServiceException) Mailbox(com.zimbra.cs.mailbox.Mailbox) MimeMessage(javax.mail.internet.MimeMessage) MimePart(javax.mail.internet.MimePart) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Aggregations

MailItem (com.zimbra.cs.mailbox.MailItem)74 Mailbox (com.zimbra.cs.mailbox.Mailbox)36 ServiceException (com.zimbra.common.service.ServiceException)30 Folder (com.zimbra.cs.mailbox.Folder)23 MailServiceException (com.zimbra.cs.mailbox.MailServiceException)23 Message (com.zimbra.cs.mailbox.Message)19 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)17 ArrayList (java.util.ArrayList)17 IOException (java.io.IOException)16 OperationContext (com.zimbra.cs.mailbox.OperationContext)15 NoSuchItemException (com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException)14 Element (com.zimbra.common.soap.Element)13 CalendarItem (com.zimbra.cs.mailbox.CalendarItem)13 Account (com.zimbra.cs.account.Account)12 Document (com.zimbra.cs.mailbox.Document)12 ItemId (com.zimbra.cs.service.util.ItemId)11 HashMap (java.util.HashMap)11 ZMailbox (com.zimbra.client.ZMailbox)9 Contact (com.zimbra.cs.mailbox.Contact)9 HashSet (java.util.HashSet)9