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 bt...@apache.org on 2017/04/03 11:10:01 UTC
[02/15] james-project git commit: JAMES-1980 Improves for
UseHeaderRecipients
JAMES-1980 Improves for UseHeaderRecipients
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/604a9dae
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/604a9dae
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/604a9dae
Branch: refs/heads/master
Commit: 604a9dae7c12bb9eb55ea7b7093deaa55b95558e
Parents: 398663e
Author: Benoit Tellier <bt...@linagora.com>
Authored: Wed Dec 28 09:31:54 2016 +0700
Committer: benwa <bt...@linagora.com>
Committed: Mon Apr 3 18:09:28 2017 +0700
----------------------------------------------------------------------
.../mailet/base/test/FakeMailContext.java | 5 +
mailet/standard/pom.xml | 5 +
.../transport/mailets/UseHeaderRecipients.java | 131 +++++++++----
.../mailets/UseHeaderRecipientsTest.java | 184 +++++++++++++++++++
4 files changed, 292 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/604a9dae/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java
----------------------------------------------------------------------
diff --git a/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java b/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java
index 4617a94..1b22e44 100644
--- a/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java
+++ b/mailet/base/src/test/java/org/apache/mailet/base/test/FakeMailContext.java
@@ -122,6 +122,11 @@ public class FakeMailContext implements MailetContext {
return this;
}
+ public Builder recipients(MailAddress... recipients) {
+ this.recipients = Optional.<Collection<MailAddress>>of(ImmutableList.copyOf(recipients));
+ return this;
+ }
+
public Builder recipient(MailAddress recipient) {
Preconditions.checkNotNull(recipient);
return recipients(ImmutableList.of(recipient));
http://git-wip-us.apache.org/repos/asf/james-project/blob/604a9dae/mailet/standard/pom.xml
----------------------------------------------------------------------
diff --git a/mailet/standard/pom.xml b/mailet/standard/pom.xml
index 04ba9e5..45048ac 100644
--- a/mailet/standard/pom.xml
+++ b/mailet/standard/pom.xml
@@ -50,6 +50,11 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.apache.james</groupId>
+ <artifactId>apache-mime4j-dom</artifactId>
+ <version>${mime4j.version}</version>
+ </dependency>
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/james-project/blob/604a9dae/mailet/standard/src/main/java/org/apache/james/transport/mailets/UseHeaderRecipients.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/UseHeaderRecipients.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/UseHeaderRecipients.java
index 603a617..b802d5d 100644
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/UseHeaderRecipients.java
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/UseHeaderRecipients.java
@@ -20,16 +20,29 @@
package org.apache.james.transport.mailets;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.AddressException;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeUtility;
+
+import org.apache.james.mime4j.dom.address.Address;
+import org.apache.james.mime4j.dom.address.AddressList;
+import org.apache.james.mime4j.dom.address.Group;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.field.address.LenientAddressParser;
+import org.apache.james.mime4j.util.MimeUtil;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.apache.mailet.base.GenericMailet;
-import javax.mail.MessagingException;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-import java.util.Collection;
-import java.util.StringTokenizer;
-import java.util.Vector;
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.base.Throwables;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
/**
* <p>Mailet designed to process the recipients from the mail headers rather
@@ -55,6 +68,17 @@ import java.util.Vector;
*/
public class UseHeaderRecipients extends GenericMailet {
+ public static final Function<Mailbox, MailAddress> TO_MAIL_ADDRESS = new Function<Mailbox, MailAddress>() {
+ @Override
+ public MailAddress apply(Mailbox input) {
+ try {
+ return new MailAddress(input.getAddress());
+ } catch (AddressException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ };
+
/**
* Controls certain log messages
*/
@@ -79,20 +103,10 @@ public class UseHeaderRecipients extends GenericMailet {
public void service(Mail mail) throws MessagingException {
MimeMessage message = mail.getMessage();
- // Utilise features of Set Collections such that they automatically
- // ensure that no two entries are equal using the equality method
- // of the element objects. MailAddress objects test equality based
- // on equivalent but not necessarily visually identical addresses.
- Collection<MailAddress> recipients = mail.getRecipients();
- // Wipe all the exist recipients
- recipients.clear();
- recipients.addAll(getHeaderMailAddresses(message, "Mail-For"));
- if (recipients.isEmpty()) {
- recipients.addAll(getHeaderMailAddresses(message, "To"));
- recipients.addAll(getHeaderMailAddresses(message, "Cc"));
- }
+ mail.setRecipients(headersAddresses(message));
+
if (isDebug) {
- log("All recipients = " + recipients.toString());
+ log("All recipients = " + mail.getRecipients());
log("Reprocessing mail using recipients in message headers");
}
@@ -101,6 +115,18 @@ public class UseHeaderRecipients extends GenericMailet {
mail.setState(Mail.GHOST);
}
+ public Collection<MailAddress> headersAddresses(MimeMessage mimeMessage) throws MessagingException {
+ Collection<MailAddress> mailForHeaderAddresses = getHeaderMailAddresses(mimeMessage, "Mail-For");
+ if (!mailForHeaderAddresses.isEmpty()) {
+ return mailForHeaderAddresses;
+ }
+ return ImmutableList.<MailAddress>builder()
+ .addAll(getHeaderMailAddresses(mimeMessage, "To"))
+ .addAll(getHeaderMailAddresses(mimeMessage, "Cc"))
+ .addAll(getHeaderMailAddresses(mimeMessage, "Bcc"))
+ .build();
+ }
+
/**
* Return a string describing this mailet.
@@ -120,28 +146,67 @@ public class UseHeaderRecipients extends GenericMailet {
* @return the collection of MailAddress objects.
*/
private Collection<MailAddress> getHeaderMailAddresses(MimeMessage message, String name) throws MessagingException {
-
if (isDebug) {
log("Checking " + name + " headers");
}
- Collection<MailAddress> addresses = new Vector<MailAddress>();
String[] headers = message.getHeader(name);
- String addressString;
- InternetAddress iAddress;
+ ImmutableList.Builder<MailAddress> addresses = ImmutableList.builder();
+
if (headers != null) {
for (String header : headers) {
- StringTokenizer st = new StringTokenizer(header, ",", false);
- while (st.hasMoreTokens()) {
- addressString = st.nextToken();
- iAddress = new InternetAddress(addressString);
- if (isDebug) {
- log("Address = " + iAddress.toString());
- }
- addresses.add(new MailAddress(iAddress));
- }
+ addresses.addAll(getMailAddressesFromHeaderLine(header));
}
}
- return addresses;
+ return addresses.build();
+ }
+
+ private ImmutableList<MailAddress> getMailAddressesFromHeaderLine(String header) throws MessagingException {
+ String unfoldedDecodedString = sanitizeHeaderString(header);
+ Iterable<String> headerParts = Splitter.on(",").split(unfoldedDecodedString);
+ return getMailAddressesFromHeadersParts(headerParts);
+ }
+
+ private ImmutableList<MailAddress> getMailAddressesFromHeadersParts(Iterable<String> headerParts) throws AddressException {
+ ImmutableList.Builder<MailAddress> result = ImmutableList.builder();
+ for (String headerPart : headerParts) {
+ if (isDebug) {
+ log("Address = " + headerPart);
+ }
+ result.addAll(readMailAddresses(headerPart));
+ }
+ return result.build();
+ }
+
+ private Collection<MailAddress> readMailAddresses(String headerPart) throws AddressException {
+ AddressList addressList = LenientAddressParser.DEFAULT
+ .parseAddressList(MimeUtil.unfold(headerPart));
+
+ ImmutableList.Builder<Mailbox> mailboxList = ImmutableList.builder();
+
+ for (Address address: addressList) {
+ mailboxList.addAll(convertAddressToMailboxCollection(address));
+ }
+
+ return FluentIterable.from(mailboxList.build())
+ .transform(TO_MAIL_ADDRESS)
+ .toList();
+ }
+
+ private Collection<Mailbox> convertAddressToMailboxCollection(Address address) {
+ if (address instanceof Mailbox) {
+ return ImmutableList.of((Mailbox) address);
+ } else if (address instanceof Group) {
+ return ImmutableList.copyOf(((Group) address).getMailboxes());
+ }
+ return ImmutableList.of();
+ }
+
+ private String sanitizeHeaderString(String header) throws MessagingException {
+ try {
+ return MimeUtility.unfold(MimeUtility.decodeText(header));
+ } catch (UnsupportedEncodingException e) {
+ throw new MessagingException("Can not decode header", e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/604a9dae/mailet/standard/src/test/java/org/apache/james/transport/mailets/UseHeaderRecipientsTest.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/UseHeaderRecipientsTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/UseHeaderRecipientsTest.java
new file mode 100644
index 0000000..95d220a
--- /dev/null
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/UseHeaderRecipientsTest.java
@@ -0,0 +1,184 @@
+/****************************************************************
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.apache.mailet.base.MailAddressFixture;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailContext;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.apache.mailet.base.test.MimeMessageBuilder;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class UseHeaderRecipientsTest {
+
+ public static final String RECIPIENT1 = "abc1@apache1.org";
+ public static final String RECIPIENT2 = "abc2@apache2.org";
+ public static final String RECIPIENT3 = "abc3@apache3.org";
+ private UseHeaderRecipients testee;
+ private FakeMailContext mailetContext;
+ private MailAddress mailAddress1;
+ private MailAddress mailAddress2;
+ private MailAddress mailAddress3;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Before
+ public void setUp() throws Exception {
+ testee = new UseHeaderRecipients();
+ mailetContext = FakeMailContext.defaultContext();
+ testee.init(FakeMailetConfig.builder().mailetContext(mailetContext).build());
+
+ mailAddress1 = new MailAddress(RECIPIENT1);
+ mailAddress2 = new MailAddress(RECIPIENT2);
+ mailAddress3 = new MailAddress(RECIPIENT3);
+ }
+
+ @Test
+ public void serviceShouldSetMimeMessageRecipients() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(MailAddressFixture.ANY_AT_JAMES, MailAddressFixture.ANY_AT_JAMES2)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient(RECIPIENT1, RECIPIENT2)
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getRecipients())
+ .containsOnly(mailAddress1, mailAddress2);
+ }
+
+ @Test
+ public void serviceShouldSetToCcAndBccSpecifiedInTheMimeMessage() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(MailAddressFixture.ANY_AT_JAMES)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient(RECIPIENT1)
+ .addCcRecipient(RECIPIENT2)
+ .addBccRecipient(RECIPIENT3)
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getRecipients())
+ .containsOnly(mailAddress1, mailAddress2, mailAddress3);
+ }
+
+ @Test
+ public void serviceShouldSetEmptyRecipientWhenNoRecipientsInTheMimeMessage() throws Exception {
+
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(MailAddressFixture.ANY_AT_JAMES)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getRecipients())
+ .isEmpty();
+ }
+
+ @Test
+ public void serviceShouldGhostEmail() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(MailAddressFixture.ANY_AT_JAMES)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getState())
+ .isEqualTo(Mail.GHOST);
+ }
+
+ @Test
+ public void serviceShouldResendTheEmail() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(MailAddressFixture.ANY_AT_JAMES)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient(RECIPIENT1)
+ .addCcRecipient(RECIPIENT2)
+ .addBccRecipient(RECIPIENT3)
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(mailetContext.getSentMails())
+ .containsOnly(FakeMailContext.sentMailBuilder()
+ .recipients(mailAddress1, mailAddress2, mailAddress3)
+ .build());
+ }
+
+ @Test
+ public void serviceShouldThrowOnInvalidMailAddress() throws Exception {
+ expectedException.expect(RuntimeException.class);
+
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients(mailAddress1)
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient("invalid")
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+ }
+
+ @Test
+ public void serviceShouldSupportAddressList() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients()
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient(RECIPIENT1, RECIPIENT2)
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getRecipients())
+ .containsOnly(mailAddress1, mailAddress2);
+ }
+
+ @Test
+ public void serviceShouldSupportMailboxes() throws Exception {
+ FakeMail fakeMail = FakeMail.builder()
+ .recipients()
+ .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+ .addToRecipient("APACHE" + "<" + UseHeaderRecipientsTest.RECIPIENT1 + ">")
+ .build())
+ .build();
+
+ testee.service(fakeMail);
+
+ assertThat(fakeMail.getRecipients())
+ .containsOnly(mailAddress1);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org