Search in sources :

Example 41 with AddressException

use of javax.mail.internet.AddressException in project zm-mailbox by Zimbra.

the class Mime method parseAddressHeader.

public static InternetAddress[] parseAddressHeader(String header, boolean expandGroups) {
    if (header == null || header.trim().isEmpty())
        return NO_ADDRESSES;
    header = header.trim();
    InternetAddress[] addresses;
    try {
        addresses = JavaMailInternetAddress.parseHeader(header, false);
    } catch (Throwable e) {
        // Catch everything in case MIME parser was not robust enough to handle a malformed header.
        if (e instanceof OutOfMemoryError) {
            Zimbra.halt("MIME parser failed: " + header, e);
        } else if (!(e instanceof AddressException)) {
            sLog.error("MIME parser failed: " + header, e);
        }
        try {
            return new InternetAddress[] { new JavaMailInternetAddress(null, header, MimeConstants.P_CHARSET_UTF8) };
        } catch (UnsupportedEncodingException e1) {
            return NO_ADDRESSES;
        }
    }
    if (!expandGroups)
        return addresses;
    boolean hasGroups = false;
    for (InternetAddress addr : addresses) {
        if (addr.isGroup()) {
            hasGroups = true;
            break;
        }
    }
    if (!hasGroups)
        return addresses;
    // if we're here, we need to expand at least one group...
    List<InternetAddress> expanded = new ArrayList<InternetAddress>();
    for (InternetAddress addr : addresses) {
        if (!addr.isGroup()) {
            expanded.add(addr);
        } else {
            try {
                InternetAddress[] members = addr.getGroup(false);
                if (members == null)
                    expanded.add(addr);
                else
                    for (InternetAddress member : members) expanded.add(member);
            } catch (AddressException e) {
                expanded.add(addr);
            }
        }
    }
    return expanded.toArray(new InternetAddress[expanded.size()]);
}
Also used : InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) AddressException(javax.mail.internet.AddressException) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException)

Example 42 with AddressException

use of javax.mail.internet.AddressException in project zm-mailbox by Zimbra.

the class SendInviteReply method handle.

