Repository: james-project
Updated Branches:
  refs/heads/master 2a3076909 -> def450ba2


JAMES-1854 Get a ride of one level of inheritance inside SieveMailet


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/c5bcdf8e
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/c5bcdf8e
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/c5bcdf8e

Branch: refs/heads/master
Commit: c5bcdf8e89851e64ee48963740f2d4bc56ccf4da
Parents: 1559058
Author: Benoit Tellier <[email protected]>
Authored: Thu Oct 27 15:29:02 2016 +0200
Committer: Benoit Tellier <[email protected]>
Committed: Fri Nov 18 18:46:45 2016 +0700

----------------------------------------------------------------------
 .../transport/mailets/delivery/SieveMailet.java | 336 ++++++++++++--
 .../mailets/jsieve/CommonsLoggingAdapter.java   |   2 +-
 .../mailets/jsieve/SieveMailboxMailet.java      | 463 -------------------
 3 files changed, 308 insertions(+), 493 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/c5bcdf8e/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailet.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailet.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailet.java
index c074858..fd74dff 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailet.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailet.java
@@ -18,11 +18,21 @@
  ****************************************************************/
 package org.apache.james.transport.mailets.delivery;
 
+import java.io.IOException;
+import java.util.Collection;
 import java.util.Date;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
 
+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 org.apache.commons.logging.Log;
 import org.apache.james.core.MimeMessageInputStream;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
@@ -31,24 +41,45 @@ import 
org.apache.james.mailbox.exception.BadCredentialsException;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxConstants;
 import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.transport.mailets.jsieve.ActionDispatcher;
+import org.apache.james.transport.mailets.jsieve.CommonsLoggingAdapter;
 import org.apache.james.transport.mailets.jsieve.Poster;
 import org.apache.james.transport.mailets.jsieve.ResourceLocator;
-import org.apache.james.transport.mailets.jsieve.SieveMailboxMailet;
+import org.apache.james.transport.mailets.jsieve.SieveMailAdapter;
 import org.apache.james.transport.util.MailetContextLog;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
+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;
+import org.apache.mailet.MailetException;
+import org.apache.mailet.base.GenericMailet;
+import org.apache.mailet.base.RFC2822Headers;
 
 /**
  * Contains resource bindings.
  */
