Search in sources :

Example 1 with JavaMailInternetAddress

use of com.zimbra.common.mime.shim.JavaMailInternetAddress in project zm-mailbox by Zimbra.

the class AppendMessage method store.

private int store(Mailbox mbox, Folder folder) throws ImapSessionClosedException, ServiceException, IOException {
    boolean idxAttach = mbox.attachmentsIndexingEnabled();
    Long receivedDate = date != null ? date.getTime() : null;
    ParsedMessage pm = new ParsedMessage(content, receivedDate, idxAttach);
    try {
        if (!pm.getSender().isEmpty()) {
            InternetAddress ia = new JavaMailInternetAddress(pm.getSender());
            if (AccountUtil.addressMatchesAccountOrSendAs(mbox.getAccount(), ia.getAddress())) {
                flags |= Flag.BITMASK_FROM_ME;
            }
        }
    } catch (Exception e) {
    }
    DeliveryOptions dopt = new DeliveryOptions().setFolderId(folder).setNoICal(true).setFlags(flags).setTags(tags);
    Message msg = mbox.addMessage(handler.getContext(), pm, dopt, null);
    if (msg != null && sflags != 0 && handler.getState() == ImapHandler.State.SELECTED) {
        ImapFolder selectedFolder = handler.getSelectedFolder();
        //   (note that this leaves session flags unset on remote appended messages)
        if (selectedFolder != null) {
            ImapMessage i4msg = selectedFolder.getById(msg.getId());
            if (i4msg != null) {
                i4msg.setSessionFlags(sflags, selectedFolder);
            }
        }
    }
    return msg == null ? -1 : msg.getId();
}
Also used : InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) Message(com.zimbra.cs.mailbox.Message) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) ParsedMessage(com.zimbra.cs.mime.ParsedMessage) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) DeliveryOptions(com.zimbra.cs.mailbox.DeliveryOptions) MessagingException(javax.mail.MessagingException) ServiceException(com.zimbra.common.service.ServiceException) ParseException(java.text.ParseException) IOException(java.io.IOException)

Example 2 with JavaMailInternetAddress

use of com.zimbra.common.mime.shim.JavaMailInternetAddress in project zm-mailbox by Zimbra.

the class CalendarItem method processNewInviteReply.