@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Mailbox mbox = getRequestedMailbox(zsc);
    Account acct = getRequestedAccount(zsc);
    Account authAcct = getAuthenticatedAccount(zsc);
    boolean isAdmin = zsc.isUsingAdminPrivileges();
    OperationContext octxt = getOperationContext(zsc, context);
    boolean onBehalfOf = isOnBehalfOfRequest(zsc);
    ItemId iid = new ItemId(request.getAttribute(MailConstants.A_ID), zsc);
    int compNum = (int) request.getAttributeLong(MailConstants.A_CAL_COMPONENT_NUM);
    String verbStr = request.getAttribute(MailConstants.A_VERB);
    Verb verb = CalendarMailSender.parseVerb(verbStr);
    boolean isDecline = CalendarMailSender.VERB_DECLINE.equals(verb);
    boolean updateOrg = request.getAttributeBool(MailConstants.A_CAL_UPDATE_ORGANIZER, true);
    // Get the identity/persona being used in the reply.  It is set at the request level, but
    // let's also look for it in the <m> child element too, because that is the precedent in
    // the SendMsg request.  For SendInviteReply we have to insist it at request level because
    // <m> is an optional element.
    String identityId = request.getAttribute(MailConstants.A_IDENTITY_ID, null);
    if (identityId == null) {
        Element msgElem = request.getOptionalElement(MailConstants.E_MSG);
        if (msgElem != null)
            identityId = msgElem.getAttribute(MailConstants.A_IDENTITY_ID, null);
    }
    Element response = getResponseElement(zsc);
    boolean intendedForMe = true;
    Invite oldInv = null;
    int calItemId;
    int inviteMsgId;
    CalendarItem calItem = null;
    boolean wasInTrash = false;
    // calendar item (id="aaaa-nnnn") --- work in both cases
    if (iid.hasSubpart()) {
        // directly accepting the calendar item
        calItemId = iid.getId();
        inviteMsgId = iid.getSubpartId();
        calItem = safeGetCalendarItemById(mbox, octxt, iid.getId());
        if (calItem == null)
            throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
        oldInv = calItem.getInvite(inviteMsgId, compNum);
    } else {
        // accepting the message: go find the calendar item and then the invite
        inviteMsgId = iid.getId();
        Message msg = mbox.getMessageById(octxt, inviteMsgId);
        Message.CalendarItemInfo info = msg.getCalendarItemInfo(compNum);
        if (info == null)
            throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
        String intendedFor = msg.getCalendarIntendedFor();
        Account intendedAcct = null;
        if (intendedFor != null) {
            try {
                InternetAddress intendedForAddr = new JavaMailInternetAddress(intendedFor);
                intendedAcct = Provisioning.getInstance().get(AccountBy.name, intendedForAddr.getAddress());
            } catch (AddressException e) {
                throw ServiceException.INVALID_REQUEST("The intended account " + intendedFor + " is invalid", e);
            }
            if (intendedAcct == null) {
                throw ServiceException.INVALID_REQUEST("The intended account " + intendedFor + " was not found", null);
            }
            // Special case: intended account = me.
            if (intendedAcct.equals(mbox.getAccount()))
                intendedAcct = null;
            else
                intendedForMe = false;
        }
        if (intendedAcct != null) {
            // trace logging: let's just indicate we're replying to a remote appointment
            ZimbraLog.calendar.info("<SendInviteReply> (remote mbox) id=%s, verb=%s, notifyOrg=%s", new ItemIdFormatter(zsc).formatItemId(iid), verb.toString(), Boolean.toString(updateOrg));
            // Replying to a remote appointment
            calItem = null;
            calItemId = 0;
            ZMailbox zmbx = getRemoteZMailbox(octxt, authAcct, intendedAcct);
            // Try to add the appointment to remote mailbox.
            AddInviteResult addInviteResult = sendAddInvite(zmbx, octxt, msg);
            if (addInviteResult == null)
                throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
            // Forward the reply request.
            remoteSendInviteReply(zmbx, request, addInviteResult);
        } else {
            // Replying to a local appointment
            if (info.getInvite() != null) {
                calItem = mbox.getCalendarItemByUid(octxt, info.getInvite().getUid());
                wasInTrash = calItem != null && calItem.inTrash();
                if (calItem != null && !wasInTrash) {
                    Invite newInv = info.getInvite();
                    // If appointment exists, check if our invite has been outdated.
                    Invite curr = calItem.getInvite(newInv.getRecurId());
                    if (curr != null && !newInv.isSameOrNewerVersion(curr))
                        throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
                }
                Invite inv = info.getInvite().newCopy();
                Invite.setDefaultAlarm(inv, acct);
                inv.setMailItemId(inviteMsgId);
                // (TODO: Is it better to delete the existing appointment/instance when declining?)
                if (calItem != null || !isDecline) {
                    // Add the invite.  This will either create or update the appointment.
                    int folder;
                    boolean untrashing = wasInTrash && !isDecline;
                    if (calItem == null || untrashing) {
                        // If appointment/task doesn't exist, create in default folder.
                        // If it exists but is in Trash and is not a decline, move it out of Trash.
                        // If it's in trash and we're declining, leave it in trash.
                        folder = inv.isTodo() ? Mailbox.ID_FOLDER_TASKS : Mailbox.ID_FOLDER_CALENDAR;
                    } else {
                        folder = calItem.getFolderId();
                    }
                    ParsedMessage pm = new ParsedMessage(msg.getMimeMessage(false), false);
                    AddInviteData aid = mbox.addInvite(octxt, inv, folder, pm, false, untrashing, true);
                    if (aid == null)
                        throw ServiceException.FAILURE("Could not create/update calendar item", null);
                    calItemId = aid.calItemId;
                    // Refetch updated item.
                    calItem = safeGetCalendarItemById(mbox, octxt, aid.calItemId);
                    if (calItem == null)
                        throw ServiceException.FAILURE("Could not refetch created/updated calendar item", null);
                } else {
                    calItemId = 0;
                }
                oldInv = inv;
            } else if (info.calItemCreated()) {
                // legacy case (before we added Invite info to Message metadata)
                calItem = safeGetCalendarItemById(mbox, octxt, info.getCalendarItemId());
                if (calItem == null)
                    throw ServiceException.FAILURE("Missing invite data", null);
                // Must be for this mailbox
                calItemId = info.getCalendarItemId().getId();
                wasInTrash = calItem.inTrash();
                oldInv = calItem.getInvite(inviteMsgId, compNum);
            } else {
                throw ServiceException.FAILURE("Missing invite data", null);
            }
        }
    }
    if (intendedForMe) {
        if (oldInv == null)
            throw MailServiceException.INVITE_OUT_OF_DATE(iid.toString());
        if (calItem != null && (mbox.getEffectivePermissions(octxt, calItemId, MailItem.Type.UNKNOWN) & ACL.RIGHT_ACTION) == 0) {
            throw ServiceException.PERM_DENIED("You do not have ACTION rights for CalendarItem " + calItemId);
        }
        // check if invite organizer requested rsvp or not
        updateOrg = updateOrg && oldInv.getRsvp();
        // Don't allow creating/editing a private appointment on behalf of another user,
        // unless that other user is a calendar resource.
        boolean allowPrivateAccess = calItem != null ? calItem.allowPrivateAccess(authAcct, isAdmin) : true;
        boolean isCalendarResource = acct instanceof CalendarResource;
        if (!allowPrivateAccess && !oldInv.isPublic() && !isCalendarResource)
            throw ServiceException.PERM_DENIED("Cannot reply to a private appointment/task on behalf of another user");
        // see if there is a specific Exception being referenced by this reply...
        Element exc = request.getOptionalElement(MailConstants.E_CAL_EXCEPTION_ID);
        ParsedDateTime exceptDt = null;
        if (exc != null) {
            TimeZoneMap tzmap = oldInv.getTimeZoneMap();
            Element tzElem = request.getOptionalElement(MailConstants.E_CAL_TZ);
            ICalTimeZone tz = null;
            if (tzElem != null) {
                tz = CalendarUtils.parseTzElement(tzElem);
                tzmap.add(tz);
            }
            exceptDt = CalendarUtils.parseDateTime(exc, tzmap);
        } else if (oldInv.hasRecurId()) {
            exceptDt = oldInv.getRecurId().getDt();
        }
        // trace logging
        String calItemIdStr = calItem != null ? Integer.toString(calItem.getId()) : "none";
        String folderIdStr = calItem != null ? Integer.toString(calItem.getFolderId()) : "none";
        if (exceptDt == null)
            ZimbraLog.calendar.info("<SendInviteReply> id=%s, folderId=%s, verb=%s, notifyOrg=%s, subject=\"%s\", UID=%s", calItemIdStr, folderIdStr, verb.toString(), Boolean.toString(updateOrg), oldInv.isPublic() ? oldInv.getName() : "(private)", oldInv.getUid());
        else
            ZimbraLog.calendar.info("<SendInviteReply> id=%s, folderId=%s, verb=%s, notifyOrg=%s, subject=\"%s\", UID=%s, recurId=%s", calItemIdStr, folderIdStr, verb.toString(), Boolean.toString(updateOrg), oldInv.isPublic() ? oldInv.getName() : "(private)", oldInv.getUid(), exceptDt.getUtcString());
        // exception instance first.  Then reply to it.
        if (calItem != null && oldInv.isRecurrence() && exceptDt != null) {
            Invite localException = oldInv.makeInstanceInvite(exceptDt);
            long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
            localException.setDtStamp(now);
            String partStat = verb.getXmlPartStat();
            localException.setPartStat(partStat);
            ZAttendee at = localException.getMatchingAttendee(acct, identityId);
            if (at != null)
                at.setPartStat(partStat);
            // Carry over the MimeMessage/ParsedMessage to preserve any attachments.
            MimeMessage mmInv = calItem.getSubpartMessage(oldInv.getMailItemId());
            ParsedMessage pm = mmInv != null ? new ParsedMessage(mmInv, false) : null;
            int folder;
            boolean untrashing = wasInTrash && !isDecline;
            if (untrashing) {
                // If it exists but is in Trash and is not a decline, move it out of Trash.
                // If it's in trash and we're declining, leave it in trash.
                folder = localException.isTodo() ? Mailbox.ID_FOLDER_TASKS : Mailbox.ID_FOLDER_CALENDAR;
            } else {
                folder = calItem.getFolderId();
            }
            mbox.addInvite(octxt, localException, folder, pm, true, untrashing, true);
            // Refetch the updated calendar item and set oldInv to refetched local exception instance.
            calItem = safeGetCalendarItemById(mbox, octxt, calItemId);
            if (calItem == null)
                throw MailServiceException.NO_SUCH_CALITEM(iid.toString(), "Could not find calendar item");
            oldInv = calItem.getInvite(new RecurId(exceptDt, RecurId.RANGE_NONE));
        }
        if (updateOrg && oldInv.hasOrganizer()) {
            Locale locale;
            Account organizer = oldInv.getOrganizerAccount();
            if (organizer != null)
                locale = organizer.getLocale();
            else
                locale = !onBehalfOf ? acct.getLocale() : authAcct.getLocale();
            String subject;
            if (!allowPrivateAccess && !oldInv.isPublic())
                subject = L10nUtil.getMessage(MsgKey.calendarSubjectWithheld, locale);
            else
                subject = oldInv.getName();
            String replySubject = CalendarMailSender.getReplySubject(verb, subject, locale);
            CalSendData csd = new CalSendData();
            csd.mOrigId = new ItemId(mbox, oldInv.getMailItemId());
            csd.mReplyType = MailSender.MSGTYPE_REPLY;
            csd.mInvite = CalendarMailSender.replyToInvite(acct, identityId, authAcct, onBehalfOf, allowPrivateAccess, oldInv, verb, replySubject, exceptDt);
            ZVCalendar iCal = csd.mInvite.newToICalendar(true);
            ParseMimeMessage.MimeMessageData parsedMessageData = new ParseMimeMessage.MimeMessageData();
            // did they specify a custom <m> message?  If so, then we don't have to build one...
            Element msgElem = request.getOptionalElement(MailConstants.E_MSG);
            if (msgElem != null) {
                String text = ParseMimeMessage.getTextPlainContent(msgElem);
                String html = ParseMimeMessage.getTextHtmlContent(msgElem);
                iCal.addDescription(text, html);
                MimeBodyPart[] mbps = new MimeBodyPart[1];
                mbps[0] = CalendarMailSender.makeICalIntoMimePart(iCal);
                // the <inv> element is *NOT* allowed -- we always build it manually
                // based on the params to the <SendInviteReply> and stick it in the
                // mbps (additionalParts) parameter...
                csd.mMm = ParseMimeMessage.parseMimeMsgSoap(zsc, octxt, mbox, msgElem, mbps, ParseMimeMessage.NO_INV_ALLOWED_PARSER, parsedMessageData);
            } else {
                // build a default "Accepted" response
                if (!(acct instanceof CalendarResource)) {
                    csd.mMm = CalendarMailSender.createDefaultReply(acct, identityId, authAcct, identityId, isAdmin, onBehalfOf, calItem, oldInv, null, replySubject, verb, null, iCal);
                } else {
                    // different template for calendar resources
                    RecurId rid = oldInv.getRecurId();
                    ParsedDateTime ridDt = rid != null ? rid.getDt() : null;
                    Invite replyInv = CalendarMailSender.replyToInvite(acct, authAcct, onBehalfOf, allowPrivateAccess, oldInv, verb, replySubject, ridDt);
                    MimeMessage mmInv = calItem.getSubpartMessage(oldInv.getMailItemId());
                    csd.mMm = CalendarMailSender.createResourceAutoReply(octxt, identityId, identityId, mbox, verb, false, null, calItem, oldInv, new Invite[] { replyInv }, mmInv, true);
                }
            }
            int apptFolderId;
            if (calItem != null)
                apptFolderId = calItem.getFolderId();
            else
                apptFolderId = oldInv.isTodo() ? Mailbox.ID_FOLDER_TASKS : Mailbox.ID_FOLDER_CALENDAR;
            MailSendQueue sendQueue = new MailSendQueue();
            try {
                sendCalendarMessage(zsc, octxt, apptFolderId, acct, mbox, csd, response, sendQueue);
            } finally {
                sendQueue.send();
            }
        }
        RecurId recurId = null;
        if (exceptDt != null) {
            recurId = new RecurId(exceptDt, RecurId.RANGE_NONE);
        }
        ZAttendee me = oldInv.getMatchingAttendee(acct);
        String cnStr = null;
        String addressStr = acct.getName();
        String role = IcalXmlStrMap.ROLE_OPT_PARTICIPANT;
        int seqNo = oldInv.getSeqNo();
        long dtStamp = oldInv.getDTStamp();
        if (me != null) {
            if (me.hasCn()) {
                cnStr = me.getCn();
            }
            addressStr = me.getAddress();
            if (me.hasRole()) {
                role = me.getRole();
            }
        }
        if (calItem != null)
            mbox.modifyPartStat(octxt, calItemId, recurId, cnStr, addressStr, null, role, verb.getXmlPartStat(), Boolean.FALSE, seqNo, dtStamp);
    }
    // move the invite to the Trash if the user wants it
    if (deleteInviteOnReply(acct)) {
        try {
            if (onBehalfOf) {
                // HACK: Run the move in the context of the organizer
                // mailbox because the authenticated account doesn't
                // have rights on Inbox and Trash folders.
                octxt = new OperationContext(mbox);
            }
            mbox.move(octxt, inviteMsgId, MailItem.Type.MESSAGE, Mailbox.ID_FOLDER_TRASH);
        } catch (MailServiceException.NoSuchItemException nsie) {
            ZimbraLog.calendar.debug("can't move nonexistent invite to Trash: " + inviteMsgId);
        }
    }
    return response;
}
Also used : Locale(java.util.Locale) Account(com.zimbra.cs.account.Account) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) Message(com.zimbra.cs.mailbox.Message) MimeMessage(javax.mail.internet.MimeMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) ItemIdFormatter(com.zimbra.cs.service.util.ItemIdFormatter) AddInviteData(com.zimbra.cs.mailbox.Mailbox.AddInviteData) Element(com.zimbra.common.soap.Element) RecurId(com.zimbra.cs.mailbox.calendar.RecurId) ItemId(com.zimbra.cs.service.util.ItemId) CalendarItem(com.zimbra.cs.mailbox.CalendarItem) ZVCalendar(com.zimbra.common.calendar.ZCalendar.ZVCalendar) ZMailbox(com.zimbra.client.ZMailbox) Mailbox(com.zimbra.cs.mailbox.Mailbox) ZMailbox(com.zimbra.client.ZMailbox) MimeMessage(javax.mail.internet.MimeMessage) Verb(com.zimbra.cs.mailbox.calendar.CalendarMailSender.Verb) AddressException(javax.mail.internet.AddressException) TimeZoneMap(com.zimbra.common.calendar.TimeZoneMap) ParsedDateTime(com.zimbra.common.calendar.ParsedDateTime) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) CalendarResource(com.zimbra.cs.account.CalendarResource) OperationContext(com.zimbra.cs.mailbox.OperationContext) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) ZimbraSoapContext(com.zimbra.soap.ZimbraSoapContext) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) MimeBodyPart(javax.mail.internet.MimeBodyPart) Invite(com.zimbra.cs.mailbox.calendar.Invite) ICalTimeZone(com.zimbra.common.calendar.ICalTimeZone)

