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