INT-1929 Custom Mail SearchTerms
Add support for overriding default SeatchTerms in ImapMailReceiver INT-1929 PR comments Polish Docs
This commit is contained in:
committed by
Gary Russell
parent
14f78509ea
commit
7207bb1840
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -41,7 +41,7 @@ import com.sun.mail.imap.IMAPMessage;
|
||||
* the option of blocking until new messages are available prior to calling
|
||||
* {@link #receive()}. That option is only available if the server supports
|
||||
* the {@link IMAPFolder#idle() idle} command.
|
||||
*
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -50,6 +50,8 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
|
||||
private volatile boolean shouldMarkMessagesAsRead = true;
|
||||
|
||||
private volatile SearchTermStrategy searchTermStrategy = new DefaultSearchTermStrategy();
|
||||
|
||||
private final MessageCountListener messageCountListener = new SimpleMessageCountListener();
|
||||
|
||||
public ImapMailReceiver() {
|
||||
@@ -76,6 +78,17 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
return shouldMarkMessagesAsRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a way to set custom {@link SearchTermStrategy} to compile a {@link SearchTerm}
|
||||
* to be applied when retrieving mail
|
||||
*
|
||||
* @param searchTermStrategy
|
||||
*/
|
||||
public void setSearchTermStrategy(SearchTermStrategy searchTermStrategy) {
|
||||
Assert.notNull(searchTermStrategy, "'searchTermStrategy' must not be null");
|
||||
this.searchTermStrategy = searchTermStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if messages should be marked as read.
|
||||
*/
|
||||
@@ -131,66 +144,10 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
}
|
||||
|
||||
private SearchTerm compileSearchTerms(Flags supportedFlags) {
|
||||
SearchTerm searchTerm = null;
|
||||
boolean recentFlagSupported = false;
|
||||
if (supportedFlags != null) {
|
||||
recentFlagSupported = supportedFlags.contains(Flags.Flag.RECENT);
|
||||
if (recentFlagSupported) {
|
||||
searchTerm = new FlagTerm(new Flags(Flags.Flag.RECENT), true);
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.ANSWERED)) {
|
||||
NotTerm notAnswered = new NotTerm(new FlagTerm(new Flags(Flags.Flag.ANSWERED), true));
|
||||
if (searchTerm == null) {
|
||||
searchTerm = notAnswered;
|
||||
}
|
||||
else {
|
||||
searchTerm = new AndTerm(searchTerm, notAnswered);
|
||||
}
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.DELETED)) {
|
||||
NotTerm notDeleted = new NotTerm(new FlagTerm(new Flags(Flags.Flag.DELETED), true));
|
||||
if (searchTerm == null) {
|
||||
searchTerm = notDeleted;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return searchTerm;
|
||||
return this.searchTermStrategy.generateSearchTerm(supportedFlags, this.getFolder());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAdditionalFlags(Message message) throws MessagingException {
|
||||
super.setAdditionalFlags(message);
|
||||
if (this.shouldMarkMessagesAsRead) {
|
||||
@@ -204,6 +161,7 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
*/
|
||||
private static class SimpleMessageCountListener extends MessageCountAdapter {
|
||||
|
||||
@Override
|
||||
public void messagesAdded(MessageCountEvent event) {
|
||||
Message[] messages = event.getMessages();
|
||||
for (Message message : messages) {
|
||||
@@ -218,4 +176,70 @@ public class ImapMailReceiver extends AbstractMailReceiver {
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultSearchTermStrategy implements SearchTermStrategy {
|
||||
|
||||
public SearchTerm generateSearchTerm(Flags supportedFlags, Folder folder) {
|
||||
SearchTerm searchTerm = null;
|
||||
boolean recentFlagSupported = false;
|
||||
if (supportedFlags != null) {
|
||||
recentFlagSupported = supportedFlags.contains(Flags.Flag.RECENT);
|
||||
if (recentFlagSupported) {
|
||||
searchTerm = new FlagTerm(new Flags(Flags.Flag.RECENT), true);
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.ANSWERED)) {
|
||||
NotTerm notAnswered = new NotTerm(new FlagTerm(new Flags(Flags.Flag.ANSWERED), true));
|
||||
if (searchTerm == null) {
|
||||
searchTerm = notAnswered;
|
||||
}
|
||||
else {
|
||||
searchTerm = new AndTerm(searchTerm, notAnswered);
|
||||
}
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.DELETED)) {
|
||||
NotTerm notDeleted = new NotTerm(new FlagTerm(new Flags(Flags.Flag.DELETED), true));
|
||||
if (searchTerm == null) {
|
||||
searchTerm = notDeleted;
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!recentFlagSupported) {
|
||||
NotTerm notFlagged = null;
|
||||
if (folder.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(AbstractMailReceiver.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);
|
||||
}
|
||||
}
|
||||
return searchTerm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.mail;
|
||||
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.search.SearchTerm;
|
||||
|
||||
/**
|
||||
* Strategy to be used to generate a {@link SearchTerm}
|
||||
*
|
||||
* See {@link ImapMailReceiver}
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.2
|
||||
*
|
||||
*/
|
||||
public interface SearchTermStrategy {
|
||||
|
||||
/**
|
||||
* Will generate an instance of the {@link SearchTerm}
|
||||
*
|
||||
* @param supportedFlags
|
||||
* @param folder
|
||||
* @return
|
||||
*/
|
||||
SearchTerm generateSearchTerm(Flags supportedFlags, Folder folder);
|
||||
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.integration.mail.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -26,11 +28,10 @@ import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.mail.ImapIdleChannelAdapter;
|
||||
import org.springframework.integration.mail.ImapMailReceiver;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the <imap-idle-channel-adapter> element in the 'mail' namespace.
|
||||
*
|
||||
*
|
||||
* @author Jonas Partner
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -38,6 +39,7 @@ import org.w3c.dom.Element;
|
||||
*/
|
||||
public class ImapIdleChannelAdapterParser extends AbstractChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(ImapIdleChannelAdapter.class);
|
||||
builder.addConstructorArgValue(this.parseImapMailReceiver(element, parserContext));
|
||||
@@ -49,6 +51,7 @@ public class ImapIdleChannelAdapterParser extends AbstractChannelAdapterParser {
|
||||
|
||||
private BeanDefinition parseImapMailReceiver(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder receiverBuilder = BeanDefinitionBuilder.genericBeanDefinition(ImapMailReceiver.class);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(receiverBuilder, element, "search-term-strategy");
|
||||
Object source = parserContext.extractSource(element);
|
||||
String uri = element.getAttribute("store-uri");
|
||||
if (StringUtils.hasText(uri)) {
|
||||
@@ -72,16 +75,16 @@ public class ImapIdleChannelAdapterParser extends AbstractChannelAdapterParser {
|
||||
if (StringUtils.hasText(markAsRead)){
|
||||
receiverBuilder.addPropertyValue("shouldMarkMessagesAsRead", markAsRead);
|
||||
}
|
||||
|
||||
|
||||
String selectorExpression = element.getAttribute("mail-filter-expression");
|
||||
|
||||
|
||||
RootBeanDefinition expressionDef = null;
|
||||
if (StringUtils.hasText(selectorExpression)){
|
||||
expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean");
|
||||
expressionDef.getConstructorArgumentValues().addGenericArgumentValue(selectorExpression);
|
||||
receiverBuilder.addPropertyValue("selectorExpression", expressionDef);
|
||||
}
|
||||
|
||||
return receiverBuilder.getBeanDefinition();
|
||||
|
||||
return receiverBuilder.getBeanDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,23 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="search-term-strategy" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.mail.SearchTermStrategy" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
Reference to a custom implementation of org.springframework.integration.mail.SearchTermStrategy
|
||||
to use when retrieving email.
|
||||
By default ImapMailReceiver will search for Messages based in the default SearchTerm
|
||||
which is "All mails that are RECENT (if supported), that are NOT ANSWERED, that are NOT DELETED, that are NOT SEEN and have not
|
||||
been processed by this mail receiver (enabled by the use of the custom USER flag or simply NOT FLAGGED if not supported)".
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
Reference in New Issue
Block a user