Search in sources :

Example 1 with SafeSendFailedException

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

the class ParseMimeMessage method parseMimeMsgSoap.

/**
     * Given an {@code <m>} element from SOAP, return us a parsed {@link MimeMessage}, and also fill in the
     * {@link MimeMessageData} structure with information we parsed out of it (e.g. contained Invite, msgids, etc etc)
     *
     * @param msgElem the {@code <m>} element
     * @param additionalParts MimeBodyParts that we want to have added to the {@link MimeMessage} (ie things the server
     * is adding onto the message)
     * @param inviteParser Callback which handles {@code <inv>} embedded invite components
     * @param out Holds info about things we parsed out of the message that the caller might want to know about
     */
public static MimeMessage parseMimeMsgSoap(ZimbraSoapContext zsc, OperationContext octxt, Mailbox mbox, Element msgElem, MimeBodyPart[] additionalParts, InviteParser inviteParser, MimeMessageData out, boolean attachMessageFromCache) throws ServiceException {
    // msgElem == "<m>" E_MSG
    assert (msgElem.getName().equals(MailConstants.E_MSG));
    Account target = DocumentHandler.getRequestedAccount(zsc);
    ParseMessageContext ctxt = new ParseMessageContext();
    ctxt.out = out;
    ctxt.zsc = zsc;
    ctxt.octxt = octxt;
    ctxt.mbox = mbox;
    ctxt.use2231 = target.isPrefUseRfc2231();
    ctxt.defaultCharset = target.getPrefMailDefaultCharset();
    if (Strings.isNullOrEmpty(ctxt.defaultCharset)) {
        ctxt.defaultCharset = MimeConstants.P_CHARSET_UTF8;
    }
    try {
        MimeMessage mm = new Mime.FixedMimeMessage(JMSession.getSmtpSession(target));
        MimeMultipart mmp = null;
        Element partElem = msgElem.getOptionalElement(MailConstants.E_MIMEPART);
        Element attachElem = msgElem.getOptionalElement(MailConstants.E_ATTACH);
        Element inviteElem = msgElem.getOptionalElement(MailConstants.E_INVITE);
        boolean hasContent = (partElem != null || inviteElem != null || additionalParts != null);
        // || inviteElem != null || additionalParts!=null);
        boolean isMultipart = (attachElem != null);
        if (isMultipart) {
            // may need to change to "digest" later
            mmp = new ZMimeMultipart("mixed");
            mm.setContent(mmp);
        }
        // Grab the <inv> part now so we can stick it in a multipart/alternative if necessary
        MimeBodyPart[] alternatives = null;
        if (inviteElem != null) {
            int additionalLen = 0;
            if (additionalParts != null) {
                additionalLen += additionalParts.length;
            }
            alternatives = new MimeBodyPart[additionalLen + 1];
            int curAltPart = 0;
            // goes into the "content" subpart
            InviteParserResult result = inviteParser.parse(zsc, octxt, mbox.getAccount(), inviteElem);
            if (partElem != null && result.mCal != null) {
                // If textual content is provided and there's an invite,
                // set the text as DESCRIPTION of the iCalendar.  This helps
                // clients that ignore alternative text content and only
                // displays the DESCRIPTION specified in the iCalendar part.
                // (e.g. MS Entourage for Mac)
                String desc = getTextPlainContent(partElem);
                String html = getTextHtmlContent(partElem);
                result.mCal.addDescription(desc, html);
                if (result.mInvite != null) {
                    // It's possible the notes were given in <inv> node only, with no corresponding MIME parts.
                    if ((desc != null && desc.length() > 0) || (html != null && html.length() > 0)) {
                        result.mInvite.setDescription(desc, html);
                        if (desc != null && desc.length() > 0) {
                            result.mInvite.setFragment(Fragment.getFragment(desc, true));
                        }
                    }
                }
            }
            MimeBodyPart mbp = CalendarMailSender.makeICalIntoMimePart(result.mCal);
            alternatives[curAltPart++] = mbp;
            if (additionalParts != null) {
                for (int i = 0; i < additionalParts.length; i++) {
                    alternatives[curAltPart++] = additionalParts[i];
                }
            }
        } else {
            alternatives = additionalParts;
        }
        // handle the content from the client, if any
        if (hasContent) {
            setContent(mm, mmp, partElem != null ? partElem : inviteElem, alternatives, ctxt);
        }
        // attachments go into the toplevel "mixed" part
        if (isMultipart && attachElem != null) {
            handleAttachments(attachElem, mmp, ctxt, null, Part.ATTACHMENT, attachMessageFromCache);
        }
        // <m> attributes: id, f[lags], s[ize], d[ate], cid(conv-id), l(parent folder)
        // <m> child elements: <e> (email), <s> (subject), <f> (fragment), <mp>, <attach>
        MessageAddresses maddrs = new MessageAddresses();
        Set<String> headerNames = ImmutableSet.copyOf(Provisioning.getInstance().getConfig().getCustomMimeHeaderNameAllowed());
        for (Element elem : msgElem.listElements()) {
            String eName = elem.getName();
            if (eName.equals(MailConstants.E_ATTACH)) {
            // ignore it...
            } else if (eName.equals(MailConstants.E_MIMEPART)) {
            /* <mp> */
            // processMessagePart(mm, elem);
            } else if (eName.equals(MailConstants.E_EMAIL)) {
                /* <e> */
                maddrs.add(elem, ctxt.defaultCharset);
            } else if (eName.equals(MailConstants.E_IN_REPLY_TO)) {
            /* <irt> */
            // mm.setHeader("In-Reply-To", elem.getText());
            } else if (eName.equals(MailConstants.E_SUBJECT)) {
            /* <su> */
            // mm.setSubject(elem.getText(), "utf-8");
            } else if (eName.equals(MailConstants.E_FRAG)) {
                /* <f> */
                ZimbraLog.soap.debug("Ignoring message fragment data");
            } else if (eName.equals(MailConstants.E_INVITE)) {
            /* <inv> */
            // Already processed above.  Ignore it.
            } else if (eName.equals(MailConstants.E_CAL_TZ)) {
            /* <tz> */
            // Ignore as a special case.
            } else if (eName.equals(MailConstants.E_HEADER)) {
                // <h>
                String name = elem.getAttribute(MailConstants.A_NAME);
                if (headerNames.contains(name)) {
                    mm.addHeader(name, MimeHeader.escape(elem.getText(), Charsets.UTF_8, true));
                } else {
                    throw ServiceException.INVALID_REQUEST("header '" + name + "' not allowed", null);
                }
            } else {
                ZimbraLog.soap.warn("unsupported child element '%s' under parent %s", elem.getName(), msgElem.getName());
            }
        }
        // deal with things that can be either <m> attributes or subelements
        String subject = msgElem.getAttribute(MailConstants.E_SUBJECT, "");
        mm.setSubject(subject, CharsetUtil.checkCharset(subject, ctxt.defaultCharset));
        String irt = cleanReference(msgElem.getAttribute(MailConstants.E_IN_REPLY_TO, null));
        if (irt != null) {
            mm.setHeader("In-Reply-To", irt);
        }
        // can have no addresses specified if it's a draft...
        if (!maddrs.isEmpty()) {
            addAddressHeaders(mm, maddrs);
        }
        if (!hasContent && !isMultipart) {
            mm.setText("", MimeConstants.P_CHARSET_DEFAULT);
        }
        String flagStr = msgElem.getAttribute(MailConstants.A_FLAGS, "");
        if (flagStr.indexOf(Flag.toChar(Flag.ID_HIGH_PRIORITY)) != -1) {
            mm.addHeader("X-Priority", "1");
            mm.addHeader("Importance", "high");
        } else if (flagStr.indexOf(Flag.toChar(Flag.ID_LOW_PRIORITY)) != -1) {
            mm.addHeader("X-Priority", "5");
            mm.addHeader("Importance", "low");
        }
        // JavaMail tip: don't forget to call this, it is REALLY confusing.
        mm.saveChanges();
        return mm;
    } catch (UnsupportedEncodingException e) {
        throw ServiceException.FAILURE("UnsupportedEncodingExecption", e);
    } catch (SendFailedException e) {
        SafeSendFailedException ssfe = new SafeSendFailedException(e);
        throw ServiceException.FAILURE("SendFailure", ssfe);
    } catch (MessagingException e) {
        throw ServiceException.FAILURE("MessagingExecption", e);
    } catch (IOException e) {
        throw ServiceException.FAILURE("IOExecption", e);
    }
}
Also used : Account(com.zimbra.cs.account.Account) SendFailedException(javax.mail.SendFailedException) SafeSendFailedException(com.zimbra.cs.mailbox.MailSender.SafeSendFailedException) MessagingException(javax.mail.MessagingException) Element(com.zimbra.common.soap.Element) UnsupportedEncodingException(java.io.UnsupportedEncodingException) SafeSendFailedException(com.zimbra.cs.mailbox.MailSender.SafeSendFailedException) IOException(java.io.IOException) Mountpoint(com.zimbra.cs.mailbox.Mountpoint) ZMimeMessage(com.zimbra.common.zmime.ZMimeMessage) MimeMessage(javax.mail.internet.MimeMessage) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) MimeMultipart(javax.mail.internet.MimeMultipart) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) ZMimeBodyPart(com.zimbra.common.zmime.ZMimeBodyPart) MimeBodyPart(javax.mail.internet.MimeBodyPart)

Aggregations

Element (com.zimbra.common.soap.Element)1 ZMimeBodyPart (com.zimbra.common.zmime.ZMimeBodyPart)1 ZMimeMessage (com.zimbra.common.zmime.ZMimeMessage)1 ZMimeMultipart (com.zimbra.common.zmime.ZMimeMultipart)1 Account (com.zimbra.cs.account.Account)1 SafeSendFailedException (com.zimbra.cs.mailbox.MailSender.SafeSendFailedException)1 Mountpoint (com.zimbra.cs.mailbox.Mountpoint)1 IOException (java.io.IOException)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 MessagingException (javax.mail.MessagingException)1 SendFailedException (javax.mail.SendFailedException)1 MimeBodyPart (javax.mail.internet.MimeBodyPart)1 MimeMessage (javax.mail.internet.MimeMessage)1 MimeMultipart (javax.mail.internet.MimeMultipart)1