You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by sb...@apache.org on 2012/01/25 18:28:47 UTC

svn commit: r1235842 - in /james/jsieve/trunk: mailet/src/main/java/org/apache/jsieve/mailet/ main/src/main/java/org/apache/jsieve/

Author: sbrewin
Date: Wed Jan 25 17:28:47 2012
New Revision: 1235842

URL: http://svn.apache.org/viewvc?rev=1235842&view=rev
Log:
JSIEVE-78 Add a Mail notification mechanism for when Sieve scripts failAdd a Mail notification mechanism for when Sieve scripts fail
JSIEVE-80 Add the ability to advertise the available Sieve extensions

Modified:
    james/jsieve/trunk/mailet/src/main/java/org/apache/jsieve/mailet/SieveMailboxMailet.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManager.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManagerImpl.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManager.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManagerImpl.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/SieveFactory.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManager.java
    james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManagerImpl.java

Modified: james/jsieve/trunk/mailet/src/main/java/org/apache/jsieve/mailet/SieveMailboxMailet.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/mailet/src/main/java/org/apache/jsieve/mailet/SieveMailboxMailet.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/mailet/src/main/java/org/apache/jsieve/mailet/SieveMailboxMailet.java (original)
+++ james/jsieve/trunk/mailet/src/main/java/org/apache/jsieve/mailet/SieveMailboxMailet.java Wed Jan 25 17:28:47 2012
@@ -19,21 +19,33 @@
 
 package org.apache.jsieve.mailet;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.io.UnsupportedEncodingException;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.Scanner;
 import java.util.Vector;
 
+import javax.activation.DataHandler;
 import javax.mail.Header;
 import javax.mail.MessagingException;
 import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
 import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.util.ByteArrayDataSource;
 
 import org.apache.commons.logging.Log;
 import org.apache.jsieve.ConfigurationManager;
 import org.apache.jsieve.SieveConfigurationException;
 import org.apache.jsieve.SieveFactory;
+import org.apache.jsieve.exception.SieveException;
+import org.apache.jsieve.parser.generated.ParseException;
+import org.apache.jsieve.parser.generated.TokenMgrError;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailAddress;
 import org.apache.mailet.MailetConfig;