Example 43 with AddressException

use of javax.mail.internet.AddressException in project zm-mailbox by Zimbra.

the class ZimbraMailAdapter method handleIDN.

private List<String> handleIDN(String headerName, String[] headers) {
    List<String> hdrs = new ArrayList<String>();
    for (String header : headers) {
        boolean altered = false;
        if (header.contains(IDNUtil.ACE_PREFIX)) {
            // handle multiple addresses in a header
            StringTokenizer st = new StringTokenizer(header, ",;", true);
            StringBuffer addrs = new StringBuffer();
            while (st.hasMoreTokens()) {
                String address = st.nextToken();
                String delim = st.hasMoreTokens() ? st.nextToken() : "";
                try {
                    javax.mail.internet.InternetAddress inetAddr = new JavaMailInternetAddress(address);
                    String addr = inetAddr.getAddress();
                    String unicodeAddr = IDNUtil.toUnicode(addr);
                    if (unicodeAddr.equalsIgnoreCase(addr)) {
                        addrs.append(address).append(delim);
                    } else {
                        altered = true;
                        // put the unicode addr back to the address
                        inetAddr.setAddress(unicodeAddr);
                        addrs.append(inetAddr.toString()).append(delim);
                    }
                } catch (AddressException e) {
                    ZimbraLog.filter.warn("handleIDN encountered invalid address " + address + "in header " + headerName);
                    // put back the orig address
                    addrs.append(address).append(delim);
                }
            }
            // if altered, add the altered value
            if (altered) {
                String unicodeAddrs = addrs.toString();
                ZimbraLog.filter.debug("handleIDN added value " + unicodeAddrs + " for header " + headerName);
                hdrs.add(unicodeAddrs);
            }
        }
        // always put back the orig value
        hdrs.add(header);
    }
    return hdrs;
}
Also used : StringTokenizer(java.util.StringTokenizer) AddressException(javax.mail.internet.AddressException) ArrayList(java.util.ArrayList) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress)

