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 ro...@apache.org on 2016/11/23 13:50:11 UTC

[08/46] james-project git commit: JAMES-1854 Move Sieve related classes in SIEVE package

JAMES-1854 Move Sieve related classes in SIEVE package


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

Branch: refs/heads/master
Commit: 05b9040d380f8ef7b6d63de492f8fd612a95604a
Parents: e9cba9c
Author: Benoit Tellier <bt...@linagora.com>
Authored: Fri Oct 28 15:58:56 2016 +0200
Committer: Benoit Tellier <bt...@linagora.com>
Committed: Fri Nov 18 18:46:46 2016 +0700

----------------------------------------------------------------------
 .../transport/mailets/SieveLocalDelivery.java   |   6 +-
 .../mailets/SieveToRecipientFolder.java         |   4 +-
 .../delivery/SieveFailureMessageComposer.java   |  57 ------
 .../mailets/delivery/SieveMailStorer.java       | 184 ------------------
 .../transport/mailets/delivery/SievePoster.java | 106 -----------
 .../delivery/SieveFailureMessageComposer.java   |  57 ++++++
 .../jsieve/delivery/SieveMailStorer.java        | 186 +++++++++++++++++++
 .../mailets/jsieve/delivery/SievePoster.java    | 108 +++++++++++
 .../mailets/delivery/SieveIntegrationTest.java  |   2 +
 9 files changed, 357 insertions(+), 353 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveLocalDelivery.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveLocalDelivery.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveLocalDelivery.java
index 9dfa5f2..6826c83 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveLocalDelivery.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveLocalDelivery.java
@@ -27,12 +27,10 @@ import org.apache.commons.logging.Log;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.sieverepository.api.SieveRepository;
-import org.apache.james.transport.mailets.RecipientRewriteTable;
-import org.apache.james.transport.mailets.ResourceLocatorImpl;
 import org.apache.james.transport.mailets.delivery.MailDispatcher;
 import org.apache.james.transport.mailets.delivery.MailboxAppender;
-import org.apache.james.transport.mailets.delivery.SieveMailStorer;
-import org.apache.james.transport.mailets.delivery.SievePoster;
+import org.apache.james.transport.mailets.jsieve.delivery.SieveMailStorer;
+import org.apache.james.transport.mailets.jsieve.delivery.SievePoster;
 import org.apache.james.transport.mailets.jsieve.CommonsLoggingAdapter;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.mailet.Mail;

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveToRecipientFolder.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveToRecipientFolder.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveToRecipientFolder.java
index a574a15..56d3a7c 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveToRecipientFolder.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SieveToRecipientFolder.java
@@ -27,8 +27,8 @@ import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.sieverepository.api.SieveRepository;
 import org.apache.james.transport.mailets.delivery.MailDispatcher;
 import org.apache.james.transport.mailets.delivery.MailboxAppender;
