From ff46bec6ada39357dff642ebf2481e90d20d0e8d Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 8 Mar 2011 15:43:10 -0500 Subject: [PATCH] INT-1804, INT-1825 finished up with support for filtering email messages and flagging messages with arbitrary flags if RECENT flag is not supported (e.g., GMAIL) --- .../mail/AbstractMailReceiver.java | 34 ++++++---- .../integration/mail/ImapMailReceiver.java | 62 ++++++++++++------- .../config/ImapIdleChannelAdapterParser.java | 2 +- .../MailInboundChannelAdapterParser.java | 2 +- .../config/spring-integration-mail-2.0.xsd | 4 +- .../mail/ImapMailReceiverTests.java | 2 - .../mail/ImapMailSearchTermsTests.java | 47 ++++---------- 7 files changed, 79 insertions(+), 74 deletions(-) diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java index f8ecb90503..488dbe6bb0 100755 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java @@ -53,6 +53,8 @@ import org.springframework.util.PatternMatchUtils; */ public abstract class AbstractMailReceiver extends IntegrationObjectSupport implements MailReceiver, DisposableBean{ + public final static String SI_USER_FLAG = "spring-integration-mail-adapter"; + protected final Log logger = LogFactory.getLog(this.getClass()); private final URLName url; @@ -243,25 +245,33 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl List copiedMessages = new LinkedList(); logger.debug("Recieved " + messages.length + " messages"); + + boolean recentFlagSupported = this.getFolder().getPermanentFlags().contains(Flags.Flag.RECENT); + for (int i = 0; i < messages.length; i++) { - System.out.println(this.getFolder()); - System.out.println(this.getFolder().getPermanentFlags()); - if (this.getFolder().getPermanentFlags().contains(Flags.Flag.USER)){ - Flags siFlags = new Flags(); - siFlags.add("spring-integration"); - messages[i].setFlags(siFlags, true); + if (!recentFlagSupported){ + if (this.getFolder().getPermanentFlags().contains(Flags.Flag.USER)){ + logger.debug("USER flags are supported by this mail server. Flagging message with '" + SI_USER_FLAG + "' user flag"); + Flags siFlags = new Flags(); + siFlags.add(SI_USER_FLAG); + messages[i].setFlags(siFlags, true); + } + else { + logger.debug("USER flags are not supported by this mail server. Flagging message with system flag"); + messages[i].setFlag(Flags.Flag.FLAGGED, true); + } } - else { - logger.warn("USER flags are not supported by this mail server. Flagging message with system flag"); - messages[i].setFlag(Flags.Flag.FLAGGED, true); - } - + if (this.selectorExpression != null){ Message message = messages[i]; if ((Boolean)this.selectorExpression.getValue(this.context, message)){ this.setAdditionalFlags(message); copiedMessages.add(new MimeMessage((MimeMessage) message)); - } + } + else { + logger.debug("Fetched email with subject '" + message.getSubject() + "' will be discarded by the matching filter" + + " and will not be flagged as SEEN."); + } } else { this.setAdditionalFlags(messages[i]); diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/ImapMailReceiver.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/ImapMailReceiver.java index 7d60c7cef6..7198b9b268 100755 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/ImapMailReceiver.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/ImapMailReceiver.java @@ -132,45 +132,63 @@ public class ImapMailReceiver extends AbstractMailReceiver { private SearchTerm compileSearchTerms(Flags supportedFlags){ SearchTerm searchTerm = null; + boolean recentFlagSupported = false; if (supportedFlags != null) { - if (supportedFlags.contains(Flags.Flag.RECENT)) { + recentFlagSupported = supportedFlags.contains(Flags.Flag.RECENT); + if (recentFlagSupported) { searchTerm = new FlagTerm(new Flags(Flags.Flag.RECENT), true); } if (supportedFlags.contains(Flags.Flag.ANSWERED)) { - FlagTerm answeredTerm = new FlagTerm(new Flags(Flags.Flag.ANSWERED), false); + NotTerm notAnswered = new NotTerm(new FlagTerm(new Flags(Flags.Flag.ANSWERED), true)); if (searchTerm == null) { - searchTerm = answeredTerm; + searchTerm = notAnswered; } else { - searchTerm = new AndTerm(searchTerm, answeredTerm); + searchTerm = new AndTerm(searchTerm, notAnswered); } } if (supportedFlags.contains(Flags.Flag.DELETED)) { - FlagTerm deletedTerm = new FlagTerm(new Flags(Flags.Flag.DELETED), false); + NotTerm notDeleted = new NotTerm(new FlagTerm(new Flags(Flags.Flag.DELETED), true)); if (searchTerm == null) { - searchTerm = deletedTerm; + searchTerm = notDeleted; } else { - searchTerm = new AndTerm(searchTerm, deletedTerm); + searchTerm = new AndTerm(searchTerm, notDeleted); + } + } + if (supportedFlags.contains(Flags.Flag.SEEN)) { + NotTerm notSeen = new NotTerm(new FlagTerm(new Flags(Flags.Flag.SEEN), true)); + if (searchTerm == null) { + searchTerm = notSeen; + } + else { + searchTerm = new AndTerm(searchTerm, notSeen); } } } - NotTerm notDeleted = new NotTerm( new FlagTerm(new Flags(Flags.Flag.DELETED), true) ); - NotTerm notSeen = new NotTerm( new FlagTerm(new Flags(Flags.Flag.SEEN), true) ); - if (searchTerm == null){ - searchTerm = notDeleted; - } - - if (this.getFolder().getPermanentFlags().contains(Flags.Flag.USER)){ - Flags siFlags = new Flags(); - siFlags.add("spring-integration"); - searchTerm = new AndTerm(new SearchTerm[]{searchTerm, notSeen, new FlagTerm(siFlags, false)}); + + if (!recentFlagSupported){ + NotTerm notFlagged = null; + if (this.getFolder().getPermanentFlags().contains(Flags.Flag.USER)){ + logger.debug("This email server does not support RECENT flag but it does support " + + "USER flags which will be used to prevent duplicates during email fetch"); + Flags siFlags = new Flags(); + siFlags.add(SI_USER_FLAG); + notFlagged = new NotTerm(new FlagTerm(siFlags, true)); + } + else { + logger.debug("This email server does not support RECENT or USER flags. " + + "System flag 'Flag.FLAGGED' will be used to prevent duplicates during email fetch"); + notFlagged = new NotTerm(new FlagTerm(new Flags(Flags.Flag.FLAGGED), true)); + } + if (searchTerm == null){ + searchTerm = notFlagged; + } + else { + searchTerm = new AndTerm(searchTerm, notFlagged); + } } - else { - searchTerm = new AndTerm(new SearchTerm[]{searchTerm, notSeen, new FlagTerm(new Flags(Flags.Flag.FLAGGED), false)}); - } - - + return searchTerm; } diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java index 63cc81d0aa..b2088c0afa 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java @@ -88,7 +88,7 @@ public class ImapIdleChannelAdapterParser extends AbstractSingleBeanDefinitionPa receiverBuilder.addPropertyValue("shouldMarkMessagesAsRead", markAsRead); } - String selectorExpression = element.getAttribute("message-matcher-expression"); + String selectorExpression = element.getAttribute("mail-filter-expression"); RootBeanDefinition expressionDef = null; if (StringUtils.hasText(selectorExpression)){ diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java index 861c9fb32c..9e720beae3 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java @@ -85,7 +85,7 @@ public class MailInboundChannelAdapterParser extends AbstractPollingInboundChann receiverBuilder.addPropertyValue("shouldMarkMessagesAsRead", markAsRead); } - String selectorExpression = element.getAttribute("message-matcher-expression"); + String selectorExpression = element.getAttribute("mail-filter-expression"); RootBeanDefinition expressionDef = null; if (StringUtils.hasText(selectorExpression)){ diff --git a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd index e1d3fc2bbc..f5c078c6fa 100644 --- a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd +++ b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd @@ -157,10 +157,10 @@ ]]> - + diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java index d4ebd678a6..518f803dac 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java @@ -173,8 +173,6 @@ public class ImapMailReceiverTests { final Message[] messages = new Message[]{msg1, msg2}; doAnswer(new Answer() { public Object answer(InvocationOnMock invocation) throws Throwable { - DirectFieldAccessor accessor = new DirectFieldAccessor(invocation.getMock()); - int folderOpenMode = (Integer) accessor.getPropertyValue("folderOpenMode"); return null; } }).when(receiver).openFolder(); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java index 6635f7c08e..0031219c50 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailSearchTermsTests.java @@ -56,12 +56,11 @@ public class ImapMailSearchTermsTests { compileSearchTerms.setAccessible(true); Flags flags = new Flags(); SearchTerm searchTerms = (SearchTerm) compileSearchTerms.invoke(receiver, flags); - assertTrue(searchTerms instanceof AndTerm); - AndTerm andTerm = (AndTerm) searchTerms; - SearchTerm[] terms = andTerm.getTerms(); - assertEquals(3, terms.length); - NotTerm notTerm = (NotTerm) terms[1]; - assertTrue(((FlagTerm)notTerm.getTerm()).getFlags().contains(Flag.SEEN)); + assertTrue(searchTerms instanceof NotTerm); + NotTerm notTerm = (NotTerm) searchTerms; + Flags siFlags = new Flags(); + siFlags.add(AbstractMailReceiver.SI_USER_FLAG); + notTerm.getTerm().equals(siFlags); } @Test public void validateSearchTermsWhenShouldMarkAsReadWithExistingFlags() throws Exception { @@ -83,9 +82,13 @@ public class ImapMailSearchTermsTests { assertTrue(searchTerms instanceof AndTerm); AndTerm andTerm = (AndTerm) searchTerms; SearchTerm[] terms = andTerm.getTerms(); - assertEquals(3, terms.length); - NotTerm notTerm = (NotTerm) terms[1]; - assertTrue(((FlagTerm)notTerm.getTerm()).getFlags().contains(Flag.SEEN)); + assertEquals(2, terms.length); + NotTerm notTerm = (NotTerm) terms[0]; + assertTrue(((FlagTerm)notTerm.getTerm()).getFlags().contains(Flag.ANSWERED)); + notTerm = (NotTerm) terms[1]; + Flags siFlags = new Flags(); + siFlags.add(AbstractMailReceiver.SI_USER_FLAG); + assertTrue(((FlagTerm)notTerm.getTerm()).getFlags().contains(siFlags)); } @Test @@ -104,30 +107,6 @@ public class ImapMailSearchTermsTests { compileSearchTerms.setAccessible(true); Flags flags = new Flags(); SearchTerm searchTerms = (SearchTerm) compileSearchTerms.invoke(receiver, flags); - assertTrue(searchTerms instanceof AndTerm); - } - @Test - public void validateSearchTermsWhenShouldNotMarkAsReadWithExistingFlags() throws Exception { - ImapMailReceiver receiver = new ImapMailReceiver(); - receiver.setShouldMarkMessagesAsRead(false); - receiver.afterPropertiesSet(); - - Field folderField = AbstractMailReceiver.class.getDeclaredField("folder"); - folderField.setAccessible(true); - Folder folder = mock(Folder.class); - when(folder.getPermanentFlags()).thenReturn(new Flags(Flags.Flag.USER)); - folderField.set(receiver, folder); - - Method compileSearchTerms = ReflectionUtils.findMethod(receiver.getClass(), "compileSearchTerms", Flags.class); - compileSearchTerms.setAccessible(true); - Flags flags = new Flags(); - flags.add(Flag.ANSWERED); - SearchTerm searchTerms = (SearchTerm) compileSearchTerms.invoke(receiver, flags); - assertTrue(searchTerms instanceof AndTerm); - AndTerm andTerm = (AndTerm) searchTerms; - SearchTerm[] andTerms = andTerm.getTerms(); - assertTrue(andTerms.length == 3); - assertTrue(((FlagTerm)andTerms[0]).getFlags().contains(Flag.ANSWERED)); - + assertTrue(searchTerms instanceof NotTerm); } }