Search in sources :

Example 1 with SieveException

use of org.apache.jsieve.exception.SieveException in project zm-mailbox by Zimbra.

the class RuleManager method setRules.

/**
 * Saves the filter rules.
 *
 * @param entry the account/domain/cos/server for which the rules are to be saved
 * @param script the sieve script, or <code>null</code> or empty string if
 * all rules should be deleted
 * @param sieveScriptAttrName
 * @param rulesCacheKey
 * @throws ServiceException
 */
private static void setRules(Entry entry, String script, String sieveScriptAttrName, String rulesCacheKey) throws ServiceException {
    if (entry instanceof Account) {
        ZimbraLog.filter.debug("Setting filter rules for account %s:\n%s", ((Account) entry).getName(), script);
    } else if (entry instanceof Domain) {
        ZimbraLog.filter.debug("Setting filter rules for domian %s:\n%s", ((Domain) entry).getName(), script);
    } else if (entry instanceof Cos) {
        ZimbraLog.filter.debug("Setting filter rules for cos %s:\n%s", ((Cos) entry).getName(), script);
    } else if (entry instanceof Server) {
        ZimbraLog.filter.debug("Setting filter rules for server %s:\n%s", ((Server) entry).getName(), script);
    }
    if (script == null) {
        script = "";
    }
    try {
        Node node = parse(script);
        // evaluate against dummy mail adapter to catch more errors
        SIEVE_FACTORY.evaluate(new DummyMailAdapter(), node);
        // save
        Map<String, Object> attrs = new HashMap<String, Object>();
        attrs.put(sieveScriptAttrName, script);
        Provisioning.getInstance().modifyAttrs(entry, attrs);
        entry.setCachedData(rulesCacheKey, node);
    } catch (ParseException e) {
        ZimbraLog.filter.error("Unable to parse script:\n" + script);
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    } catch (TokenMgrError e) {
        ZimbraLog.filter.error("Unable to parse script:\n" + script);
        throw ServiceException.PARSE_ERROR("parsing Sieve script", e);
    } catch (SieveException e) {
        ZimbraLog.filter.error("Unable to evaluate script:\n" + script);
        throw ServiceException.PARSE_ERROR("evaluating Sieve script", e);
    }
}
Also used : Account(com.zimbra.cs.account.Account) Server(com.zimbra.cs.account.Server) HashMap(java.util.HashMap) Cos(com.zimbra.cs.account.Cos) Node(org.apache.jsieve.parser.generated.Node) TokenMgrError(org.apache.jsieve.parser.generated.TokenMgrError) SieveException(org.apache.jsieve.exception.SieveException) ParseException(org.apache.jsieve.parser.generated.ParseException) Domain(com.zimbra.cs.account.Domain)

Example 2 with SieveException

use of org.apache.jsieve.exception.SieveException in project zm-mailbox by Zimbra.

the class RuleManager method createSieveFactory.

private static SieveFactory createSieveFactory() {
    // Initialize custom jSieve extensions
    ConfigurationManager mgr;
    try {
        mgr = new ZimbraConfigurationManager();
    } catch (SieveException e) {
        ZimbraLog.filter.error("Unable to initialize mail filtering extensions.", e);
        return null;
    }
    Map<String, String> commandMap = mgr.getCommandMap();
    commandMap.putAll(JsieveConfigMapHandler.getCommandMap());
    Map<String, String> testMap = mgr.getTestMap();
    testMap.putAll(JsieveConfigMapHandler.getTestMap());
    return mgr.build();
}
Also used : SieveException(org.apache.jsieve.exception.SieveException) ConfigurationManager(org.apache.jsieve.ConfigurationManager)

Example 3 with SieveException

use of org.apache.jsieve.exception.SieveException in project zm-mailbox by Zimbra.

the class RuleManager method applyRulesToExistingMessage.