boolean processNewInviteReply(Invite reply, String sender) throws ServiceException {
    List<ZAttendee> attendees = reply.getAttendees();
    String senderAddress = null;
    if (sender != null && !sender.isEmpty()) {
        try {
            JavaMailInternetAddress address = new JavaMailInternetAddress(sender);
            senderAddress = address.getAddress();
        } catch (AddressException e) {
        // ignore invalid sender address.
        }
    }
    if (senderAddress != null && !attendees.isEmpty()) {
        AccountAddressMatcher acctMatcher = null;
        Account acct = Provisioning.getInstance().get(AccountBy.name, senderAddress);
        if (acct != null) {
            acctMatcher = new AccountAddressMatcher(acct);
        }
        Iterator<ZAttendee> iter = attendees.iterator();
        while (iter.hasNext()) {
            ZAttendee att = iter.next();
            // Remove the attendee if not same as the sender.
            if (!(att.addressMatches(senderAddress) || (acctMatcher != null && acctMatcher.matches(att.getAddress())))) {
                iter.remove();
            }
        }
    }
    // trace logging
    ZAttendee att1 = !attendees.isEmpty() ? attendees.get(0) : null;
    if (att1 != null) {
        String ptst = IcalXmlStrMap.sPartStatMap.toIcal(att1.getPartStat());
        if (!reply.hasRecurId())
            ZimbraLog.calendar.info("Processing CalendarItem reply: attendee=%s, partstat=%s, id=%d, folderId=%d, subject=\"%s\", UID=%s", att1.getAddress(), ptst, mId, getFolderId(), reply.isPublic() ? reply.getName() : "(private)", mUid);
        else
            ZimbraLog.calendar.info("Processing CalendarItem reply: attendee=%s, partstat=%s, id=%d, folderId=%d, subject=\"%s\", UID=%s, recurId=%s", att1.getAddress(), ptst, mId, getFolderId(), reply.isPublic() ? reply.getName() : "(private)", mUid, reply.getRecurId().getDtZ());
    }
    // Require private access permission only when we're replying to a private series/instance.
    boolean requirePrivateCheck = requirePrivateCheck(reply);
    OperationContext octxt = getMailbox().getOperationContext();
    Account authAccount = octxt != null ? octxt.getAuthenticatedUser() : null;
    boolean asAdmin = octxt != null ? octxt.isUsingAdminPrivileges() : false;
    if (!canAccess(ACL.RIGHT_ACTION, authAccount, asAdmin, requirePrivateCheck))
        throw ServiceException.PERM_DENIED("you do not have sufficient permissions to change this appointment/task's state");
    boolean dirty = false;
    // unique ID: UID+RECURRENCE_ID
    // See RFC2446: 2.1.5 Message Sequencing
    // UID already matches...next check if RecurId matches
    // if so, then seqNo is next
    // finally use DTStamp
    Invite matchingInvite = matchingInvite(reply.getRecurId());
    if (matchingInvite != null) {
        //             up to date with the organizer's event, provided there were no major changes.
        if ((matchingInvite.isOrganizer() && (matchingInvite.getLastFullSeqNo() > reply.getSeqNo())) || (!matchingInvite.isOrganizer() && (matchingInvite.getSeqNo() > reply.getSeqNo()))) {
            sLog.info("Invite-Reply %s is outdated (Calendar entry has higher SEQUENCE), ignoring!", reply);
            return false;
        }
    // maybeStoreNewReply does some further checks which might invalidate this reply
    // so, postpone updating attendee information until after that.
    }
    // they must be replying to a arbitrary instance)
    for (ZAttendee at : attendees) {
        if (mReplyList.maybeStoreNewReply(reply, at, this))
            dirty = true;
    }
    if (!dirty) {
        sLog.info("Invite-Reply %s is outdated ignoring!", reply);
        return false;
    }
    if (matchingInvite != null) {
        matchingInvite.updateMatchingAttendeesFromReply(reply);
        updateLocalExceptionsWhichMatchSeriesReply(reply);
    } else {
        createPseudoExceptionForSingleInstanceReplyIfNecessary(reply);
    }
    saveMetadata();
    return true;
}
Also used : Account(com.zimbra.cs.account.Account) AccountAddressMatcher(com.zimbra.cs.util.AccountUtil.AccountAddressMatcher) ZAttendee(com.zimbra.cs.mailbox.calendar.ZAttendee) AddressException(javax.mail.internet.AddressException) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) Invite(com.zimbra.cs.mailbox.calendar.Invite)

Example 3 with JavaMailInternetAddress

use of com.zimbra.common.mime.shim.JavaMailInternetAddress in project zm-mailbox by Zimbra.

the class FilterUtil method notifyMailto.