-import org.apache.james.transport.mailets.delivery.SieveMailStorer;
-import org.apache.james.transport.mailets.delivery.SievePoster;
+import org.apache.james.transport.mailets.jsieve.delivery.SieveMailStorer;
+import org.apache.james.transport.mailets.jsieve.delivery.SievePoster;
 import org.apache.james.transport.mailets.jsieve.CommonsLoggingAdapter;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.mailet.Mail;

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveFailureMessageComposer.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveFailureMessageComposer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveFailureMessageComposer.java
deleted file mode 100644
index 241c714..0000000
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveFailureMessageComposer.java
+++ /dev/null
@@ -1,57 +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.delivery;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeBodyPart;
-import javax.mail.internet.MimeMessage;
-import javax.mail.internet.MimeMultipart;
-
-import org.apache.mailet.Mail;
-
-public class SieveFailureMessageComposer {
-
-    public static MimeMessage composeMessage(Mail aMail, Exception ex, String user) throws MessagingException {
-        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();
-        return message;
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailStorer.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailStorer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailStorer.java
deleted file mode 100644
index 5cfd2c0..0000000
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SieveMailStorer.java
+++ /dev/null
@@ -1,184 +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.delivery;
-
-import java.io.IOException;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
-import org.apache.commons.logging.Log;
-import org.apache.james.transport.mailets.jsieve.ActionDispatcher;
-import org.apache.james.transport.mailets.jsieve.ResourceLocator;
-import org.apache.james.transport.mailets.jsieve.SieveMailAdapter;
-import org.apache.james.user.api.UsersRepository;
-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.MailetContext;
-
-import com.google.common.base.Preconditions;
-
-public class SieveMailStorer implements MailStorer {
-
-    public static Builder builder() {
-        return new Builder();
-    }
-
-    public static class Builder {
-        private MailetContext mailetContext;
-        private UsersRepository usersRepos;
-        private SievePoster sievePoster;
-        private String folder;
-        private ResourceLocator resourceLocator;
-        private Log log;
-
-        public Builder folder(String folder) {
-            this.folder = folder;
-            return this;
-        }
-
-        public Builder usersRepository(UsersRepository usersRepository) {
-            this.usersRepos = usersRepository;
-            return this;
-        }
-
-        public Builder sievePoster(SievePoster sievePoster) {
-            this.sievePoster = sievePoster;
-            return this;
-        }
-
-        public Builder mailetContext(MailetContext mailetContext) {
-            this.mailetContext = mailetContext;
-            return this;
-        }
-
-        public Builder resourceLocator(ResourceLocator resourceLocator) {
-            this.resourceLocator = resourceLocator;
-            return this;
-        }
-
-        public Builder log(Log log) {
-            this.log = log;
-            return this;
-        }
-
-        public SieveMailStorer build() throws MessagingException {
-            Preconditions.checkNotNull(mailetContext);
-            Preconditions.checkNotNull(usersRepos);
-            Preconditions.checkNotNull(folder);
-            Preconditions.checkNotNull(resourceLocator);
-            Preconditions.checkNotNull(log);
-            Preconditions.checkNotNull(sievePoster);
-            return new SieveMailStorer(mailetContext, usersRepos, sievePoster, folder, resourceLocator, log);
-        }
-    }
-
-    private final MailetContext mailetContext;
-    private final UsersRepository usersRepos;
-    private final SievePoster sievePoster;
-    private final String folder;
-    private final ResourceLocator resourceLocator;
-    private final SieveFactory factory;
-    private final ActionDispatcher actionDispatcher;
-    private final Log log;
-
-    public SieveMailStorer(MailetContext mailetContext, UsersRepository usersRepos, SievePoster sievePoster, String folder,
-                           ResourceLocator resourceLocator, Log log) throws MessagingException {
-        this.mailetContext = mailetContext;
-        this.usersRepos = usersRepos;
-        this.sievePoster = sievePoster;
-        this.folder = folder;
-        this.resourceLocator = resourceLocator;
-        try {
-            final ConfigurationManager configurationManager = new ConfigurationManager();
-            configurationManager.setLog(log);
-            factory = configurationManager.build();
-        } catch (SieveConfigurationException e) {
-            throw new MessagingException("Failed to load standard Sieve configuration.", e);
-        }
-        this.actionDispatcher = new ActionDispatcher();
-        this.log = log;
-    }
-
-    public void storeMail(MailAddress sender, MailAddress recipient, Mail mail) throws MessagingException {
-        Preconditions.checkNotNull(recipient, "Recipient for mail to be spooled cannot be null.");
-        Preconditions.checkNotNull(mail.getMessage(), "Mail message to be spooled cannot be null.");
-
-        sieveMessage(recipient, mail, log);
-        // If no exception was thrown the message was successfully stored in the mailbox
-        log.info("Local delivered mail " + mail.getName() + " sucessfully from " + DeliveryUtils.prettyPrint(sender) + " to " + DeliveryUtils.prettyPrint(recipient)
-            + " in folder " + this.folder);
-    }
-
-    protected void sieveMessage(MailAddress recipient, Mail aMail, Log log) throws MessagingException {
-        String username = DeliveryUtils.getUsername(recipient, usersRepos, log);
-        try {
-            final ResourceLocator.UserSieveInformation userSieveInformation = resourceLocator.get(getScriptUri(recipient, log));
-            sieveMessageEvaluate(recipient, aMail, userSieveInformation, log);
-        } 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
-            log.error("Cannot evaluate Sieve script. Storing mail in user INBOX.", ex);
-            storeMessageInbox(username, aMail.getMessage());
-        }
-    }
-
-    private void sieveMessageEvaluate(MailAddress recipient, Mail aMail, ResourceLocator.UserSieveInformation userSieveInformation, Log log) throws MessagingException, IOException {
-        try {
-            SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
-                mailetContext, actionDispatcher, sievePoster, userSieveInformation.getScriptActivationDate(),
-                userSieveInformation.getScriptInterpretationDate(), recipient);
-            aMailAdapter.setLog(log);
-            // This logging operation is potentially costly
-            log.debug("Evaluating " + aMailAdapter.toString() + "against \"" + getScriptUri(recipient, log) + "\"");
-            factory.evaluate(aMailAdapter, factory.parse(userSieveInformation.getScriptContent()));
-        } catch (SieveException ex) {
-            handleFailure(recipient, aMail, ex, log);
-        }
-        catch (ParseException ex) {
-            handleFailure(recipient, aMail, ex, log);
-        }
-        catch (TokenMgrError ex) {
-            handleFailure(recipient, aMail, new SieveException(ex), log);
-        }
-    }
-
-    protected String getScriptUri(MailAddress m, Log log) {
-        return "//" + DeliveryUtils.getUsername(m, usersRepos, log) + "/sieve";
-    }
-
-    protected void handleFailure(MailAddress recipient, Mail aMail, Exception ex, Log log) throws MessagingException, IOException {
-        String user = DeliveryUtils.getUsername(recipient, usersRepos, log);
-        storeMessageInbox(user, SieveFailureMessageComposer.composeMessage(aMail, ex, user));
-    }
-
-    protected void storeMessageInbox(String username, MimeMessage message) throws MessagingException {
-        sievePoster.post("mailbox://" + username + "/", message);
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SievePoster.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SievePoster.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SievePoster.java
deleted file mode 100644
index ce6ba76..0000000
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SievePoster.java
+++ /dev/null
@@ -1,106 +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.delivery;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
-import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.model.MailboxConstants;
-import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.transport.mailets.jsieve.Poster;
-import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.api.UsersRepositoryException;
-import org.apache.mailet.MailetContext;
-
-import com.google.common.base.Strings;
-
-public class SievePoster implements Poster {
-
-    private final MailboxAppender mailboxAppender;
-    private final String folder;
-    private final UsersRepository usersRepos;
-    private final MailetContext mailetContext;
-
-    public SievePoster(MailboxAppender mailboxAppender, String folder, UsersRepository usersRepos, MailetContext mailetContext) {
-        this.mailboxAppender = mailboxAppender;
-        this.folder = folder;
-        this.usersRepos = usersRepos;
-        this.mailetContext = mailetContext;
-    }
-
-    @Override
-    public void post(String url, MimeMessage mail) throws MessagingException {
-        final int endOfScheme = url.indexOf(':');
-        if (endOfScheme < 0) {
-            throw new MessagingException("Malformed URI");
-        } else {
-            final String scheme = url.substring(0, endOfScheme);
-            if (scheme.equals("mailbox")) {
-                handleMailboxProtocol(url, mail, endOfScheme);
-            } else {
-                throw new MessagingException("Unsupported protocol");
-            }
-        }
-    }
-
-    private void handleMailboxProtocol(String url, MimeMessage mail, int endOfScheme) throws MessagingException {
-        int startOfUser = endOfScheme + 3;
-        int endOfUser = url.indexOf('@', startOfUser);
-        int startOfHost = endOfUser + 1;
-        int endOfHost = url.indexOf('/', startOfHost);
-        if (endOfUser < 0) {
-            // TODO: When user missing, append to a default location
-            throw new MessagingException("Shared mailbox is not supported");
-        } else {
-            String host = url.substring(startOfHost, endOfHost);
-            String user = parseUser(url, startOfUser, endOfUser, host);
-            String urlPath = parseUrlPath(url, endOfHost);
-
-            mailboxAppender.appendAndUseSlashAsSeparator(mail, user, urlPath, folder);
-        }
-    }
-
-    private String parseUrlPath(String url, int endOfHost) {
-        String urlPath;
-        int length = url.length();
-        if (endOfHost + 1 == length) {
-            urlPath = this.folder;
-        } else {
-            urlPath = url.substring(endOfHost, length);
-        }
-        return urlPath;
-    }
-
-    private String parseUser(String url, int startOfUser, int endOfUser, String host) throws MessagingException {
-        // lowerCase the user - see
-        // https://issues.apache.org/jira/browse/JAMES-1369
-        String user = url.substring(startOfUser, endOfUser).toLowerCase();
-        // Check if we should use the full email address as username
-        try {
-            if (usersRepos.supportVirtualHosting()) {
-                return user + "@" + host;
-            }
-            return user;
-        } catch (UsersRepositoryException e) {
-            throw new MessagingException("Unable to accessUsersRepository", e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveFailureMessageComposer.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveFailureMessageComposer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveFailureMessageComposer.java
new file mode 100644
index 0000000..ba22dfe
--- /dev/null
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveFailureMessageComposer.java
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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.delivery;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.mailet.Mail;
+
+public class SieveFailureMessageComposer {
+
+    public static MimeMessage composeMessage(Mail aMail, Exception ex, String user) throws MessagingException {
+        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();
+        return message;
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveMailStorer.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveMailStorer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveMailStorer.java
new file mode 100644
index 0000000..f4c04f2
--- /dev/null
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SieveMailStorer.java
@@ -0,0 +1,186 @@
+/****************************************************************
+ * 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.delivery;
+
+import java.io.IOException;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.logging.Log;
+import org.apache.james.transport.mailets.delivery.DeliveryUtils;
+import org.apache.james.transport.mailets.delivery.MailStorer;
+import org.apache.james.transport.mailets.jsieve.ActionDispatcher;
+import org.apache.james.transport.mailets.jsieve.ResourceLocator;
+import org.apache.james.transport.mailets.jsieve.SieveMailAdapter;
+import org.apache.james.user.api.UsersRepository;
+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.MailetContext;
+
+import com.google.common.base.Preconditions;
+
+public class SieveMailStorer implements MailStorer {
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+        private MailetContext mailetContext;
+        private UsersRepository usersRepos;
+        private SievePoster sievePoster;
+        private String folder;
+        private ResourceLocator resourceLocator;
+        private Log log;
+
+        public Builder folder(String folder) {
+            this.folder = folder;
+            return this;
+        }
+
+        public Builder usersRepository(UsersRepository usersRepository) {
+            this.usersRepos = usersRepository;
+            return this;
+        }
+
+        public Builder sievePoster(SievePoster sievePoster) {
+            this.sievePoster = sievePoster;
+            return this;
+        }
+
+        public Builder mailetContext(MailetContext mailetContext) {
+            this.mailetContext = mailetContext;
+            return this;
+        }
+
+        public Builder resourceLocator(ResourceLocator resourceLocator) {
+            this.resourceLocator = resourceLocator;
+            return this;
+        }
+
+        public Builder log(Log log) {
+            this.log = log;
+            return this;
+        }
+
+        public SieveMailStorer build() throws MessagingException {
+            Preconditions.checkNotNull(mailetContext);
+            Preconditions.checkNotNull(usersRepos);
+            Preconditions.checkNotNull(folder);
+            Preconditions.checkNotNull(resourceLocator);
+            Preconditions.checkNotNull(log);
+            Preconditions.checkNotNull(sievePoster);
+            return new SieveMailStorer(mailetContext, usersRepos, sievePoster, folder, resourceLocator, log);
+        }
+    }
+
+    private final MailetContext mailetContext;
+    private final UsersRepository usersRepos;
+    private final SievePoster sievePoster;
+    private final String folder;
+    private final ResourceLocator resourceLocator;
+    private final SieveFactory factory;
+    private final ActionDispatcher actionDispatcher;
+    private final Log log;
+
+    public SieveMailStorer(MailetContext mailetContext, UsersRepository usersRepos, SievePoster sievePoster, String folder,
+                           ResourceLocator resourceLocator, Log log) throws MessagingException {
+        this.mailetContext = mailetContext;
+        this.usersRepos = usersRepos;
+        this.sievePoster = sievePoster;
+        this.folder = folder;
+        this.resourceLocator = resourceLocator;
+        try {
+            final ConfigurationManager configurationManager = new ConfigurationManager();
+            configurationManager.setLog(log);
+            factory = configurationManager.build();
+        } catch (SieveConfigurationException e) {
+            throw new MessagingException("Failed to load standard Sieve configuration.", e);
+        }
+        this.actionDispatcher = new ActionDispatcher();
+        this.log = log;
+    }
+
+    public void storeMail(MailAddress sender, MailAddress recipient, Mail mail) throws MessagingException {
+        Preconditions.checkNotNull(recipient, "Recipient for mail to be spooled cannot be null.");
+        Preconditions.checkNotNull(mail.getMessage(), "Mail message to be spooled cannot be null.");
+
+        sieveMessage(recipient, mail, log);
+        // If no exception was thrown the message was successfully stored in the mailbox
+        log.info("Local delivered mail " + mail.getName() + " sucessfully from " + DeliveryUtils.prettyPrint(sender) + " to " + DeliveryUtils.prettyPrint(recipient)
+            + " in folder " + this.folder);
+    }
+
+    protected void sieveMessage(MailAddress recipient, Mail aMail, Log log) throws MessagingException {
+        String username = DeliveryUtils.getUsername(recipient, usersRepos, log);
+        try {
+            final ResourceLocator.UserSieveInformation userSieveInformation = resourceLocator.get(getScriptUri(recipient, log));
+            sieveMessageEvaluate(recipient, aMail, userSieveInformation, log);
+        } 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
+            log.error("Cannot evaluate Sieve script. Storing mail in user INBOX.", ex);
+            storeMessageInbox(username, aMail.getMessage());
+        }
+    }
+
+    private void sieveMessageEvaluate(MailAddress recipient, Mail aMail, ResourceLocator.UserSieveInformation userSieveInformation, Log log) throws MessagingException, IOException {
+        try {
+            SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
+                mailetContext, actionDispatcher, sievePoster, userSieveInformation.getScriptActivationDate(),
+                userSieveInformation.getScriptInterpretationDate(), recipient);
+            aMailAdapter.setLog(log);
+            // This logging operation is potentially costly
+            log.debug("Evaluating " + aMailAdapter.toString() + "against \"" + getScriptUri(recipient, log) + "\"");
+            factory.evaluate(aMailAdapter, factory.parse(userSieveInformation.getScriptContent()));
+        } catch (SieveException ex) {
+            handleFailure(recipient, aMail, ex, log);
+        }
+        catch (ParseException ex) {
+            handleFailure(recipient, aMail, ex, log);
+        }
+        catch (TokenMgrError ex) {
+            handleFailure(recipient, aMail, new SieveException(ex), log);
+        }
+    }
+
+    protected String getScriptUri(MailAddress m, Log log) {
+        return "//" + DeliveryUtils.getUsername(m, usersRepos, log) + "/sieve";
+    }
+
+    protected void handleFailure(MailAddress recipient, Mail aMail, Exception ex, Log log) throws MessagingException, IOException {
+        String user = DeliveryUtils.getUsername(recipient, usersRepos, log);
+        storeMessageInbox(user, SieveFailureMessageComposer.composeMessage(aMail, ex, user));
+    }
+
+    protected void storeMessageInbox(String username, MimeMessage message) throws MessagingException {
+        sievePoster.post("mailbox://" + username + "/", message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SievePoster.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SievePoster.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SievePoster.java
new file mode 100644
index 0000000..f530ad3
--- /dev/null
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/delivery/SievePoster.java
@@ -0,0 +1,108 @@
+/****************************************************************
+ * 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.delivery;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.model.MailboxConstants;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.transport.mailets.delivery.DeliveryUtils;
+import org.apache.james.transport.mailets.delivery.MailboxAppender;
+import org.apache.james.transport.mailets.jsieve.Poster;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.mailet.MailetContext;
+
+import com.google.common.base.Strings;
+
+public class SievePoster implements Poster {
+
+    private final MailboxAppender mailboxAppender;
+    private final String folder;
+    private final UsersRepository usersRepos;
+    private final MailetContext mailetContext;
+
+    public SievePoster(MailboxAppender mailboxAppender, String folder, UsersRepository usersRepos, MailetContext mailetContext) {
+        this.mailboxAppender = mailboxAppender;
+        this.folder = folder;
+        this.usersRepos = usersRepos;
+        this.mailetContext = mailetContext;
+    }
+
+    @Override
+    public void post(String url, MimeMessage mail) throws MessagingException {
+        final int endOfScheme = url.indexOf(':');
+        if (endOfScheme < 0) {
+            throw new MessagingException("Malformed URI");
+        } else {
+            final String scheme = url.substring(0, endOfScheme);
+            if (scheme.equals("mailbox")) {
+                handleMailboxProtocol(url, mail, endOfScheme);
+            } else {
+                throw new MessagingException("Unsupported protocol");
+            }
+        }
+    }
+
+    private void handleMailboxProtocol(String url, MimeMessage mail, int endOfScheme) throws MessagingException {
+        int startOfUser = endOfScheme + 3;
+        int endOfUser = url.indexOf('@', startOfUser);
+        int startOfHost = endOfUser + 1;
+        int endOfHost = url.indexOf('/', startOfHost);
+        if (endOfUser < 0) {
+            // TODO: When user missing, append to a default location
+            throw new MessagingException("Shared mailbox is not supported");
+        } else {
+            String host = url.substring(startOfHost, endOfHost);
+            String user = parseUser(url, startOfUser, endOfUser, host);
+            String urlPath = parseUrlPath(url, endOfHost);
+
+            mailboxAppender.appendAndUseSlashAsSeparator(mail, user, urlPath, folder);
+        }
+    }
+
+    private String parseUrlPath(String url, int endOfHost) {
+        String urlPath;
+        int length = url.length();
+        if (endOfHost + 1 == length) {
+            urlPath = this.folder;
+        } else {
+            urlPath = url.substring(endOfHost, length);
+        }
+        return urlPath;
+    }
+
+    private String parseUser(String url, int startOfUser, int endOfUser, String host) throws MessagingException {
+        // lowerCase the user - see
+        // https://issues.apache.org/jira/browse/JAMES-1369
+        String user = url.substring(startOfUser, endOfUser).toLowerCase();
+        // Check if we should use the full email address as username
+        try {
+            if (usersRepos.supportVirtualHosting()) {
+                return user + "@" + host;
+            }
+            return user;
+        } catch (UsersRepositoryException e) {
+            throw new MessagingException("Unable to accessUsersRepository", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/05b9040d/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
----------------------------------------------------------------------
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
index 4158231..8c502fd 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/SieveIntegrationTest.java
@@ -51,6 +51,8 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.sieverepository.api.exception.ScriptNotFoundException;
 import org.apache.james.transport.mailets.jsieve.ResourceLocator;
+import org.apache.james.transport.mailets.jsieve.delivery.SieveMailStorer;
+import org.apache.james.transport.mailets.jsieve.delivery.SievePoster;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailAddress;


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