public static boolean applyRulesToExistingMessage(OperationContext octxt, Mailbox mbox, int messageId, Node node) throws ServiceException {
    Message msg = mbox.getMessageById(octxt, messageId);
    ExistingMessageHandler handler = new ExistingMessageHandler(octxt, mbox, messageId, (int) msg.getSize());
    ZimbraMailAdapter mailAdapter = new ZimbraMailAdapter(mbox, handler);
    try {
        SIEVE_FACTORY.evaluate(mailAdapter, node);
        mailAdapter.executeAllActions();
    } catch (SieveException e) {
        throw ServiceException.FAILURE("Unable to evaluate script", e);
    }
    return handler.filtered();
}
Also used : SieveException(org.apache.jsieve.exception.SieveException) Message(com.zimbra.cs.mailbox.Message) ParsedMessage(com.zimbra.cs.mime.ParsedMessage)

Example 4 with SieveException

use of org.apache.jsieve.exception.SieveException in project zm-mailbox by Zimbra.

the class EnvelopeTest method match.

/**
 * Compares the address with operator
 *
 * @param operator "gt" / "ge" / "lt" / "le" / "eq" / "ne"
 */
private boolean match(MailAdapter mail, String addressPart, String comparator, String matchType, String operator, List<String> headerNames, List<String> keys, SieveContext context) throws SieveException {
    if (mail instanceof DummyMailAdapter) {
        return true;
    }
    if (!(mail instanceof ZimbraMailAdapter)) {
        return false;
    }
    // Iterate over the address fields looking for a match
    boolean isMatched = false;
    List<String> headerValues = Lists.newArrayListWithExpectedSize(2);
    for (final String headerName : headerNames) {
        if ("to".equalsIgnoreCase(headerName)) {
            // RFC 5231 4.2. ... The envelope "to" will always have only one
            // entry, which is the address of the user for whom the Sieve script
            // is running.
            String recipient = null;
            try {
                recipient = ((ZimbraMailAdapter) mail).getMailbox().getAccount().getMail();
            } catch (ServiceException e) {
                recipient = "";
            }
            headerValues.add(getMatchAddressPart(addressPart, recipient));
        } else if ("from".equalsIgnoreCase(headerName)) {
            List<String> values = getMatchingValues(mail, headerName);
            if (values != null) {
                if (matchType.equalsIgnoreCase(HeaderConstants.COUNT)) {
                    // RFC 5231 Section 4.2 Match Type COUNT says:
                    // | The envelope "from" will be 0 if the MAIL FROM is empty, or 1 if MAIL
                    // | FROM is not empty.
                    // This method could be called for other match type, such as :value or :is,
                    // remove the empty element only if the match type is :count.
                    values.removeIf(s -> Strings.isNullOrEmpty(s));
                }
                for (String value : values) {
                    headerValues.add(getMatchAddressPart(addressPart, value));
                }
            }
        } else {
            throw new SyntaxException("Unexpected header name as a value for <envelope-part>: '" + headerName + "'");
        }
    }
    if (HeaderConstants.COUNT.equals(matchType)) {
        for (final String key : keys) {
            isMatched = ZimbraComparatorUtils.counts(mail, comparator, operator, headerValues, ZimbraComparatorUtils.getMatchKey(addressPart, key), context);
            if (isMatched) {
                break;
            }
        }
    } else {
        Iterator headerValuesIter = headerValues.iterator();
        while (!isMatched && headerValuesIter.hasNext()) {
            List<String> normalizedKeys = Lists.newArrayListWithExpectedSize(keys.size());
            if (DOMAIN_TAG.equalsIgnoreCase(addressPart)) {
                for (String key : keys) {
                    normalizedKeys.add(key.toLowerCase());
                }
            } else {
                normalizedKeys = keys;
            }
            String headerValue = (String) headerValuesIter.next();
            // Iterate over the keys looking for a match
            for (final String key : keys) {
                isMatched = ZimbraComparatorUtils.match(mail, comparator, matchType, operator, headerValue, key, context);
                if (isMatched) {
                    break;
                }
            }
        }
    }
    return isMatched;
}
Also used : CAPABILITY_ENVELOPE(com.zimbra.cs.filter.JsieveConfigMapHandler.CAPABILITY_ENVELOPE) ASCII_NUMERIC_COMPARATOR(com.zimbra.cs.filter.jsieve.ComparatorName.ASCII_NUMERIC_COMPARATOR) MessagingException(javax.mail.MessagingException) ServiceException(com.zimbra.common.service.ServiceException) Strings(com.google.common.base.Strings) ZimbraComparatorUtils(com.zimbra.cs.filter.ZimbraComparatorUtils) Lists(com.google.common.collect.Lists) FilterUtil(com.zimbra.cs.filter.FilterUtil) SieveException(org.apache.jsieve.exception.SieveException) MatchTypeTags(org.apache.jsieve.comparators.MatchTypeTags) HeaderConstants(com.zimbra.common.soap.HeaderConstants) DOMAIN_TAG(org.apache.jsieve.tests.AddressPartTags.DOMAIN_TAG) DummyMailAdapter(com.zimbra.cs.filter.DummyMailAdapter) Iterator(java.util.Iterator) ASCII_CASEMAP_COMPARATOR(org.apache.jsieve.comparators.ComparatorNames.ASCII_CASEMAP_COMPARATOR) Arguments(org.apache.jsieve.Arguments) ZimbraMailAdapter(com.zimbra.cs.filter.ZimbraMailAdapter) MailAdapter(org.apache.jsieve.mail.MailAdapter) ALL_TAG(org.apache.jsieve.tests.AddressPartTags.ALL_TAG) Envelope(org.apache.jsieve.tests.optional.Envelope) List(java.util.List) SyntaxException(org.apache.jsieve.exception.SyntaxException) LOCALPART_TAG(org.apache.jsieve.tests.AddressPartTags.LOCALPART_TAG) SieveContext(org.apache.jsieve.SieveContext) StringUtil(com.zimbra.common.util.StringUtil) IS_TAG(org.apache.jsieve.comparators.MatchTypeTags.IS_TAG) ServiceException(com.zimbra.common.service.ServiceException) SyntaxException(org.apache.jsieve.exception.SyntaxException) Iterator(java.util.Iterator) DummyMailAdapter(com.zimbra.cs.filter.DummyMailAdapter) List(java.util.List) ZimbraMailAdapter(com.zimbra.cs.filter.ZimbraMailAdapter)