@@ -54,7 +66,7 @@ import org.apache.mailet.base.RFC2822Hea
  * </table>
  */
 public class SieveMailboxMailet extends GenericMailet {
-
+    
     /**
      * The delivery header
      */
@@ -315,7 +327,6 @@ public class SieveMailboxMailet extends 
      * @param mail
      * @throws MessagingException
      */
-    @SuppressWarnings("deprecation")
     public void storeMail(MailAddress sender, MailAddress recipient,
             Mail mail) throws MessagingException {
         if (recipient == null) {
@@ -331,42 +342,49 @@ public class SieveMailboxMailet extends 
  
     }
     
-    void sieveMessage(MailAddress recpient, Mail aMail) throws MessagingException {
-    	String username = getUsername(recpient);
-        // Evaluate the script against the mail
-        String relativeUri = "//" + username +"/sieve"; 
-        try
-        {
-            final InputStream ins = locator.get(relativeUri);
-            
-            SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
-                    getMailetContext(), actionDispatcher, poster);
-            aMailAdapter.setLog(log);
-            // This logging operation is potentially costly
-            if (verbose) {
-                log("Evaluating " + aMailAdapter.toString() + "against \""
-                    + relativeUri + "\"");
-            }
-            factory.evaluate(aMailAdapter, factory.parse(ins));
-        }
-        catch (Exception ex)
-        {
-            //
-            // SLIEVE is a mail filtering protocol.
+    protected void sieveMessage(MailAddress recipient, Mail aMail) throws MessagingException {
+        String username = getUsername(recipient);
+        try {
+            final InputStream ins = locator.get(getScriptUri(recipient));
+            sieveMessageEvaluate(recipient, aMail, ins);
+        } catch (Exception ex) {
+            // SIEVE is a mail filtering protocol.
             // Rejecting the mail because it cannot be filtered
             // seems very unfriendly.
-            // So just log and store in INBOX.
-            //
+            // So just log and store in INBOX
             if (isInfoLoggingOn()) {
                 log("Cannot evaluate Sieve script. Storing mail in user INBOX.", ex);
             }
-            storeMessageInbox(username, aMail);
+            storeMessageInbox(username, aMail.getMessage());
         }
     }
     
-    void storeMessageInbox(String username, Mail mail) throws MessagingException {
+    private void sieveMessageEvaluate(MailAddress recipient, Mail aMail, InputStream ins) throws MessagingException, IOException {    
+            try {
+                SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
+                        getMailetContext(), actionDispatcher, poster);
+                aMailAdapter.setLog(log);
+                // This logging operation is potentially costly
+                if (verbose) {
+                    log("Evaluating " + aMailAdapter.toString() + "against \""
+                            + getScriptUri(recipient) + "\"");
+                }
+                factory.evaluate(aMailAdapter, factory.parse(ins));
+            } catch (SieveException ex) {
+                handleFailure(recipient, aMail, ex);
+            }
+            catch (ParseException ex) {
+                handleFailure(recipient, aMail, ex);
+            }
+            catch (TokenMgrError ex)
+            {
+                handleFailure(recipient, aMail, new SieveException(ex));
+            }
+    }
+    
+    protected void storeMessageInbox(String username, MimeMessage message) throws MessagingException {
         String url = "mailbox://" + username + "/";
-        poster.post(url, mail.getMessage());
+        poster.post(url, message);
     }
 
     /**
@@ -396,6 +414,62 @@ public class SieveMailboxMailet extends 
      * @return username
      */
     protected String getUsername(MailAddress m) {
-    	return m.getLocalPart() + "@localhost";
+        return m.getLocalPart() + "@localhost";
+    }
+    
+    /**
+     * Return the URI for the sieve script
+     *
+     * @param m
+     * @return
+     */
+    protected String getScriptUri(MailAddress m) {
+        return "//" + getUsername(m) + "/sieve";
     }
+    
+    /**
+     * Deliver the original mail as an attachment with the main part being an error report.
+     *
+     * @param recipient
+     * @param aMail
+     * @param ex
+     * @throws MessagingException
+     * @throws IOException 
+     */
+    protected void handleFailure(MailAddress recipient, Mail aMail, Exception ex)
+            throws MessagingException, IOException {
+        String user = getUsername(recipient);
+
+        MimeMessage originalMessage = aMail.getMessage();
+        MimeMessage message = new MimeMessage(originalMessage);
+        MimeMultipart multipart = new MimeMultipart();
+        
+        MimeBodyPart noticePart = new MimeBodyPart();
+        noticePart.setText(new StringBuilder()
+            .append("An error was encountered while processing this mail with the active sieve script for user \"")
+            .append(user)
+            .append("\". The error encountered was:\r\n")
+            .append(ex.getLocalizedMessage())
+            .append("\r\n")
+            .toString());      
+        multipart.addBodyPart(noticePart);
+        
+        MimeBodyPart originalPart = new MimeBodyPart();
+        originalPart.setContent(originalMessage, "message/rfc822");
+        if ((originalMessage.getSubject() != null) && (!originalMessage.getSubject().trim().isEmpty())) {
+            originalPart.setFileName(originalMessage.getSubject().trim());
+        } else {
+            originalPart.setFileName("No Subject");
+        }
+        originalPart.setDisposition(MimeBodyPart.INLINE);
+        multipart.addBodyPart(originalPart);
+        
+        message.setContent(multipart);
+        message.setSubject("[SIEVE ERROR] " + originalMessage.getSubject());
+        message.setHeader("X-Priority", "1");
+        message.saveChanges();
+        
+        storeMessageInbox(user, message);
+    }
+   
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManager.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManager.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManager.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManager.java Wed Jan 25 17:28:47 2012
@@ -19,6 +19,8 @@
 
 package org.apache.jsieve;
 
+import java.util.List;
+
 import org.apache.jsieve.exception.LookupException;
 
 /**
@@ -49,4 +51,11 @@ public interface CommandManager {
      * @return boolean - True if the Command name is configured.
      */
     public boolean isCommandSupported(String name);
+    
+    /**
+     * Answer a List of the names of supported Sieve extensions.
+     *
+     * @return
+     */
+    public List<String> getExtensions();
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManagerImpl.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManagerImpl.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManagerImpl.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/CommandManagerImpl.java Wed Jan 25 17:28:47 2012
@@ -19,18 +19,28 @@
 
 package org.apache.jsieve;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.jsieve.exception.LookupException;
 
 /**
- * <p>Maps command names to comman implementations.</p>
+ * <p>Maps command names to common implementations.</p>
  * <h4>Thread Safety</h4>
  * <p>
  * Instances may safely be accessed concurrently by multiple threads.
  * </p>
  */
 public class CommandManagerImpl implements CommandManager {
+    
+    private static List<String> IMPLICITLY_DECLARED = Arrays.asList("if", "else", "elsif",
+            "require", "stop", "keep", "discard", "redirect");
+
+    private static boolean isImplicitlyDeclared(String name) {
+        return IMPLICITLY_DECLARED.contains(name);
+    }
 
     private final ConcurrentMap<String, String> classNameMap;
 
@@ -123,4 +133,19 @@ public class CommandManagerImpl implemen
                     + "' not mapped.");
         return className;
     }
+
+    /**
+     * @see org.apache.jsieve.CommandManager#getExtensions()
+     */
+    public List<String> getExtensions() {
+        List<String> extensions = new ArrayList<String>(classNameMap.size());
+        for (String key : classNameMap.keySet())
+        {
+            if (!isImplicitlyDeclared(key))
+            {
+                extensions.add(key);
+            }
+        }
+        return extensions;
+    }
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManager.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManager.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManager.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManager.java Wed Jan 25 17:28:47 2012
@@ -19,6 +19,8 @@
 
 package org.apache.jsieve;
 
+import java.util.List;
+
 import org.apache.jsieve.comparators.Comparator;
 import org.apache.jsieve.exception.LookupException;
 
@@ -56,4 +58,11 @@ public interface ComparatorManager {
      * @return true when supported, false otherwise
      */
     public boolean isSupported(String name);
+    
+    /**
+     * Answer a List of the names of supported Sieve extensions.
+     *
+     * @return
+     */
+    public List<String> getExtensions();
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManagerImpl.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManagerImpl.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManagerImpl.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/ComparatorManagerImpl.java Wed Jan 25 17:28:47 2012
@@ -22,6 +22,8 @@ package org.apache.jsieve;
 import static org.apache.jsieve.Constants.COMPARATOR_ASCII_CASEMAP_NAME;
 import static org.apache.jsieve.Constants.COMPARATOR_OCTET_NAME;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 
@@ -162,4 +164,19 @@ public class ComparatorManagerImpl imple
             return false;
         }
     }
+
+    /**
+     * @see org.apache.jsieve.ComparatorManager#getExtensions()
+     */
+    public List<String> getExtensions() {
+        List<String> extensions = new ArrayList<String>(classNameMap.size());
+        for (String key : classNameMap.keySet())
+        {
+            if (!isImplicitlyDeclared(key))
+            {
+                extensions.add(key);
+            }
+        }
+        return extensions;
+    }
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/SieveFactory.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/SieveFactory.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/SieveFactory.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/SieveFactory.java Wed Jan 25 17:28:47 2012
@@ -20,6 +20,8 @@
 package org.apache.jsieve;
 
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.jsieve.exception.SieveException;
@@ -198,4 +200,22 @@ public class SieveFactory {
             throws ParseException, SieveException {
         evaluate(mail, parse(inputStream));
     }
+    
+    /**
+     * <p>Answer a List of supported Sieve extensions. This depends on the configured Command, Comparator
+     * and Test managers.
+     *
+     * @return a List of supported Sieve extensions
+     */
+    public List<String> getExtensions() {
+        List<String> commands = commandManager.getExtensions();
+        List<String> comparators = comparatorManager.getExtensions();
+        List<String> tests = testManager.getExtensions();
+        List<String> extensions = new ArrayList<String>(commands.size() + comparators.size()
+                + tests.size());
+        extensions.addAll(commands);
+        extensions.addAll(comparators);
+        extensions.addAll(tests);
+        return extensions;
+    }
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManager.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManager.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManager.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManager.java Wed Jan 25 17:28:47 2012
@@ -19,6 +19,8 @@
 
 package org.apache.jsieve;
 
+import java.util.List;
+
 import org.apache.jsieve.exception.LookupException;
 import org.apache.jsieve.tests.ExecutableTest;
 
@@ -40,4 +42,11 @@ public interface TestManager {
      * @throws LookupException
      */
     public ExecutableTest getTest(String name) throws LookupException;
+    
+    /**
+     * Answer a List of the names of supported Sieve extensions.
+     *
+     * @return
+     */
+    public List<String> getExtensions();
 }

Modified: james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManagerImpl.java
URL: http://svn.apache.org/viewvc/james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManagerImpl.java?rev=1235842&r1=1235841&r2=1235842&view=diff
==============================================================================
--- james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManagerImpl.java (original)
+++ james/jsieve/trunk/main/src/main/java/org/apache/jsieve/TestManagerImpl.java Wed Jan 25 17:28:47 2012
@@ -19,6 +19,9 @@
 
 package org.apache.jsieve;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.jsieve.exception.LookupException;
@@ -32,6 +35,13 @@ import org.apache.jsieve.tests.Executabl
  * </p>
  */
 public class TestManagerImpl implements TestManager {
+       
+    private static List<String> IMPLICITLY_DECLARED = Arrays.asList("address",
+            "allof", "anyof", "exists", "false", "header", "not", "size", "true");
+
+    private static boolean isImplicitlyDeclared(String name) {
+        return IMPLICITLY_DECLARED.contains(name);
+    }
 
     private final ConcurrentMap<String, String> classNameMap;
 
@@ -106,4 +116,20 @@ public class TestManagerImpl implements 
             throw new LookupException("Test named '" + name + "' not mapped.");
         return className;
     }
+
+    /**
+     * @see org.apache.jsieve.TestManager#getExtensions()
+     */
+    public List<String> getExtensions() {
+        List<String> extensions = new ArrayList<String>(classNameMap.size());
+        for (String key : classNameMap.keySet())
+        {
+            if (!isImplicitlyDeclared(key))
+            {
+                extensions.add(key);
+            }
+        }
+        return extensions;
+    }
+
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org