same signature to get replyTo and replyToAll addresses in ReplyToParser

This commit is contained in:
Vincent Breitmoser 2016-05-20 11:26:13 +02:00
parent 31f6deb474
commit 43899da77c
5 changed files with 77 additions and 88 deletions

View file

@ -41,7 +41,7 @@ public class ListHeaders {
public static Address[] getListPostAddresses(Message message) {
String[] headerValues = getHeaderValues(message, LIST_POST_HEADER);
if (headerValues.length < 1) {
if (headerValues == null || headerValues.length < 1) {
return new Address[0];
}

View file

@ -136,16 +136,12 @@ public class RecipientPresenter implements PermissionPingCallback {
}
public void initFromReplyToMessage(Message message, boolean isReplyAll) {
Address[] replyToAddresses = replyToParser.getRecipientsToReplyTo(message, account);
addToAddresses(replyToAddresses);
ReplyToAddresses replyToAddresses = isReplyAll ?
replyToParser.getRecipientsToReplyAllTo(message, account) :
replyToParser.getRecipientsToReplyTo(message, account);
if (isReplyAll) {
ReplyToAddresses replyToAllAddresses =
replyToParser.getRecipientsToReplyAllTo(message, replyToAddresses, account);
addToAddresses(replyToAllAddresses.to);
addCcAddresses(replyToAllAddresses.cc);
}
addToAddresses(replyToAddresses.to);
addCcAddresses(replyToAddresses.cc);
boolean shouldSendAsPgpInline = composePgpInlineDecider.shouldReplyInline(message);
if (shouldSendAsPgpInline) {

View file

@ -17,31 +17,34 @@ import com.fsck.k9.mail.internet.ListHeaders;
public class ReplyToParser {
public Address[] getRecipientsToReplyTo(Message message, Account account) {
Address[] result = message.getReplyTo();
public ReplyToAddresses getRecipientsToReplyTo(Message message, Account account) {
Address[] candidateAddress;
boolean hasNoReplyToAddresses = (result.length == 0);
if (hasNoReplyToAddresses) {
result = ListHeaders.getListPostAddresses(message);
Address[] replyToAddresses = message.getReplyTo();
Address[] listPostAddresses = ListHeaders.getListPostAddresses(message);
Address[] fromAddresses = message.getFrom();
if (replyToAddresses.length > 0) {
candidateAddress = replyToAddresses;
} else if (listPostAddresses.length > 0) {
candidateAddress = listPostAddresses;
} else {
candidateAddress = fromAddresses;
}
boolean hasNoListPostAddresses = result.length == 0;
if (hasNoListPostAddresses) {
result = message.getFrom();
}
boolean replyToAddressIsUserIdentity = account.isAnIdentity(result);
boolean replyToAddressIsUserIdentity = account.isAnIdentity(candidateAddress);
if (replyToAddressIsUserIdentity) {
result = message.getRecipients(RecipientType.TO);
candidateAddress = message.getRecipients(RecipientType.TO);
}
return result;
return new ReplyToAddresses(candidateAddress);
}
public ReplyToAddresses getRecipientsToReplyAllTo(
Message message, Address[] replyToAddresses, Account account) {
HashSet<Address> alreadyAddedAddresses = new HashSet<>(Arrays.asList(replyToAddresses));
ArrayList<Address> toAddresses = new ArrayList<>();
public ReplyToAddresses getRecipientsToReplyAllTo(Message message, Account account) {
List<Address> replyToAddresses = Arrays.asList(getRecipientsToReplyTo(message, account).to);
HashSet<Address> alreadyAddedAddresses = new HashSet<>(replyToAddresses);
ArrayList<Address> toAddresses = new ArrayList<>(replyToAddresses);
ArrayList<Address> ccAddresses = new ArrayList<>();
for (Address address : message.getFrom()) {
@ -77,6 +80,12 @@ public class ReplyToParser {
to = toAddresses.toArray(new Address[toAddresses.size()]);
cc = ccAddresses.toArray(new Address[ccAddresses.size()]);
}
@VisibleForTesting
public ReplyToAddresses(Address[] toAddresses) {
to = toAddresses;
cc = new Address[0];
}
}
}

View file

@ -33,7 +33,7 @@ import static org.mockito.Mockito.when;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = "src/main/AndroidManifest.xml", sdk = 21)
public class RecipientPresenterTest {
public static final Address[] TO_ADDRESSES = Address.parse("to@example.org");
public static final ReplyToAddresses TO_ADDRESSES = new ReplyToAddresses(Address.parse("to@example.org"));
public static final List<Address> ALL_TO_ADDRESSES = Arrays.asList(Address.parse("allTo@example.org"));
public static final List<Address> ALL_CC_ADDRESSES = Arrays.asList(Address.parse("allCc@example.org"));
@ -80,18 +80,17 @@ public class RecipientPresenterTest {
when(replyToParser.getRecipientsToReplyTo(message, account)).thenReturn(TO_ADDRESSES);
ReplyToAddresses replyToAddresses = new ReplyToAddresses(ALL_TO_ADDRESSES, ALL_CC_ADDRESSES);
when(replyToParser.getRecipientsToReplyAllTo(message, TO_ADDRESSES, account)).thenReturn(replyToAddresses);
when(replyToParser.getRecipientsToReplyAllTo(message, account)).thenReturn(replyToAddresses);
recipientPresenter.initFromReplyToMessage(message, true);
verify(replyToParser).getRecipientsToReplyTo(message, account);
verify(replyToParser).getRecipientsToReplyAllTo(message, TO_ADDRESSES, account);
verify(replyToParser).getRecipientsToReplyAllTo(message, account);
verifyNoMoreInteractions(replyToParser);
verify(composePgpInlineDecider).shouldReplyInline(message);
verifyNoMoreInteractions(composePgpInlineDecider);
verify(recipientMvpView, VerificationModeFactory.times(2)).addRecipients(eq(RecipientType.TO), any(Recipient.class));
verify(recipientMvpView).addRecipients(eq(RecipientType.TO), any(Recipient.class));
verify(recipientMvpView).addRecipients(eq(RecipientType.CC), any(Recipient.class));
}
}

View file

@ -13,16 +13,16 @@ import com.fsck.k9.mail.internet.ListHeaders;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.internal.verification.VerificationModeFactory;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@ -57,10 +57,11 @@ public class ReplyToParserTest {
when(message.getHeader(ListHeaders.LIST_POST_HEADER)).thenReturn(LIST_POST_HEADER_VALUES);
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
Address[] result = replyToParser.getRecipientsToReplyTo(message, account);
ReplyToAddresses result = replyToParser.getRecipientsToReplyTo(message, account);
assertArrayEquals(REPLY_TO_ADDRESSES, result);
verify(account).isAnIdentity(result);
assertArrayEquals(REPLY_TO_ADDRESSES, result.to);
assertArrayEquals(EMPTY_ADDRESSES, result.cc);
verify(account).isAnIdentity(result.to);
}
@Test
@ -71,9 +72,10 @@ public class ReplyToParserTest {
when(message.getRecipients(RecipientType.TO)).thenReturn(TO_ADDRESSES);
when(account.isAnIdentity(any(Address[].class))).thenReturn(true);
Address[] result = replyToParser.getRecipientsToReplyTo(message, account);
ReplyToAddresses result = replyToParser.getRecipientsToReplyTo(message, account);
assertArrayEquals(TO_ADDRESSES, result);
assertArrayEquals(TO_ADDRESSES, result.to);
assertArrayEquals(EMPTY_ADDRESSES, result.cc);
}
@Test
@ -82,10 +84,11 @@ public class ReplyToParserTest {
when(message.getHeader(ListHeaders.LIST_POST_HEADER)).thenReturn(LIST_POST_HEADER_VALUES);
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
Address[] result = replyToParser.getRecipientsToReplyTo(message, account);
ReplyToAddresses result = replyToParser.getRecipientsToReplyTo(message, account);
assertArrayEquals(LIST_POST_ADDRESSES, result);
verify(account).isAnIdentity(result);
assertArrayEquals(LIST_POST_ADDRESSES, result.to);
assertArrayEquals(EMPTY_ADDRESSES, result.cc);
verify(account).isAnIdentity(result.to);
}
@Test
@ -94,59 +97,33 @@ public class ReplyToParserTest {
when(message.getHeader(ListHeaders.LIST_POST_HEADER)).thenReturn(new String[0]);
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
Address[] result = replyToParser.getRecipientsToReplyTo(message, account);
ReplyToAddresses result = replyToParser.getRecipientsToReplyTo(message, account);
assertArrayEquals(FROM_ADDRESSES, result);
verify(account).isAnIdentity(result);
assertArrayEquals(FROM_ADDRESSES, result.to);
assertArrayEquals(EMPTY_ADDRESSES, result.cc);
verify(account).isAnIdentity(result.to);
}
@Test
public void getRecipientsToReplyAllTo_should_returnFromAndToAndCcRecipients() throws Exception {
when(message.getReplyTo()).thenReturn(EMPTY_ADDRESSES);
when(message.getHeader(ListHeaders.LIST_POST_HEADER)).thenReturn(new String[0]);
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
when(message.getRecipients(RecipientType.TO)).thenReturn(TO_ADDRESSES);
when(message.getRecipients(RecipientType.CC)).thenReturn(CC_ADDRESSES);
ReplyToAddresses recipientsToReplyAllTo =
replyToParser.getRecipientsToReplyAllTo(message, REPLY_TO_ADDRESSES, account);
ReplyToAddresses recipientsToReplyAllTo = replyToParser.getRecipientsToReplyAllTo(message, account);
assertArrayEquals(arrayConcatenate(FROM_ADDRESSES, TO_ADDRESSES, Address.class), recipientsToReplyAllTo.to);
assertArrayEquals(CC_ADDRESSES, recipientsToReplyAllTo.cc);
}
@Test
public void getRecipientsToReplyAllTo_should_returnToAndCcRecipients() throws Exception {
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
when(message.getRecipients(RecipientType.TO)).thenReturn(TO_ADDRESSES);
when(message.getRecipients(RecipientType.CC)).thenReturn(CC_ADDRESSES);
ReplyToAddresses recipientsToReplyAllTo =
replyToParser.getRecipientsToReplyAllTo(message, REPLY_TO_ADDRESSES, account);
assertArrayEquals(arrayConcatenate(FROM_ADDRESSES, TO_ADDRESSES, Address.class), recipientsToReplyAllTo.to);
assertArrayEquals(CC_ADDRESSES, recipientsToReplyAllTo.cc);
}
@Test
public void getRecipientsToReplyAllTo_should_excludeIdentityAddressesInFrom() throws Exception {
when(message.getFrom()).thenReturn(FROM_ADDRESSES);
when(message.getRecipients(RecipientType.TO)).thenReturn(EMPTY_ADDRESSES);
when(message.getRecipients(RecipientType.CC)).thenReturn(CC_ADDRESSES);
Address excludedFromAddress = FROM_ADDRESSES[0];
when(account.isAnIdentity(eq(excludedFromAddress))).thenReturn(true);
ReplyToAddresses recipientsToReplyAllTo =
replyToParser.getRecipientsToReplyAllTo(message, REPLY_TO_ADDRESSES, account);
assertArrayEquals(arrayExcept(FROM_ADDRESSES, excludedFromAddress), recipientsToReplyAllTo.to);
assertArrayEquals(CC_ADDRESSES, recipientsToReplyAllTo.cc);
int addressesToCheck = FROM_ADDRESSES.length + CC_ADDRESSES.length;
verify(account, VerificationModeFactory.times(addressesToCheck)).isAnIdentity(any(Address.class));
verifyNoMoreInteractions(account);
}
@Test
public void getRecipientsToReplyAllTo_should_excludeIdentityAddressesInToAndCc() throws Exception {
public void getRecipientsToReplyAllTo_should_excludeIdentityAddresses() throws Exception {
when(message.getReplyTo()).thenReturn(EMPTY_ADDRESSES);
when(message.getHeader(ListHeaders.LIST_POST_HEADER)).thenReturn(new String[0]);
when(message.getFrom()).thenReturn(EMPTY_ADDRESSES);
when(message.getRecipients(RecipientType.TO)).thenReturn(TO_ADDRESSES);
when(message.getRecipients(RecipientType.CC)).thenReturn(CC_ADDRESSES);
Address excludedCcAddress = CC_ADDRESSES[1];
@ -154,29 +131,37 @@ public class ReplyToParserTest {
when(account.isAnIdentity(eq(excludedToAddress))).thenReturn(true);
when(account.isAnIdentity(eq(excludedCcAddress))).thenReturn(true);
ReplyToAddresses recipientsToReplyAllTo =
replyToParser.getRecipientsToReplyAllTo(message, REPLY_TO_ADDRESSES, account);
ReplyToAddresses recipientsToReplyAllTo = replyToParser.getRecipientsToReplyAllTo(message, account);
assertArrayEquals(arrayExcept(TO_ADDRESSES, excludedToAddress), recipientsToReplyAllTo.to);
assertArrayEquals(arrayExcept(CC_ADDRESSES, excludedCcAddress), recipientsToReplyAllTo.cc);
int addressesToCheck = TO_ADDRESSES.length + CC_ADDRESSES.length;
verify(account, VerificationModeFactory.times(addressesToCheck)).isAnIdentity(any(Address.class));
verifyNoMoreInteractions(account);
}
@Test
public void getRecipientsToReplyAllTo_should_excludeDuplicates() throws Exception {
when(message.getReplyTo()).thenReturn(REPLY_TO_ADDRESSES);
when(message.getFrom()).thenReturn(arrayConcatenate(FROM_ADDRESSES, REPLY_TO_ADDRESSES, Address.class));
when(message.getRecipients(RecipientType.TO)).thenReturn(arrayConcatenate(TO_ADDRESSES, FROM_ADDRESSES, Address.class));
when(message.getRecipients(RecipientType.TO)).thenReturn(arrayConcatenate(FROM_ADDRESSES, TO_ADDRESSES, Address.class));
when(message.getRecipients(RecipientType.CC)).thenReturn(arrayConcatenate(CC_ADDRESSES, TO_ADDRESSES, Address.class));
ReplyToAddresses recipientsToReplyAllTo =
replyToParser.getRecipientsToReplyAllTo(message, REPLY_TO_ADDRESSES, account);
ReplyToAddresses recipientsToReplyAllTo = replyToParser.getRecipientsToReplyAllTo(message, account);
assertArrayEquals(arrayConcatenate(FROM_ADDRESSES, TO_ADDRESSES, Address.class), recipientsToReplyAllTo.to);
assertArrayContainsAll(REPLY_TO_ADDRESSES, recipientsToReplyAllTo.to);
assertArrayContainsAll(FROM_ADDRESSES, recipientsToReplyAllTo.to);
assertArrayContainsAll(TO_ADDRESSES, recipientsToReplyAllTo.to);
int totalExpectedAddresses = REPLY_TO_ADDRESSES.length + FROM_ADDRESSES.length + TO_ADDRESSES.length;
assertEquals(totalExpectedAddresses, recipientsToReplyAllTo.to.length);
assertArrayEquals(CC_ADDRESSES, recipientsToReplyAllTo.cc);
}
public <T> void assertArrayContainsAll(T[] expecteds, T[] actual) {
for (T expected : expecteds) {
assertTrue("Element must be in array (" + expected + ")", Utility.arrayContains(actual, expected));
}
}
public <T> T[] arrayConcatenate(T[] first, T[] second, Class<T> cls) {
// noinspection unchecked
T[] result = (T[]) Array.newInstance(cls, first.length + second.length);