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);
}
}
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();
}
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();
}
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;
}
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);
}
}
Aggregations