-public class SieveMailet extends SieveMailboxMailet implements Poster {
+public class SieveMailet  extends GenericMailet implements Poster {
     private final UsersRepository usersRepos;
     private final MailboxManager mailboxManager;
     private final String folder;
     private final ResourceLocator resourceLocator;
+    private String deliveryHeader;
+    private boolean resetReturnPath;
+    private Poster poster;
+    private ResourceLocator locator;
+    private boolean verbose = false;
+    private boolean consume = true;
+    private boolean quiet = true;
+    private SieveFactory factory;
+    private ActionDispatcher actionDispatcher;
+    private Log log;
 
     public SieveMailet(UsersRepository usersRepos, MailboxManager 
mailboxManager, ResourceLocator resourceLocator, String folder) {
         this.usersRepos = usersRepos;
@@ -58,44 +89,111 @@ public class SieveMailet extends SieveMailboxMailet 
implements Poster {
     }
 
     @Override
-    public void init(MailetConfig config) throws MessagingException {
+    public void init() throws MessagingException {
+
+        this.deliveryHeader = getInitParameter("addDeliveryHeader");
+        this.resetReturnPath = getInitParameter("resetReturnPath", true);
+        this.consume = getInitParameter("consume", true);
+        this.verbose = getInitParameter("verbose", false);
+        this.quiet = getInitParameter("quiet", false);
+
+        actionDispatcher = new ActionDispatcher();
+
         setLocator(resourceLocator);
         setPoster(this);
-        super.init(config);
+
+        if (poster == null || locator == null) {
+            throw new MailetException("Not initialised. Please ensure that the 
mailet container supports either" +
+                " setter or constructor injection");
+        }
+
+        try {
+            final ConfigurationManager configurationManager = new 
ConfigurationManager();
+            final int logLevel;
+            if (verbose) {
+                logLevel = CommonsLoggingAdapter.TRACE;
+            } else if (quiet) {
+                logLevel = CommonsLoggingAdapter.FATAL;
+            } else {
+                logLevel = CommonsLoggingAdapter.WARN;
+            }
+            log = new CommonsLoggingAdapter(this, logLevel);
+            configurationManager.setLog(log);
+            factory = configurationManager.build();
+        } catch (SieveConfigurationException e) {
+            throw new MessagingException("Failed to load standard Sieve 
configuration.", e);
+        }
+    }
+
+    public ResourceLocator getLocator() {
+        return locator;
+    }
+
+    public void setLocator(ResourceLocator locator) {
+        this.locator = locator;
+    }
+
+    public Poster getPoster() {
+        return poster;
+    }
+
+    public void setPoster(Poster poster) {
+        this.poster = poster;
+    }
+
+    public boolean isConsume() {
+        return consume;
+    }
+
+    public void setConsume(boolean consume) {
+        this.consume = consume;
+    }
+
+    public boolean isVerbose() {
+        return verbose;
+    }
+
+    public void setVerbose(boolean verbose) {
+        this.verbose = verbose;
+    }
+
+    public boolean isQuiet() {
+        return quiet;
+    }
+
+    public void setQuiet(boolean quiet) {
+        this.quiet = quiet;
+    }
+
+    public boolean isInfoLoggingOn() {
+        return verbose || !quiet;
     }
 
-    /**
-     * Return the username to use for sieve processing for the given
-     * MailAddress. If virtualhosting is supported use the full emailaddrees as
-     * username
-     * 
-     * @param m
-     * @return username
-     */
     protected String getUsername(MailAddress m) {
         try {
             if (usersRepos.supportVirtualHosting()) {
                 return m.toString();
             } else {
-                return super.getUsername(m);
+                return m.getLocalPart() + "@localhost";
             }
         } catch (UsersRepositoryException e) {
             log("Unable to access UsersRepository", e);
-            return super.getUsername(m);
+            return m.getLocalPart() + "@localhost";
 
         }
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.apache.jsieve.mailet.SieveMailboxMailet#storeMail(org.apache.mailet
-     * .MailAddress, org.apache.mailet.MailAddress, org.apache.mailet.Mail)
-     */
-    @Override
     public void storeMail(MailAddress sender, MailAddress recipient, Mail 
mail) throws MessagingException {
-        super.storeMail(sender, recipient, mail);
+        if (recipient == null) {
+            throw new IllegalArgumentException(
+                "Recipient for mail to be spooled cannot be null.");
+        }
+        if (mail.getMessage() == null) {
+            throw new IllegalArgumentException(
+                "Mail message to be spooled cannot be null.");
+        }
+
+        sieveMessage(recipient, mail);
         String s;
         if (sender != null) {
             s = sender.toString();
@@ -108,12 +206,6 @@ public class SieveMailet extends SieveMailboxMailet 
implements Poster {
                 + " in folder " + this.folder);
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.jsieve.mailet.Poster#post(java.lang.String,
-     * javax.mail.internet.MimeMessage)
-     */
     @Override
     public void post(String url, MimeMessage mail) throws MessagingException {
 
@@ -220,4 +312,190 @@ public class SieveMailet extends SieveMailboxMailet 
implements Poster {
         }
     }
 
+
+    /**
+     * Delivers a mail to a local mailbox.
+     *
+     * @param mail
+     *            the mail being processed
+     *
+     * @throws MessagingException
+     *             if an error occurs while storing the mail
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public void service(Mail mail) throws MessagingException {
+        Collection<MailAddress> recipients = mail.getRecipients();
+        Collection<MailAddress> errors = new Vector<MailAddress>();
+
+        MimeMessage message = null;
+        if (deliveryHeader != null || resetReturnPath) {
+            message = mail.getMessage();
+        }
+
+        if (resetReturnPath) {
+            // Set Return-Path and remove all other Return-Path headers from 
the
+            // message
+            // This only works because there is a placeholder inserted by
+            // MimeMessageWrapper
+            message.setHeader(RFC2822Headers.RETURN_PATH,
+                (mail.getSender() == null ? "<>" : "<" + mail.getSender()
+                    + ">"));
+        }
+
+        Enumeration headers;
+        InternetHeaders deliveredTo = new InternetHeaders();
+        if (deliveryHeader != null) {
+            // Copy any Delivered-To headers from the message
+            headers = message
+                .getMatchingHeaders(new String[] { deliveryHeader });
+            while (headers.hasMoreElements()) {
+                Header header = (Header) headers.nextElement();
+                deliveredTo.addHeader(header.getName(), header.getValue());
+            }
+        }
+
+        for (Iterator<MailAddress> i = recipients.iterator(); i.hasNext();) {
+            MailAddress recipient = i.next();
+            try {
+                if (deliveryHeader != null) {
+                    // Add qmail's de facto standard Delivered-To header
+                    message.addHeader(deliveryHeader, recipient.toString());
+                }
+
+                storeMail(mail.getSender(), recipient, mail);
+
+                if (deliveryHeader != null) {
+                    if (i.hasNext()) {
+                        // Remove headers but leave all placeholders
+                        message.removeHeader(deliveryHeader);
+                        headers = deliveredTo.getAllHeaders();
+                        // And restore any original Delivered-To headers
+                        while (headers.hasMoreElements()) {
+                            Header header = (Header) headers.nextElement();
+                            message.addHeader(header.getName(), header
+                                .getValue());
+                        }
+                    }
+                }
+            } catch (Exception ex) {
+                log("Error while storing mail.", ex);
+                errors.add(recipient);
+            }
+        }
+
+        if (!errors.isEmpty()) {
+            // If there were errors, we redirect the email to the ERROR
+            // processor.
+            // In order for this server to meet the requirements of the SMTP
+            // specification, mails on the ERROR processor must be returned to
+            // the sender. Note that this email doesn't include any details
+            // regarding the details of the failure(s).
+            // In the future we may wish to address this.
+            getMailetContext().sendMail(mail.getSender(), errors,
+                mail.getMessage(), Mail.ERROR);
+        }
+        if (consume) {
+            // Consume this message
+            mail.setState(Mail.GHOST);
+        }
+    }
+
+    protected void sieveMessage(MailAddress recipient, Mail aMail) throws 
MessagingException {
+        String username = getUsername(recipient);
+        try {
+            final ResourceLocator.UserSieveInformation userSieveInformation = 
locator.get(getScriptUri(recipient));
+            sieveMessageEvaluate(recipient, aMail, userSieveInformation);
+        } 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
+            if (isInfoLoggingOn()) {
+                log("Cannot evaluate Sieve script. Storing mail in user 
INBOX.", ex);
+            }
+            storeMessageInbox(username, aMail.getMessage());
+        }
+    }
+
+    private void sieveMessageEvaluate(MailAddress recipient, Mail aMail, 
ResourceLocator.UserSieveInformation userSieveInformation) throws 
MessagingException, IOException {
+        try {
+            SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
+                getMailetContext(), actionDispatcher, poster, 
userSieveInformation.getScriptActivationDate(),
+                userSieveInformation.getScriptInterpretationDate(), recipient);
+            aMailAdapter.setLog(log);
+            // This logging operation is potentially costly
+            if (verbose) {
+                log("Evaluating " + aMailAdapter.toString() + "against \""
+                    + getScriptUri(recipient) + "\"");
+            }
+            factory.evaluate(aMailAdapter, 
factory.parse(userSieveInformation.getScriptContent()));
+        } 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, message);
+    }
+
+
+    /**
+     * 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("An error was encountered while processing this 
mail with the active sieve script for user \""
+            + user + "\". The error encountered was:\r\n" + 
ex.getLocalizedMessage() + "\r\n");
+        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);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/c5bcdf8e/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/CommonsLoggingAdapter.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/CommonsLoggingAdapter.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/CommonsLoggingAdapter.java
index 9999a99..66628af 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/CommonsLoggingAdapter.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/CommonsLoggingAdapter.java
@@ -24,7 +24,7 @@ import org.apache.mailet.base.GenericMailet;
 /**
  * Adapts commons logging to mailet logging.
  */
-class CommonsLoggingAdapter implements Log {
+public class CommonsLoggingAdapter implements Log {
     
     public static final int TRACE = 6;
     public static final int DEBUG = 5;

http://git-wip-us.apache.org/repos/asf/james-project/blob/c5bcdf8e/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/SieveMailboxMailet.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/SieveMailboxMailet.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/SieveMailboxMailet.java
deleted file mode 100644
index d58938b..0000000
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/SieveMailboxMailet.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.transport.mailets.jsieve;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Vector;
-
-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 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;
-import org.apache.mailet.MailetException;
-import org.apache.mailet.base.GenericMailet;
-import org.apache.mailet.base.RFC2822Headers;
-
-/**
- * <p>Executes a <a href='http://www.rfc-editor.org/rfc/rfc3028.txt'>Sieve</a>
- * script against incoming mail. The script applied is based on the 
recipient.</p>
- * <h4>Init Parameters</h4>
- * <table>
- * 
<thead><tr><th>Name</th><th>Required</th><th>Values</th><th>Role</th></thead>
- * <tr><td>verbose</td><td>No - defaults to false</td><td>true (ignoring case) 
to enable, otherwise disable</td>
- * <td>
- * Enables verbose logging.
- * </td></tr>
- * </table>
- */
-public class SieveMailboxMailet extends GenericMailet {
-    
-    /**
-     * The delivery header
-     */
-    private String deliveryHeader;
-
-    /**
-     * resetReturnPath
-     */
-    private boolean resetReturnPath;
-    /** Experimental */
-    private Poster poster;
-    /** Experimental */
-    private ResourceLocator locator;
-    
-    /** Indicates whether this mailet should log verbosely */
-    private boolean verbose = false;
-    
-    private boolean consume = true;
-    /** Indicates whether this mailet should log minimal information */
-    private boolean quiet = true;
-
-    private SieveFactory factory;
-
-    private ActionDispatcher actionDispatcher;
-
-    private Log log;
-
-    /**
-     * For SDI
-     */
-    public SieveMailboxMailet() {}
-    
-    /**
-     * CDI
-     * @param poster not null
-     */
-    public SieveMailboxMailet(Poster poster, ResourceLocator locator) {
-        this();
-        this.poster = poster;
-        this.locator = locator;
-    }
-
-    
-    public ResourceLocator getLocator() {
-        return locator;
-    }
-
-    /**
-     * For SDI
-     * @param locator not null
-     */
-    public void setLocator(ResourceLocator locator) {
-        this.locator = locator;
-    }
-
-    public Poster getPoster() {
-        return poster;
-    }
-    
-    /**
-     * For SDI
-     * @param poster not null
-     */
-    public void setPoster(Poster poster) {
-        this.poster = poster;
-    }
-
-    /**
-     * Is this mailet GHOSTing all mail it processes?
-     * @return true when mailet consumes all mail, false otherwise
-     */
-    public boolean isConsume() {
-        return consume;
-    }
-
-    /**
-     * Sets whether this mailet should GHOST all mail.
-     * @param consume true when the mailet should consume all mail, 
-     * false otherwise
-     */
-    public void setConsume(boolean consume) {
-        this.consume = consume;
-    }
-
-    /**
-     * Is this mailet logging verbosely?
-     * This property is set by init parameters.
-     * @return true if logging should be verbose, false otherwise
-     */
-    public boolean isVerbose() {
-        return verbose;
-    }
-
-
-    /**
-     * Sets whether logging should be verbose for this mailet.
-     * This property is set by init parameters.
-     * This setting overrides {@link #isQuiet()}.
-     * @param verbose true when logging should be verbose,
-     * false otherwise
-     */
-    public void setVerbose(boolean verbose) {
-        this.verbose = verbose;
-    }
-
-    /**
-     * Is the logging for this mailet set to minimal?
-     * @return true
-     */
-    public boolean isQuiet() {
-        return quiet;
-    }
-
-    /**
-     * Sets the logging for this mailet to minimal.
-     * This is overriden by {@link #setVerbose(boolean)}.
-     * @param quiet true for minimal logging, false otherwise
-     */
-    public void setQuiet(boolean quiet) {
-        this.quiet = quiet;
-    }
-    
-   
-    /**
-     * Is informational logging turned on? 
-     * @return true when minimal logging is off,
-     * false when logging is minimal
-     */
-    public boolean isInfoLoggingOn() {
-        return verbose || !quiet;
-    }
-
-    @Override
-    public void init(MailetConfig config) throws MessagingException {
-        
-        super.init(config);
-
-        try {
-            final ConfigurationManager configurationManager = new 
ConfigurationManager();
-            final int logLevel;
-            if (verbose) {
-                logLevel = CommonsLoggingAdapter.TRACE;
-            } else if (quiet) {
-                logLevel = CommonsLoggingAdapter.FATAL;
-            } else {
-                logLevel = CommonsLoggingAdapter.WARN;
-            }
-            log = new CommonsLoggingAdapter(this, logLevel);
-            configurationManager.setLog(log);
-            factory = configurationManager.build();
-        } catch (SieveConfigurationException e) {
-            throw new MessagingException("Failed to load standard Sieve 
configuration.", e);
-        }
-    }
-
-    /**
-     * Delivers a mail to a local mailbox.
-     * 
-     * @param mail
-     *            the mail being processed
-     * 
-     * @throws MessagingException
-     *             if an error occurs while storing the mail
-     */
-    @Override
-    public void service(Mail mail) throws MessagingException {
-        Collection<MailAddress> recipients = mail.getRecipients();
-        Collection<MailAddress> errors = new Vector<MailAddress>();
-
-        MimeMessage message = null;
-        if (deliveryHeader != null || resetReturnPath) {
-            message = mail.getMessage();
-        }
-
-        if (resetReturnPath) {
-            // Set Return-Path and remove all other Return-Path headers from 
the
-            // message
-            // This only works because there is a placeholder inserted by
-            // MimeMessageWrapper
-            message.setHeader(RFC2822Headers.RETURN_PATH,
-                    (mail.getSender() == null ? "<>" : "<" + mail.getSender()
-                            + ">"));
-        }
-
-        Enumeration<?> headers;
-        InternetHeaders deliveredTo = new InternetHeaders();
-        if (deliveryHeader != null) {
-            // Copy any Delivered-To headers from the message
-            headers = message
-                    .getMatchingHeaders(new String[] { deliveryHeader });
-            while (headers.hasMoreElements()) {
-                Header header = (Header) headers.nextElement();
-                deliveredTo.addHeader(header.getName(), header.getValue());
-            }
-        }
-
-        for (Iterator<MailAddress> i = recipients.iterator(); i.hasNext();) {
-            MailAddress recipient = i.next();
-            try {
-                if (deliveryHeader != null) {
-                    // Add qmail's de facto standard Delivered-To header
-                    message.addHeader(deliveryHeader, recipient.toString());
-                }
-
-                storeMail(mail.getSender(), recipient, mail);
-
-                if (deliveryHeader != null) {
-                    if (i.hasNext()) {
-                        // Remove headers but leave all placeholders
-                        message.removeHeader(deliveryHeader);
-                        headers = deliveredTo.getAllHeaders();
-                        // And restore any original Delivered-To headers
-                        while (headers.hasMoreElements()) {
-                            Header header = (Header) headers.nextElement();
-                            message.addHeader(header.getName(), header
-                                    .getValue());
-                        }
-                    }
-                }
-            } catch (Exception ex) {
-                log("Error while storing mail.", ex);
-                errors.add(recipient);
-            }
-        }
-
-        if (!errors.isEmpty()) {
-            // If there were errors, we redirect the email to the ERROR
-            // processor.
-            // In order for this server to meet the requirements of the SMTP
-            // specification, mails on the ERROR processor must be returned to
-            // the sender. Note that this email doesn't include any details
-            // regarding the details of the failure(s).
-            // In the future we may wish to address this.
-            getMailetContext().sendMail(mail.getSender(), errors,
-                    mail.getMessage(), Mail.ERROR);
-        }
-        if (consume) {
-            // Consume this message
-            mail.setState(Mail.GHOST);
-        }
-    }
-
-    /**
-     * Return a string describing this mailet.
-     * 
-     * @return a string describing this mailet
-     */
-    @Override
-    public String getMailetInfo() {
-        return "Sieve Mailbox Mailet";
-    }
-
-    /**
-     * 
-     * @param sender
-     * @param recipient
-     * @param mail
-     * @throws MessagingException
-     */
-    public void storeMail(MailAddress sender, MailAddress recipient,
-            Mail mail) throws MessagingException {
-        if (recipient == null) {
-            throw new IllegalArgumentException(
-                    "Recipient for mail to be spooled cannot be null.");
-        }
-        if (mail.getMessage() == null) {
-            throw new IllegalArgumentException(
-                    "Mail message to be spooled cannot be null.");
-        }
-        
-        sieveMessage(recipient, mail);
- 
-    }
-    
-    protected void sieveMessage(MailAddress recipient, Mail aMail) throws 
MessagingException {
-        String username = getUsername(recipient);
-        try {
-            final ResourceLocator.UserSieveInformation userSieveInformation = 
locator.get(getScriptUri(recipient));
-            sieveMessageEvaluate(recipient, aMail, userSieveInformation);
-        } 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
-            if (isInfoLoggingOn()) {
-                log("Cannot evaluate Sieve script. Storing mail in user 
INBOX.", ex);
-            }
-            storeMessageInbox(username, aMail.getMessage());
-        }
-    }
-    
-    private void sieveMessageEvaluate(MailAddress recipient, Mail aMail, 
ResourceLocator.UserSieveInformation userSieveInformation) throws 
MessagingException, IOException {
-            try {
-                SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
-                    getMailetContext(), actionDispatcher, poster, 
userSieveInformation.getScriptActivationDate(),
-                    userSieveInformation.getScriptInterpretationDate(), 
recipient);
-                aMailAdapter.setLog(log);
-                // This logging operation is potentially costly
-                if (verbose) {
-                    log("Evaluating " + aMailAdapter.toString() + "against \""
-                            + getScriptUri(recipient) + "\"");
-                }
-                factory.evaluate(aMailAdapter, 
factory.parse(userSieveInformation.getScriptContent()));
-            } 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, message);
-    }
-
-    /**
-     * @see org.apache.mailet.base.GenericMailet#init()
-     */
-    @Override
-    public void init() throws MessagingException {
-        super.init();
-        if (poster == null || locator == null) {
-            throw new MailetException("Not initialised. Please ensure that the 
mailet container supports either" +
-                    " setter or constructor injection");
-        }
-        
-        this.deliveryHeader = getInitParameter("addDeliveryHeader");
-        this.resetReturnPath = getInitParameter("resetReturnPath", true);
-        this.consume = getInitParameter("consume", true);
-        this.verbose = getInitParameter("verbose", false);
-        this.quiet = getInitParameter("quiet", false);
-        
-        actionDispatcher = new ActionDispatcher();
-    }
-    
-    /**
-     * Return the username to use for sieve processing for the given 
MailAddress
-     * 
-     * @param m
-     * @return username
-     */
-    protected String getUsername(MailAddress m) {
-        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("An error was encountered while processing this 
mail with the active sieve script for user \""
-                + user + "\". The error encountered was:\r\n" + 
ex.getLocalizedMessage() + "\r\n");
-        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);
-    }
-   
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to