public static void notifyMailto(LmtpEnvelope envelope, OperationContext octxt, Mailbox mailbox, ParsedMessage parsedMessage, String from, int importance, Map<String, String> options, String message, String mailto, Map<String, List<String>> mailtoParams) throws MessagingException, ServiceException {
    // X-Zimbra-Forwarded
    MimeMessage mimeMessage = parsedMessage.getMimeMessage();
    if (isMailLoop(mailbox, mimeMessage, new String[] { HEADER_FORWARDED, HEADER_AUTO_SUBMITTED })) {
        String error = String.format("Detected a mail loop for message %s while notifying", Mime.getMessageID(mimeMessage));
        throw ServiceException.FAILURE(error, null);
    }
    Account account = mailbox.getAccount();
    MimeMessage notification = new Mime.FixedMimeMessage(JMSession.getSmtpSession(account));
    MailSender mailSender = mailbox.getMailSender().setSaveToSent(false);
    mailSender.setRedirectMode(true);
    // add the forwarded header account names to detect the mail loop between accounts
    for (String headerFwdAccountName : Mime.getHeaders(mimeMessage, HEADER_FORWARDED)) {
        notification.addHeader(HEADER_FORWARDED, headerFwdAccountName);
    }
    notification.addHeader(HEADER_FORWARDED, account.getName());
    // Envelope FROM
    // RFC 5436 2.7. (1st item of the 'guidelines')
    String originalEnvelopeFrom = envelope == null ? null : envelope.getSender().getEmailAddress();
    if (originalEnvelopeFrom == null) {
        // Whenever the envelope FROM of the original message is <>, set <> to the notification message too
        mailSender.setEnvelopeFrom("<>");
    } else if (!StringUtil.isNullOrEmpty(from)) {
        List<com.zimbra.common.mime.InternetAddress> addr = com.zimbra.common.mime.InternetAddress.parseHeader(from);
        String escapedFrom = StringEscapeUtils.escapeJava(addr.get(0).getAddress());
        boolean matches;
        do {
            // if address contains single backslash, don't escape it
            String patternString = ".*([\\p{ASCII}&&[^\\\\]])([\\\\][\\\\])([^\\\\])(.*)@.*";
            Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(escapedFrom);
            matches = matcher.matches();
            if (matches)
                escapedFrom = new StringBuilder(escapedFrom).replace(matcher.start(2), matcher.end(2), "\\").toString();
        } while (matches);
        mailSender.setEnvelopeFrom(escapedFrom);
    } else {
        // System default value
        mailSender.setEnvelopeFrom("<>");
    }
    // Envelope TO & Header To/Cc
    // RFC 5436 2.7. (2nd and 5th item of the 'guidelines')
    Set<String> envelopeTos = new HashSet<String>();
    envelopeTos.add(mailto);
    notification.addRecipient(javax.mail.Message.RecipientType.TO, new JavaMailInternetAddress(mailto));
    List<String> tos = mailtoParams.get("to");
    if (tos != null && tos.size() > 0) {
        for (String to : tos) {
            envelopeTos.add(to);
            notification.addRecipient(javax.mail.Message.RecipientType.TO, new JavaMailInternetAddress(to));
        }
    }
    List<String> ccs = mailtoParams.get("cc");
    if (ccs != null && ccs.size() > 0) {
        for (String cc : ccs) {
            envelopeTos.add(cc);
            notification.addRecipient(javax.mail.Message.RecipientType.CC, new JavaMailInternetAddress(cc));
        }
    }
    List<String> bccs = mailtoParams.get("bcc");
    if (bccs != null && bccs.size() > 0) {
        for (String bcc : bccs) {
            envelopeTos.add(bcc);
        // No Bcc for the message header
        }
    }
    mailSender.setRecipients(envelopeTos.toArray(new String[envelopeTos.size()]));
    // Auto-Submitted
    // RFC 5436 2.7. (3rd item of the 'guidelines') and 2.7.1.
    StringBuilder autoSubmitted = new StringBuilder("auto-notified; owner-email=\"").append(account.getName()).append("\"");
    notification.addHeader(HEADER_AUTO_SUBMITTED, autoSubmitted.toString());
    // RFC 5436 2.7. (4th item of the 'guidelines')
    if (!StringUtil.isNullOrEmpty(from)) {
        // The "From:" header field of the notification message SHOULD be set
        // to the value of the ":from" tag to the notify action, if one is
        // specified, has email address syntax, and is valid according to the
        // implementation-specific security checks.
        notification.addHeader("from", from);
    } else {
        // If ":from" is not specified or is not valid, the
        // "From:" header field of the notification message SHOULD be set
        // either to the envelope "to" field from the triggering message, as
        // used by Sieve...
        // This MUST NOT be overridden by a "from" URI header, and any such
        // URI header MUST be ignored.
        notification.addHeader("from", mailbox.getAccount().getMail());
    }
    // RFC 5436 2.7. (6th item of the 'guidelines')
    if (StringUtil.isNullOrEmpty(message)) {
        List<String> subjectList = mailtoParams.get("subject");
        if (subjectList != null && subjectList.size() > 0) {
            message = subjectList.get(0);
        } else {
            String[] subjects = Mime.getHeaders(mimeMessage, "Subject");
            if (subjects.length > 0) {
                message = subjects[0];
            }
        }
    }
    notification.setSubject(message, getCharset(account, message));
    // Body
    // RFC 5436 2.7. (8th item of the 'guidelines')
    List<String> bodys = mailtoParams.get("body");
    if (bodys != null && bodys.size() > 0) {
        String body = bodys.get(0);
        notification.setText(body, getCharset(account, body));
    } else {
        notification.setText("");
    }
    notification.saveChanges();
    // Misc.
    notification.setSentDate(new Date());
    for (String headerName : mailtoParams.keySet()) {
        if (!("to".equalsIgnoreCase(headerName) || "cc".equalsIgnoreCase(headerName) || "bcc".equalsIgnoreCase(headerName) || "from".equalsIgnoreCase(headerName) || "subject".equalsIgnoreCase(headerName) || "auto-submitted".equalsIgnoreCase(headerName) || "x-zimbra-forwarded".equalsIgnoreCase(headerName) || "message-id".equalsIgnoreCase(headerName) || "date".equalsIgnoreCase(headerName) || "body".equalsIgnoreCase(headerName))) {
            List<String> values = mailtoParams.get(headerName);
            for (String value : values) {
                notification.addHeaderLine(headerName + ": " + value);
            }
        }
    }
    mailSender.setDsnNotifyOptions(MailSender.DsnNotifyOption.NEVER);
    mailSender.sendMimeMessage(octxt, mailbox, notification);
}
Also used : Account(com.zimbra.cs.account.Account) Pattern(java.util.regex.Pattern) Matcher(java.util.regex.Matcher) MailSender(com.zimbra.cs.mailbox.MailSender) Date(java.util.Date) MimeMessage(javax.mail.internet.MimeMessage) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) List(java.util.List) HashSet(java.util.HashSet)