Example 5 with SieveException

use of org.apache.jsieve.exception.SieveException in project zm-mailbox by Zimbra.

the class ZimbraMailAdapter method executeActions.

@Override
public void executeActions() throws SieveException {
    try {
        handler.beforeFiltering();
        String messageId = Mime.getMessageID(handler.getMimeMessage());
        // the script contains a single discard action, JSieve returns an empty list.
        if (getActions().size() == 0) {
            ZimbraLog.filter.info("Discarding message with Message-ID %s from %s", messageId, Mime.getSender(handler.getMimeMessage()));
            handler.discard();
            return;
        }
        List<Action> deliveryActions = getDeliveryActions();
        if (deliveryActions.isEmpty()) {
            // i.e. no keep/fileinto/redirect actions
            if (getReplyNotifyRejectActions().isEmpty()) {
                // if only flag/tag actions are present, we keep the message even if discard
                // action is present
                keep(KeepType.EXPLICIT_KEEP);
            } else if (!discardActionPresent) {
                // else if reply/notify/reject/ereject actions are present and there's no discard, do sort
                // of implicit keep
                keep(KeepType.EXPLICIT_KEEP);
            }
        } else {
            ListIterator<Action> li = deliveryActions.listIterator(deliveryActions.size());
            while (li.hasPrevious()) {
                Action lastDeliveryAction = li.previous();
                if (lastDeliveryAction instanceof ActionFileInto) {
                    ActionFileInto lastFileIntoAction = (ActionFileInto) lastDeliveryAction;
                    if (lastFileIntoAction.isCopy() && !discardActionPresent) {
                        keep(KeepType.EXPLICIT_KEEP);
                    }
                    break;
                } else if (lastDeliveryAction instanceof ActionRedirect) {
                    ActionRedirect lastRedirectAction = (ActionRedirect) lastDeliveryAction;
                    if (lastRedirectAction.isCopy() && !discardActionPresent) {
                        keep(KeepType.EXPLICIT_KEEP);
                    }
                    break;
                }
            }
        }
        for (Action action : actions) {
            if (action instanceof ActionKeep) {
                if (context == null) {
                    ZimbraLog.filter.warn("SieveContext has unexpectedly not been set");
                    keep(KeepType.IMPLICIT_KEEP);
                } else if (context.getCommandStateManager().isImplicitKeep()) {
                    // implicit keep: this means that none of the user's rules have been matched
                    // we need to check system spam filter to see if the mail is spam
                    keep(KeepType.IMPLICIT_KEEP);
                } else {
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionFileInto) {
                ActionFileInto fileinto = (ActionFileInto) action;
                String folderPath = fileinto.getDestination();
                folderPath = FilterUtil.replaceVariables(this, folderPath);
                try {
                    if (!allowFilterToMountpoint && isMountpoint(mailbox, folderPath)) {
                        ZimbraLog.filter.info("Filing to mountpoint \"%s\" is not allowed.  Filing to the default folder instead.", folderPath);
                        keep(KeepType.EXPLICIT_KEEP);
                    } else {
                        fileInto(folderPath);
                    }
                } catch (ServiceException e) {
                    ZimbraLog.filter.info("Unable to file message to %s.  Filing to %s instead.", folderPath, handler.getDefaultFolderPath(), e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionRedirect) {
                // redirect mail to another address
                ActionRedirect redirect = (ActionRedirect) action;
                String addr = redirect.getAddress();
                addr = FilterUtil.replaceVariables(this, addr);
                ZimbraLog.filter.info("Redirecting message to %s.", addr);
                try {
                    handler.redirect(addr);
                } catch (Exception e) {
                    ZimbraLog.filter.warn("Unable to redirect to %s.  Filing message to %s.", addr, handler.getDefaultFolderPath(), e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionReply) {
                // reply to mail
                ActionReply reply = (ActionReply) action;
                ZimbraLog.filter.debug("Replying to message");
                try {
                    String replyStrg = FilterUtil.replaceVariables(this, reply.getBodyTemplate());
                    handler.reply(replyStrg);
                } catch (Exception e) {
                    ZimbraLog.filter.warn("Unable to reply.", e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionNotify) {
                ActionNotify notify = (ActionNotify) action;
                ZimbraLog.filter.debug("Sending notification message to %s.", notify.getEmailAddr());
                try {
                    handler.notify(FilterUtil.replaceVariables(this, notify.getEmailAddr()), FilterUtil.replaceVariables(this, notify.getSubjectTemplate()), FilterUtil.replaceVariables(this, notify.getBodyTemplate()), notify.getMaxBodyBytes(), notify.getOrigHeaders());
                } catch (Exception e) {
                    ZimbraLog.filter.warn("Unable to notify.", e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionReject) {
                ActionReject reject = (ActionReject) action;
                ZimbraLog.filter.debug("Refusing delivery of a message: %s", reject.getMessage());
                try {
                    String msg = FilterUtil.replaceVariables(this, reject.getMessage());
                    handler.reject(msg, envelope);
                    handler.discard();
                } catch (Exception e) {
                    ZimbraLog.filter.info("Unable to reject.", e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            } else if (action instanceof ActionEreject) {
                ActionEreject ereject = (ActionEreject) action;
                ZimbraLog.filter.debug("Refusing delivery of a message at the protocol level");
                try {
                    handler.ereject(envelope);
                } catch (ErejectException e) {
                    // 'ereject' action executed
                    throw e;
                } catch (Exception e) {
                    ZimbraLog.filter.warn("Unable to ereject.", e);
                }
            } else if (action instanceof ActionNotifyMailto) {
                ActionNotifyMailto notifyMailto = (ActionNotifyMailto) action;
                ZimbraLog.filter.debug("Sending RFC 5435/5436 compliant notification message to %s.", notifyMailto.getMailto());
                try {
                    handler.notifyMailto(envelope, notifyMailto.getFrom(), notifyMailto.getImportance(), notifyMailto.getOptions(), notifyMailto.getMessage(), notifyMailto.getMailto(), notifyMailto.getMailtoParams());
                } catch (Exception e) {
                    ZimbraLog.filter.warn("Unable to notify (mailto).", e);
                    keep(KeepType.EXPLICIT_KEEP);
                }
            }
        }
        handler.afterFiltering();
    } catch (ServiceException e) {
        throw new ZimbraSieveException(e);
    }
}
Also used : Action(org.apache.jsieve.mail.Action) ActionReply(com.zimbra.cs.filter.jsieve.ActionReply) ActionRedirect(com.zimbra.cs.filter.jsieve.ActionRedirect) MessagingException(javax.mail.MessagingException) SieveMailException(org.apache.jsieve.mail.SieveMailException) SieveException(org.apache.jsieve.exception.SieveException) AddressException(javax.mail.internet.AddressException) ServiceException(com.zimbra.common.service.ServiceException) ErejectException(com.zimbra.cs.filter.jsieve.ErejectException) IOException(java.io.IOException) ActionEreject(com.zimbra.cs.filter.jsieve.ActionEreject) ActionNotifyMailto(com.zimbra.cs.filter.jsieve.ActionNotifyMailto) ServiceException(com.zimbra.common.service.ServiceException) ActionKeep(org.apache.jsieve.mail.ActionKeep) ActionReject(org.apache.jsieve.mail.ActionReject) ActionFileInto(com.zimbra.cs.filter.jsieve.ActionFileInto) ErejectException(com.zimbra.cs.filter.jsieve.ErejectException) ActionNotify(com.zimbra.cs.filter.jsieve.ActionNotify)

Aggregations

SieveException (org.apache.jsieve.exception.SieveException)11 ZimbraMailAdapter (com.zimbra.cs.filter.ZimbraMailAdapter)6 MessagingException (javax.mail.MessagingException)6 DummyMailAdapter (com.zimbra.cs.filter.DummyMailAdapter)5 ZimbraComparatorUtils (com.zimbra.cs.filter.ZimbraComparatorUtils)3 ServiceException (com.zimbra.common.service.ServiceException)2 StringListArgument (org.apache.jsieve.StringListArgument)2 Strings (com.google.common.base.Strings)1 Lists (com.google.common.collect.Lists)1 HeaderConstants (com.zimbra.common.soap.HeaderConstants)1 StringUtil (com.zimbra.common.util.StringUtil)1 Account (com.zimbra.cs.account.Account)1 Cos (com.zimbra.cs.account.Cos)1 Domain (com.zimbra.cs.account.Domain)1 Server (com.zimbra.cs.account.Server)1 FilterUtil (com.zimbra.cs.filter.FilterUtil)1 CAPABILITY_ENVELOPE (com.zimbra.cs.filter.JsieveConfigMapHandler.CAPABILITY_ENVELOPE)1 ActionEreject (com.zimbra.cs.filter.jsieve.ActionEreject)1 ActionFileInto (com.zimbra.cs.filter.jsieve.ActionFileInto)1 ActionNotify (com.zimbra.cs.filter.jsieve.ActionNotify)1