use of org.apache.jsieve.parser.generated.Node in project zm-mailbox by Zimbra.
the class RuleManager method applyRulesToOutgoingMessage.
public static List<ItemId> applyRulesToOutgoingMessage(OperationContext octxt, Mailbox mailbox, ParsedMessage pm, int sentFolderId, boolean noICal, int flags, String[] tags, int convId) throws ServiceException {
List<ItemId> addedMessageIds = null;
OutgoingMessageHandler handler = new OutgoingMessageHandler(mailbox, pm, sentFolderId, noICal, flags, tags, convId, octxt);
ZimbraMailAdapter mailAdapter = new ZimbraMailAdapter(mailbox, handler);
try {
Account account = mailbox.getAccount();
Node node = getRulesNode(account, FilterType.OUTGOING, true);
if (node != null) {
SIEVE_FACTORY.evaluate(mailAdapter, node);
// multiple fileinto may result in multiple copies of the messages in different folders
addedMessageIds = mailAdapter.getAddedMessageIds();
}
} catch (Exception e) {
ZimbraLog.filter.warn("An error occurred while processing filter rules. Filing message to %s.", handler.getDefaultFolderPath(), e);
} catch (TokenMgrError e) {
ZimbraLog.filter.warn("An error occurred while processing filter rules. Filing message to %s.", handler.getDefaultFolderPath(), e);
}
if (addedMessageIds == null) {
// Filter rules were not processed. File to the default folder.
Message msg = mailAdapter.keep(KeepType.IMPLICIT_KEEP);
addedMessageIds = new ArrayList<ItemId>(1);
addedMessageIds.add(new ItemId(msg));
}
return addedMessageIds;
}
use of org.apache.jsieve.parser.generated.Node 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.parser.generated.Node in project zm-mailbox by Zimbra.
the class RuleManager method getRulesNode.
/**
* Returns the parsed filter rules for the given account. If no cached
* copy of the parsed rules exists, parses the script returned by
* {@link #getRules(com.zimbra.cs.account.Account, String)} and caches the result on the <tt>Account</tt>.
*
* @param account the owner account of the filter rule
* @param filterType <tt>FilterType.INCOMING</tt> or <tt>FilterType.OUTGOING</tt>
* @param useAdminRule TRUE to return a combined sieve rule of admin sieve(s) and user defined rule. FALSE to return only a user defined rule.
*
* @see Account#setCachedData(String, Object)
* @throws ParseException if there was an error while parsing the Sieve script
*/
private static Node getRulesNode(Account account, FilterType filterType, boolean useAdminRule) throws ParseException {
String rulesCacheKey = null;
// user-defined sieve rule
String sieveScriptAttrName = null;
// admin-defined sieve rule applied before and after user sieve
String adminRuleBeforeAttrName = null;
String adminRuleAfterAttrName = null;
if (filterType == FilterType.INCOMING) {
if (useAdminRule) {
rulesCacheKey = ADMIN_FILTER_RULES_CACHE_KEY;
} else {
rulesCacheKey = FILTER_RULES_CACHE_KEY;
}
sieveScriptAttrName = Provisioning.A_zimbraMailSieveScript;
adminRuleBeforeAttrName = Provisioning.A_zimbraAdminSieveScriptBefore;
adminRuleAfterAttrName = Provisioning.A_zimbraAdminSieveScriptAfter;
} else {
if (useAdminRule) {
rulesCacheKey = ADMIN_OUTGOING_FILTER_RULES_CACHE_KEY;
} else {
rulesCacheKey = OUTGOING_FILTER_RULES_CACHE_KEY;
}
sieveScriptAttrName = Provisioning.A_zimbraMailOutgoingSieveScript;
adminRuleBeforeAttrName = Provisioning.A_zimbraAdminOutgoingSieveScriptBefore;
adminRuleAfterAttrName = Provisioning.A_zimbraAdminOutgoingSieveScriptAfter;
}
Node node = (Node) account.getCachedData(rulesCacheKey);
if (node == null) {
String script = getRules(account, sieveScriptAttrName);
String debugScript = script;
if (useAdminRule) {
/*
* Sandwitches the user-defined sieve rule
* between the admin-defined rules.
*/
StringBuilder requiresPart = new StringBuilder();
String adminRuleBefore = getRules(account, adminRuleBeforeAttrName);
String adminRuleAfter = getRules(account, adminRuleAfterAttrName);
String debugAdminRuleBefore = adminRuleBefore;
String debugAdminRuleAfter = adminRuleAfter;
if (adminRuleBefore == null) {
debugAdminRuleBefore = "";
adminRuleBefore = "";
} else {
List<String> splits = splitScript(adminRuleBefore);
requiresPart.append(splits.get(0));
debugAdminRuleBefore = adminRuleBefore = splits.get(1);
}
if (script == null) {
debugScript = "";
script = "";
} else {
List<String> splits = splitScript(script);
requiresPart.append(splits.get(0));
script = "\nzimbravariablesctrl :reset;\n" + splits.get(1);
debugScript = splits.get(1);
}
if (adminRuleAfter == null) {
debugAdminRuleAfter = "";
adminRuleAfter = "";
} else {
List<String> splits = splitScript(adminRuleAfter);
requiresPart.append(splits.get(0));
adminRuleAfter = "\nzimbravariablesctrl :reset;\n" + splits.get(1);
debugAdminRuleAfter = splits.get(1);
}
/*
* Since "require" is only allowed before other commands,
* the "require" part at the beginning of each sieve rule
* text will be cut, and pasted into the very top of the
* combined rule. RFC-wise, it is okay to declare the
* "require" commands multiple times.
*/
script = requiresPart.toString() + adminRuleBefore + script + adminRuleAfter;
debugScript = requiresPart.toString() + "\n# AdminBefore script\n" + debugAdminRuleBefore + "\n# End user script\n" + debugScript + "\n# AdminAfter script\n" + debugAdminRuleAfter;
}
if (script == null) {
script = "";
}
ZimbraLog.filter.debug("filterType[%s] useAdminRule[%s] rule[%s]", filterType == FilterType.INCOMING ? "incoming" : "outgoing", useAdminRule ? "true" : "false", debugScript);
node = parse(script);
account.setCachedData(rulesCacheKey, node);
}
return node;
}
use of org.apache.jsieve.parser.generated.Node in project zm-mailbox by Zimbra.
the class RuleManager method applyRulesToIncomingMessage.
/**
* Adds a message to a mailbox. If filter rules exist, processes
* the filter rules. Otherwise, files to <tt>Inbox</tt> or <tt>Spam</tt>.
*
* @param allowFilterToMountpoint if <tt>false</tt>, rules
* @return the list of message id's that were added, or an empty list.
*/
public static List<ItemId> applyRulesToIncomingMessage(OperationContext octxt, Mailbox mailbox, ParsedMessage pm, int size, String recipient, LmtpEnvelope env, DeliveryContext sharedDeliveryCtxt, int incomingFolderId, boolean noICal, boolean allowFilterToMountpoint) throws ServiceException {
List<ItemId> addedMessageIds = null;
IncomingMessageHandler handler = new IncomingMessageHandler(octxt, sharedDeliveryCtxt, mailbox, recipient, pm, size, incomingFolderId, noICal);
ZimbraMailAdapter mailAdapter = new ZimbraMailAdapter(mailbox, handler);
mailAdapter.setEnvelope(env);
mailAdapter.setAllowFilterToMountpoint(allowFilterToMountpoint);
try {
Account account = mailbox.getAccount();
Node node = getRulesNode(account, FilterType.INCOMING, true);
// Determine whether to apply rules
boolean applyRules = true;
if (node == null) {
applyRules = false;
}
if (SpamHandler.isSpam(handler.getMimeMessage()) && !account.getBooleanAttr(Provisioning.A_zimbraSpamApplyUserFilters, false)) {
// Don't apply user filters to spam by default
applyRules = false;
}
if (applyRules) {
SIEVE_FACTORY.evaluate(mailAdapter, node);
// multiple fileinto may result in multiple copies of the messages in different folders
addedMessageIds = mailAdapter.getAddedMessageIds();
}
} catch (ErejectException ex) {
throw DeliveryServiceException.DELIVERY_REJECTED(ex.getMessage(), ex);
} catch (Exception e) {
ZimbraLog.filter.warn("An error occurred while processing filter rules. Filing message to %s.", handler.getDefaultFolderPath(), e);
} catch (TokenMgrError e) {
// Workaround for bug 19576. Certain parse errors can cause JavaCC to throw an Error
// instead of an Exception. Woo.
ZimbraLog.filter.warn("An error occurred while processing filter rules. Filing message to %s.", handler.getDefaultFolderPath(), e);
}
if (addedMessageIds == null) {
// Filter rules were not processed. File to the default folder.
Message msg = mailAdapter.keep(KeepType.IMPLICIT_KEEP);
addedMessageIds = new ArrayList<ItemId>(1);
addedMessageIds.add(new ItemId(msg));
}
return addedMessageIds;
}
use of org.apache.jsieve.parser.generated.Node in project zm-mailbox by Zimbra.
the class RuleRewriter method action.
private void action(Element elem, Node node) {
int numChildren = node.jjtGetNumChildren();
for (int i = 0; i < numChildren; i++) {
Node childNode = node.jjtGetChild(i);
if (childNode instanceof ASTstring) {
String val = ((SieveNode) childNode).getValue().toString();
if (val.startsWith("text:")) {
elem.addText(val.substring(5));
} else {
// Put quotes around value to maintain backward compatibility
// with ZCS 5.x. See bug 39911.
StringBuilder buf = new StringBuilder();
if (!val.startsWith("\"")) {
buf.append('"');
}
buf.append(val);
if (!val.endsWith("\"")) {
buf.append('"');
}
elem.addElement(MailConstants.E_FILTER_ARG).setText(buf.toString());
}
} else {
action(elem, childNode);
}
}
}
Aggregations