Example 4 with JavaMailInternetAddress

use of com.zimbra.common.mime.shim.JavaMailInternetAddress in project zm-mailbox by Zimbra.

the class FilterUtil method notify.

public static void notify(OperationContext octxt, Mailbox mailbox, ParsedMessage parsedMessage, String emailAddr, String subjectTemplate, String bodyTemplate, int maxBodyBytes, List<String> origHeaders) throws MessagingException, ServiceException {
    MimeMessage mimeMessage = parsedMessage.getMimeMessage();
    if (isMailLoop(mailbox, mimeMessage, new String[] { HEADER_FORWARDED })) {
        String error = String.format("Detected a mail loop for message %s.", Mime.getMessageID(mimeMessage));
        throw ServiceException.FAILURE(error, null);
    }
    Account account = mailbox.getAccount();
    MimeMessage notification = new Mime.FixedMimeMessage(JMSession.getSmtpSession(account));
    // add the forwarded header account names to detect the mail loop between accounts
    for (String headerFwdAccountName : Mime.getHeaders(mimeMessage, HEADER_FORWARDED)) {
        notification.addHeader(HEADER_FORWARDED, headerFwdAccountName);
    }
    notification.addHeader(HEADER_FORWARDED, account.getName());
    MailSender mailSender = mailbox.getMailSender().setSaveToSent(false);
    // Map<String, String> vars = getVarsMap(mailbox, parsedMessage, mimeMessage);
    if (origHeaders == null || origHeaders.isEmpty()) {
        // no headers need to be copied from the original message
        notification.setRecipient(javax.mail.Message.RecipientType.TO, new JavaMailInternetAddress(emailAddr));
        notification.setSentDate(new Date());
        if (!StringUtil.isNullOrEmpty(subjectTemplate)) {
            notification.setSubject(subjectTemplate, getCharset(account, subjectTemplate));
        }
    } else {
        if (origHeaders.size() == 1 && "*".equals(origHeaders.get(0))) {
            // all headers need to be copied from the original message
            Enumeration enumeration = mimeMessage.getAllHeaders();
            while (enumeration.hasMoreElements()) {
                Header header = (Header) enumeration.nextElement();
                if (StringUtil.equal(header.getName(), HEADER_FORWARDED)) {
                    continue;
                }
                if (StringUtil.equal(header.getName(), HEADER_CONTENT_TYPE) || StringUtil.equal(header.getName(), HEADER_CONTENT_DISPOSITION)) {
                    // Zimbra Mime parser will add the correct Content Type if absent
                    continue;
                }
                notification.addHeader(header.getName(), header.getValue());
            }
        } else {
            // some headers need to be copied from the original message
            Set<String> headersToCopy = Sets.newHashSet(origHeaders);
            boolean copySubject = false;
            for (String header : headersToCopy) {
                if ("Subject".equalsIgnoreCase(header)) {
                    copySubject = true;
                }
                if (StringUtil.equal(header, HEADER_FORWARDED)) {
                    continue;
                }
                String[] hdrVals = mimeMessage.getHeader(header);
                if (hdrVals == null) {
                    continue;
                }
                for (String hdrVal : hdrVals) {
                    notification.addHeader(header, hdrVal);
                }
            }
            if (!copySubject && !StringUtil.isNullOrEmpty(subjectTemplate)) {
                notification.setSubject(subjectTemplate, getCharset(account, subjectTemplate));
            }
        }
        mailSender.setRedirectMode(true);
        mailSender.setRecipients(emailAddr);
    }
    String body = StringUtil.truncateIfRequired(bodyTemplate, maxBodyBytes);
    notification.setText(body, getCharset(account, body));
    notification.saveChanges();
    if (isDeliveryStatusNotification(mimeMessage)) {
        mailSender.setEnvelopeFrom("<>");
    } else {
        mailSender.setEnvelopeFrom(account.getName());
    }
    mailSender.setDsnNotifyOptions(MailSender.DsnNotifyOption.NEVER);
    mailSender.sendMimeMessage(octxt, mailbox, notification);
}
Also used : Account(com.zimbra.cs.account.Account) Enumeration(java.util.Enumeration) ZInternetHeader(com.zimbra.common.zmime.ZInternetHeader) Header(javax.mail.Header) MimeMessage(javax.mail.internet.MimeMessage) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) MailSender(com.zimbra.cs.mailbox.MailSender) Date(java.util.Date)

