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 2578583c33..df363c0601 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 @@ -27,7 +27,6 @@ import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Store; import javax.mail.URLName; -import javax.mail.Flags.Flag; import javax.mail.internet.MimeMessage; import org.apache.commons.logging.Log; @@ -63,7 +62,7 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl private volatile boolean shouldDeleteMessages = false; - private volatile int folderOpenMode = Folder.READ_ONLY; + protected volatile int folderOpenMode = Folder.READ_ONLY; private volatile Properties javaMailProperties = new Properties(); @@ -207,7 +206,7 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl if (logger.isDebugEnabled()) { logger.debug("opening folder [" + MailTransportUtils.toPasswordProtectedString(this.url) + "]"); } - this.folder.open(folderOpenMode); + this.folder.open(this.folderOpenMode); } public synchronized Message[] receive() { @@ -244,7 +243,7 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl "failure occurred while receiving from folder", e); } finally { - MailTransportUtils.closeFolder(this.folder); + MailTransportUtils.closeFolder(this.folder, this.shouldDeleteMessages); } } @@ -278,7 +277,7 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl public void destroy() throws Exception { synchronized (this.initializationMonitor) { - MailTransportUtils.closeFolder(this.folder); + MailTransportUtils.closeFolder(this.folder, this.shouldDeleteMessages); MailTransportUtils.closeService(this.store); this.folder = null; this.store = null; @@ -290,14 +289,21 @@ public abstract class AbstractMailReceiver extends IntegrationObjectSupport impl public String toString() { return this.url.toString(); } + /** + * Optional method allowing you to set additional flags. + * Currently only implemented in IMapMailReceiever. + * + * @param message + * @throws MessagingException + */ + protected void setAdditionalFlags(Message message) throws MessagingException {} - protected void setAdditionalFlags(Message message) throws MessagingException { - if (this.shouldDeleteMessages) { - message.setFlag(Flag.DELETED, true); + /** + * + */ + protected void onInit() throws Exception { + if (this.shouldDeleteMessages){ + this.folderOpenMode = Folder.READ_WRITE; } } - - void setFolderOpenMode(int folderOpenMode) { - this.folderOpenMode = folderOpenMode; - } } 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 77f51740c8..b16d6ef677 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 @@ -179,7 +179,7 @@ public class ImapMailReceiver extends AbstractMailReceiver { */ protected void onInit() throws Exception { if (this.shouldMarkMessagesAsRead){ - this.setFolderOpenMode(Folder.READ_WRITE); + this.folderOpenMode = Folder.READ_WRITE; } } /** diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/MailTransportUtils.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/MailTransportUtils.java index 480e34fa76..5a3ad02760 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/MailTransportUtils.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/MailTransportUtils.java @@ -58,16 +58,16 @@ public abstract class MailTransportUtils { } } - /** - * Close the given JavaMail Folder and ignore any thrown exception. This is - * useful for typical finally blocks in manual JavaMail code. - * - * @param folder the JavaMail Folder to close (may be null) - */ - - public static void closeFolder(Folder folder) { - closeFolder(folder, false); - } +// /** +// * Close the given JavaMail Folder and ignore any thrown exception. This is +// * useful for typical finally blocks in manual JavaMail code. +// * +// * @param folder the JavaMail Folder to close (may be null) +// */ +// +// public static void closeFolder(Folder folder) { +// closeFolder(folder, false); +// } /** * Close the given JavaMail Folder and ignore any thrown exception. This is @@ -79,7 +79,7 @@ public abstract class MailTransportUtils { public static void closeFolder(Folder folder, boolean expunge) { if (folder != null && folder.isOpen()) { try { - folder.close(expunge); + folder.close(expunge); } catch (MessagingException ex) { logger.debug("Could not close JavaMail Folder", ex); diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java index 0fa3df95a0..4a2fb337c4 100755 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java @@ -16,6 +16,7 @@ package org.springframework.integration.mail; +import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.URLName; @@ -79,7 +80,5 @@ public class Pop3MailReceiver extends AbstractMailReceiver { for (int i = 0; i < messages.length; i++) { new MimeMessage((MimeMessage) messages[i]); } - MailTransportUtils.closeFolder(this.getFolder(), true); } - } diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java index 002425eff6..f382949d8b 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java @@ -155,6 +155,7 @@ public class MailReceiverFactoryBean implements FactoryBean, Dispo ((ImapMailReceiver)receiver).setShouldMarkMessagesAsRead(this.shouldMarkMessagesAsRead); } } + receiver.afterPropertiesSet(); return receiver; } 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 04d65bbece..d82e7e5b7c 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 @@ -53,6 +53,8 @@ import com.sun.mail.imap.IMAPFolder; */ public class ImapMailReceiverTests { + + @Test public void receieveAndMarkAsReadDontDelete() throws Exception{ AbstractMailReceiver receiver = new ImapMailReceiver(); @@ -164,6 +166,44 @@ public class ImapMailReceiverTests { verify(msg2, times(0)).setFlag(Flag.SEEN, true); } @Test + public void receieveAndDontMarkAsReadButDelete() throws Exception{ + AbstractMailReceiver receiver = new Pop3MailReceiver(); + ((Pop3MailReceiver)receiver).setShouldDeleteMessages(true); + receiver = spy(receiver); + receiver.afterPropertiesSet(); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + 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"); + if (folderOpenMode != Folder.READ_WRITE){ + throw new IllegalArgumentException("Folder had to be open in READ_WRITE mode"); + } + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.afterPropertiesSet(); + receiver.receive(); + verify(msg1, times(0)).setFlag(Flag.SEEN, true); + verify(msg2, times(0)).setFlag(Flag.SEEN, true); + verify(msg1, times(1)).setFlag(Flag.DELETED, true); + verify(msg2, times(1)).setFlag(Flag.DELETED, true); + } + @Test public void receieveAndIgnoreMarkAsReadDontDelete() throws Exception{ AbstractMailReceiver receiver = new ImapMailReceiver(); receiver = spy(receiver); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java new file mode 100644 index 0000000000..d5f8790682 --- /dev/null +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java @@ -0,0 +1,197 @@ +/* + * Copyright 2002-2010 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 static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Properties; + +import javax.mail.Flags; +import javax.mail.Flags.Flag; +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.internet.MimeMessage; + +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.core.PollableChannel; +import org.springframework.integration.history.MessageHistory; +import org.springframework.integration.mail.config.ImapIdleChannelAdapterParserTests; +import org.springframework.integration.test.util.TestUtils; + +import com.sun.mail.imap.IMAPFolder; + +/** + * @author Oleg Zhurakousky + * + */ +public class Pop3MailReceiverTests { + @Test + public void receieveAndDelete() throws Exception{ + AbstractMailReceiver receiver = new Pop3MailReceiver(); + ((Pop3MailReceiver)receiver).setShouldDeleteMessages(true); + receiver = spy(receiver); + receiver.afterPropertiesSet(); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + 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"); + if (folderOpenMode != Folder.READ_WRITE){ + throw new IllegalArgumentException("Folder had to be open in READ_WRITE mode"); + } + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.afterPropertiesSet(); + receiver.receive(); + verify(msg1, times(1)).setFlag(Flag.DELETED, true); + verify(msg2, times(1)).setFlag(Flag.DELETED, true); + } + @Test + public void receieveAndDontDelete() throws Exception{ + AbstractMailReceiver receiver = new Pop3MailReceiver(); + ((Pop3MailReceiver)receiver).setShouldDeleteMessages(false); + receiver = spy(receiver); + receiver.afterPropertiesSet(); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + 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"); + if (folderOpenMode == Folder.READ_WRITE){ + throw new IllegalArgumentException("Folder had to be open in READ_ONLY mode"); + } + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.afterPropertiesSet(); + receiver.receive(); + verify(msg1, times(0)).setFlag(Flag.DELETED, true); + verify(msg2, times(0)).setFlag(Flag.DELETED, true); + } + @Test @Ignore + public void receieveAndDontSetDeleteFlagWithUrl() throws Exception{ + AbstractMailReceiver receiver = new Pop3MailReceiver("pop3://some.host"); + receiver = spy(receiver); + receiver.afterPropertiesSet(); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + 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"); + if (folderOpenMode == Folder.READ_WRITE){ + throw new IllegalArgumentException("Folder had to be open in READ_ONLY mode"); + } + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.afterPropertiesSet(); + receiver.receive(); + verify(msg1, times(0)).setFlag(Flag.DELETED, true); + verify(msg2, times(0)).setFlag(Flag.DELETED, true); + } + @Test + public void receieveAndDontSetDeleteFlagWithoutUrl() throws Exception{ + AbstractMailReceiver receiver = new Pop3MailReceiver(); + receiver = spy(receiver); + receiver.afterPropertiesSet(); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + 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"); + if (folderOpenMode == Folder.READ_WRITE){ + throw new IllegalArgumentException("Folder had to be open in READ_ONLY mode"); + } + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.afterPropertiesSet(); + receiver.receive(); + verify(msg1, times(0)).setFlag(Flag.DELETED, true); + verify(msg2, times(0)).setFlag(Flag.DELETED, true); + } +}