Example 44 with AddressException

use of javax.mail.internet.AddressException in project zm-mailbox by Zimbra.

the class NotifyMailto method execute.

/**
     * Execute RFC Compliant notify
     * @param mail The ZimbraMailAdapter
     * @param arguments The Sieve Arguments
     * @param context The Sieve Context
     * @throws SyntaxException
     */
private Object execute(MailAdapter mail, Arguments arguments, SieveContext context) throws SyntaxException {
    if (!(mail instanceof ZimbraMailAdapter)) {
        return null;
    }
    ZimbraMailAdapter mailAdapter = (ZimbraMailAdapter) mail;
    /*
         * RFC 5435 3.1. Notify Action
         * usage: notify [":from" string]
         *        [":importance" <"1" / "2" / "3">]
         *        [":options" string-list]
         *        [":message" string]
         *        <method: string>
         */
    String from = null;
    int importance = 0;
    String message = null;
    String method = null;
    String mailto = null;
    Map<String, String> options = null;
    Map<String, List<String>> mailtoParams = null;
    ListIterator<Argument> argumentsIter = arguments.getArgumentList().listIterator();
    boolean stop = false;
    // Tag processing
    while (!stop && argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof TagArgument) {
            final String tag = ((TagArgument) argument).getTag();
            if (from == null && NOTIFY_FROM.equals(tag)) {
                // The next argument must be a string
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_FROM);
                        }
                        String email = FilterUtil.replaceVariables(mailAdapter, (String) stringList.get(0));
                        // Validate email address using javax.mail.internet.InternetAddress
                        try {
                            InternetAddress addr = new InternetAddress(email);
                            addr.validate();
                            from = email;
                        } catch (AddressException ex) {
                            // if the :from addr is not valid, the FilterUtil.notifyMailto() method takes
                            // care of the From header before composing the notification message.
                            ZimbraLog.filter.info("The value of the \":from\" [" + email + "] is not valid");
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_FROM);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_FROM);
                }
            } else if (importance == 0 && NOTIFY_IMPORTANCE.equals(tag)) {
                // The next argument must be a number
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_IMPORTANCE);
                        }
                        String strImportance = (String) stringList.get(0);
                        FilterUtil.replaceVariables(mailAdapter, strImportance);
                        importance = Integer.parseInt(strImportance);
                        if (!(importance == 1 || importance == 2 || importance == 3)) {
                            throw new SyntaxException("Expecting an integer number (1, 2, 3) for " + NOTIFY_IMPORTANCE);
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_IMPORTANCE);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_IMPORTANCE);
                }
            } else if (options == null && NOTIFY_OPTIONS.equals(tag)) {
                // The next argument must be a string-list of options "<optionname>=<value>[,<optionname>=<value]*"
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> listOptions = ((StringListArgument) argument).getList();
                        if (listOptions.size() == 0) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_OPTIONS);
                        }
                        options = new HashMap<String, String>();
                        for (String option : listOptions) {
                            String[] token = option.split("=");
                            String key = null;
                            String value = null;
                            if (token.length == 2) {
                                key = token[0];
                                value = token[1];
                            } else if (token.length == 1) {
                                key = token[0];
                                value = "";
                            } else {
                                key = "";
                                value = "";
                            }
                            key = FilterUtil.replaceVariables(mailAdapter, key);
                            value = FilterUtil.replaceVariables(mailAdapter, value);
                            options.put(key, value);
                        }
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_OPTIONS);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_OPTIONS);
                }
            } else if (message == null && NOTIFY_MESSAGE.equals(tag)) {
                // The next argment must be a string
                if (argumentsIter.hasNext()) {
                    argument = argumentsIter.next();
                    if (argument instanceof StringListArgument) {
                        List<String> stringList = ((StringListArgument) argument).getList();
                        if (stringList.size() != 1) {
                            throw new SyntaxException("Expecting exactly one String for " + NOTIFY_MESSAGE);
                        }
                        message = FilterUtil.replaceVariables(mailAdapter, (String) stringList.get(0));
                    } else {
                        throw new SyntaxException("Expecting a StringList for " + NOTIFY_MESSAGE);
                    }
                } else {
                    throw new SyntaxException("Expecting a parameter for " + NOTIFY_MESSAGE);
                }
            }
        } else {
            // Stop when a non-tag argument is encountered
            argumentsIter.previous();
            stop = true;
        }
    }
    // The next argument MUST be a <method: string>
    if (argumentsIter.hasNext()) {
        Argument argument = argumentsIter.next();
        if (argument instanceof StringListArgument) {
            List<String> stringList = ((StringListArgument) argument).getList();
            if (stringList.size() != 1) {
                throw new SyntaxException("Expecting exactly one String");
            }
            method = (String) stringList.get(0);
        } else {
            throw new SyntaxException("Expecting a StringList");
        }
    }
    if (method == null) {
        throw context.getCoordinate().syntaxException("Expecting a method string");
    } else {
        method = FilterUtil.replaceVariables(mailAdapter, method);
    }
    mailtoParams = new HashMap<String, List<String>>();
    try {
        URL url = new URL(method);
        mailto = FilterUtil.replaceVariables(mailAdapter, url.getPath());
        String query = url.getQuery();
        if (!StringUtil.isNullOrEmpty(query)) {
            String[] params = query.split("&");
            for (String param : params) {
                String[] token = param.split("=");
                if (token.length > 2) {
                    throw new SyntaxException("'mailto' method syntax error: too many parameters");
                } else {
                    if (StringUtils.isEmpty(token[0])) {
                        throw new SyntaxException("'mailto' method syntax error: empty parameter name");
                    }
                    FilterUtil.headerNameHasSpace(token[0]);
                }
                // If the value or parameter name is URL encoded, it should be
                // decoded.  If it is not even URL encoded, more or less decoding
                // the string does not do harm the contents.
                String headerName = null;
                String headerValue = null;
                try {
                    headerName = URLDecoder.decode(token[0].toLowerCase(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                // No exception should be thrown because the charset is always "UTF-8"
                } catch (IllegalArgumentException e) {
                    headerName = token[0].toLowerCase();
                }
                if (token.length == 1) {
                    // The value must be empty
                    headerValue = "";
                } else {
                    headerValue = token[1];
                }
                try {
                    headerValue = URLDecoder.decode(headerValue, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                // No exception should be thrown because the charset is always "UTF-8"
                } catch (IllegalArgumentException e) {
                // Use token[1] as is
                }
                if (!mailtoParams.containsKey(headerName)) {
                    // Create a new entry for a header
                    List<String> value = new ArrayList<String>();
                    value.add(headerValue);
                    mailtoParams.put(headerName, value);
                } else {
                    // Some headers, such as to or cc fields, can be specified multiple times
                    mailtoParams.get(headerName).add(headerValue);
                }
            }
        }
    } catch (MalformedURLException e) {
        throw new SyntaxException("'mailto' method syntax error", e);
    }
    mail.addAction(new ActionNotifyMailto(from, options, importance, message, mailto, mailtoParams));
    return null;
}
Also used : InternetAddress(javax.mail.internet.InternetAddress) MalformedURLException(java.net.MalformedURLException) Argument(org.apache.jsieve.Argument) StringListArgument(org.apache.jsieve.StringListArgument) TagArgument(org.apache.jsieve.TagArgument) ArrayList(java.util.ArrayList) UnsupportedEncodingException(java.io.UnsupportedEncodingException) StringListArgument(org.apache.jsieve.StringListArgument) URL(java.net.URL) SyntaxException(org.apache.jsieve.exception.SyntaxException) TagArgument(org.apache.jsieve.TagArgument) AddressException(javax.mail.internet.AddressException) ArrayList(java.util.ArrayList) List(java.util.List) ZimbraMailAdapter(com.zimbra.cs.filter.ZimbraMailAdapter)

Example 45 with AddressException

use of javax.mail.internet.AddressException in project zm-mailbox by Zimbra.

the class CalendarMailSender method sendInviteDeniedMessage.

public static void sendInviteDeniedMessage(final OperationContext octxt, Account fromAccount, Account senderAccount, boolean onBehalfOf, boolean allowPrivateAccess, final Mailbox mbox, final ItemId origMsgId, String toEmail, Invite inv) throws ServiceException {
    Address toAddr;
    try {
        toAddr = new JavaMailInternetAddress(toEmail);
    } catch (AddressException e) {
        throw ServiceException.FAILURE("Bad address: " + toEmail, e);
    }
    MsgKey bodyTextKey;
    if (fromAccount instanceof CalendarResource)
        bodyTextKey = MsgKey.calendarResourceDefaultReplyPermissionDenied;
    else
        bodyTextKey = MsgKey.calendarUserReplyPermissionDenied;
    final MimeMessage mm = createCalendarInviteDeniedMessage(fromAccount, senderAccount, onBehalfOf, allowPrivateAccess, toAddr, inv, bodyTextKey);
    // Send in a separate thread to avoid nested transaction error when saving a copy to Sent folder.
    Runnable r = new Runnable() {

        @Override
        public void run() {
            try {
                MailSender mailSender = getCalendarMailSender(mbox).setSendPartial(true);
                mailSender.sendMimeMessage(octxt, mbox, true, mm, null, origMsgId, MailSender.MSGTYPE_REPLY, null, false);
            } catch (ServiceException e) {
                ZimbraLog.calendar.warn("Ignoring error while sending permission-denied auto reply", e);
            } catch (OutOfMemoryError e) {
                Zimbra.halt("OutOfMemoryError while sending permission-denied auto reply", e);
            }
        }
    };
    Thread senderThread = new Thread(r, "CalendarPermDeniedReplySender");
    senderThread.setDaemon(true);
    senderThread.start();
}
Also used : Address(javax.mail.Address) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ServiceException(com.zimbra.common.service.ServiceException) MailServiceException(com.zimbra.cs.mailbox.MailServiceException) ZMimeMessage(com.zimbra.common.zmime.ZMimeMessage) MimeMessage(javax.mail.internet.MimeMessage) AddressException(javax.mail.internet.AddressException) MsgKey(com.zimbra.common.util.L10nUtil.MsgKey) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) MailSender(com.zimbra.cs.mailbox.MailSender) CalendarResource(com.zimbra.cs.account.CalendarResource)

Aggregations

AddressException (javax.mail.internet.AddressException)46 InternetAddress (javax.mail.internet.InternetAddress)37 MimeMessage (javax.mail.internet.MimeMessage)18 JavaMailInternetAddress (com.zimbra.common.mime.shim.JavaMailInternetAddress)17 MessagingException (javax.mail.MessagingException)15 IOException (java.io.IOException)9 ArrayList (java.util.ArrayList)9 Date (java.util.Date)7 Address (javax.mail.Address)7 ZMimeMessage (com.zimbra.common.zmime.ZMimeMessage)5 UnsupportedEncodingException (java.io.UnsupportedEncodingException)5 MimeMultipart (javax.mail.internet.MimeMultipart)5 Properties (java.util.Properties)4 Session (javax.mail.Session)4 MimeBodyPart (javax.mail.internet.MimeBodyPart)4 ServiceException (com.zimbra.common.service.ServiceException)3 Account (com.zimbra.cs.account.Account)3 Invite (com.zimbra.cs.mailbox.calendar.Invite)3 ZAttendee (com.zimbra.cs.mailbox.calendar.ZAttendee)3 Locale (java.util.Locale)3