Example 5 with JavaMailInternetAddress

use of com.zimbra.common.mime.shim.JavaMailInternetAddress in project zm-mailbox by Zimbra.

the class FilterUtil method reject.

public static void reject(OperationContext octxt, Mailbox mailbox, ParsedMessage parsedMessage, String reason, LmtpEnvelope envelope) throws MessagingException, ServiceException {
    MimeMessage mimeMessage = parsedMessage.getMimeMessage();
    if (isMailLoop(mailbox, mimeMessage, new String[] { HEADER_FORWARDED })) {
        // Detected a mail loop.  Do not send MDN, but just discard the message
        String error = String.format("Detected a mail loop for message %s. No MDN sent.", Mime.getMessageID(mimeMessage));
        ZimbraLog.filter.info(error);
        throw ServiceException.FAILURE(error, null);
    }
    String reportTo = null;
    if (envelope != null && envelope.hasSender()) {
        reportTo = envelope.getSender().getEmailAddress();
    }
    if (reportTo == null || reportTo.isEmpty()) {
        String[] returnPath = mimeMessage.getHeader(HEADER_RETURN_PATH);
        if (returnPath == null || returnPath.length == 0) {
            // >> NOT be generated if the MAIL FROM (or Return-Path) is empty.
            throw new MessagingException("Neither 'envelope from' nor 'Return-Path' specified. Can't locate the address to reject to (No MDN sent)");
        } else {
            // At least one 'return-path' should exist.
            reportTo = returnPath[0];
        }
    }
    Account owner = mailbox.getAccount();
    Locale locale = owner.getLocale();
    String charset = owner.getPrefMailDefaultCharset();
    if (charset == null) {
        charset = MimeConstants.P_CHARSET_UTF8;
    }
    SMTPMessage report = AccountUtil.getSmtpMessageObj(owner);
    // add the forwarded header account names to detect the mail loop between accounts
    for (String headerFwdAccountName : Mime.getHeaders(mimeMessage, HEADER_FORWARDED)) {
        report.addHeader(HEADER_FORWARDED, headerFwdAccountName);
    }
    report.addHeader(HEADER_FORWARDED, owner.getName());
    // MDN header
    report.setEnvelopeFrom("<>");
    report.setRecipient(javax.mail.Message.RecipientType.TO, new JavaMailInternetAddress(reportTo));
    String subject = L10nUtil.getMessage(MsgKey.seiveRejectMDNSubject, locale);
    report.setSubject(subject);
    report.setSentDate(new Date());
    InternetAddress address = new JavaMailInternetAddress(owner.getName());
    report.setFrom(address);
    MimeMultipart multi = new ZMimeMultipart("report");
    // part 1: human-readable notification
    String text = L10nUtil.getMessage(MsgKey.seiveRejectMDNErrorMsg, locale) + "\n" + reason;
    MimeBodyPart mpText = new ZMimeBodyPart();
    mpText.setText(text, CharsetUtil.checkCharset(text, charset));
    multi.addBodyPart(mpText);
    // part 2: disposition notification
    StringBuilder mdn = new StringBuilder();
    mdn.append("Final-Recipient: rfc822;").append(owner.getName()).append("\r\n");
    mdn.append("Disposition: automatic-action/MDN-sent-automatically");
    mdn.append("; deleted\r\n");
    MimeBodyPart mpMDN = new ZMimeBodyPart();
    mpMDN.setText(mdn.toString(), MimeConstants.P_CHARSET_UTF8);
    mpMDN.setHeader("Content-Type", "message/disposition-notification; charset=utf-8");
    multi.addBodyPart(mpMDN);
    // Assemble the MDN
    report.setContent(multi);
    report.setHeader("Content-Type", multi.getContentType() + "; report-type=disposition-notification");
    report.saveChanges();
    MailSender mailSender = mailbox.getMailSender().setSaveToSent(false);
    mailSender.setRecipients(reportTo);
    mailSender.setEnvelopeFrom("<>");
    mailSender.sendMimeMessage(octxt, mailbox, report);
}
Also used : Locale(java.util.Locale) Account(com.zimbra.cs.account.Account) SMTPMessage(com.sun.mail.smtp.SMTPMessage) InternetAddress(javax.mail.internet.InternetAddress) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) MessagingException(javax.mail.MessagingException) ZMimeBodyPart(com.zimbra.common.zmime.ZMimeBodyPart) MailSender(com.zimbra.cs.mailbox.MailSender) Date(java.util.Date) MimeMessage(javax.mail.internet.MimeMessage) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) MimeMultipart(javax.mail.internet.MimeMultipart) JavaMailInternetAddress(com.zimbra.common.mime.shim.JavaMailInternetAddress) ZMimeMultipart(com.zimbra.common.zmime.ZMimeMultipart) ZMimeBodyPart(com.zimbra.common.zmime.ZMimeBodyPart) MimeBodyPart(javax.mail.internet.MimeBodyPart)

Aggregations

JavaMailInternetAddress (com.zimbra.common.mime.shim.JavaMailInternetAddress)46 InternetAddress (javax.mail.internet.InternetAddress)31 MimeMessage (javax.mail.internet.MimeMessage)25 AddressException (javax.mail.internet.AddressException)17 Date (java.util.Date)15 MessagingException (javax.mail.MessagingException)14 ZMimeMessage (com.zimbra.common.zmime.ZMimeMessage)13 Account (com.zimbra.cs.account.Account)12 MailSender (com.zimbra.cs.mailbox.MailSender)9 UnsupportedEncodingException (java.io.UnsupportedEncodingException)9 ArrayList (java.util.ArrayList)9 Address (javax.mail.Address)9 ServiceException (com.zimbra.common.service.ServiceException)8 Locale (java.util.Locale)8 SMTPMessage (com.sun.mail.smtp.SMTPMessage)7 MimeBodyPart (javax.mail.internet.MimeBodyPart)7 ZMimeBodyPart (com.zimbra.common.zmime.ZMimeBodyPart)6 ZMimeMultipart (com.zimbra.common.zmime.ZMimeMultipart)6 IOException (java.io.IOException)6 MimeMultipart (javax.mail.internet.MimeMultipart)6