Coverage Report - org.mule.transport.email.RetrieveMessageReceiver
 
Classes in this File Line Coverage Branch Coverage Complexity
RetrieveMessageReceiver
0%
0/147
0%
0/68
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.transport.email;
 8  
 
 9  
 import org.mule.api.MuleException;
 10  
 import org.mule.api.MuleMessage;
 11  
 import org.mule.api.construct.FlowConstruct;
 12  
 import org.mule.api.endpoint.InboundEndpoint;
 13  
 import org.mule.api.lifecycle.CreateException;
 14  
 import org.mule.api.transport.Connector;
 15  
 import org.mule.api.transport.ReceiveException;
 16  
 import org.mule.transport.AbstractPollingMessageReceiver;
 17  
 import org.mule.transport.email.i18n.EmailMessages;
 18  
 import org.mule.util.FileUtils;
 19  
 import org.mule.util.StringUtils;
 20  
 import org.mule.util.UUID;
 21  
 
 22  
 import java.io.File;
 23  
 import java.io.FileOutputStream;
 24  
 import java.io.IOException;
 25  
 import java.util.ArrayList;
 26  
 import java.util.List;
 27  
 
 28  
 import javax.mail.Address;
 29  
 import javax.mail.Flags;
 30  
 import javax.mail.Folder;
 31  
 import javax.mail.Message;
 32  
 import javax.mail.MessagingException;
 33  
 import javax.mail.Store;
 34  
 import javax.mail.event.MessageCountEvent;
 35  
 import javax.mail.event.MessageCountListener;
 36  
 import javax.mail.internet.InternetAddress;
 37  
 import javax.mail.internet.MimeMessage;
 38  
 
 39  
 /**
 40  
  * Poll a mailbox for messages, remove the messages and route them as events into
 41  
  * Mule.
 42  
  * <p/>
 43  
  * This contains a reference to a mail folder (and also the endpoint and connector,
 44  
  * via superclasses)
 45  
  */
 46  
 public class RetrieveMessageReceiver extends AbstractPollingMessageReceiver implements MessageCountListener
 47  
 {
 48  0
     private Folder folder = null;
 49  0
     private Folder moveToFolder = null;
 50  
     private boolean backupEnabled;
 51  0
     private String backupFolder = null;
 52  
     // A lock to protect concurrent access to the folder.
 53  0
     private final Object folderLock = new Object();
 54  
 
 55  
     public RetrieveMessageReceiver(Connector connector,
 56  
                                    FlowConstruct flowConstruct,
 57  
                                    InboundEndpoint endpoint,
 58  
                                    long checkFrequency,
 59  
                                    boolean backupEnabled,
 60  
                                    String backupFolder) throws CreateException
 61  
     {
 62  0
         super(connector, flowConstruct, endpoint);
 63  0
         this.backupFolder = backupFolder;
 64  0
         this.backupEnabled = backupEnabled;
 65  0
         this.setFrequency(checkFrequency);
 66  0
     }
 67  
 
 68  
     private AbstractRetrieveMailConnector castConnector()
 69  
     {
 70  0
         return (AbstractRetrieveMailConnector) getConnector();
 71  
     }
 72  
 
 73  
     @Override
 74  
     protected void doConnect() throws Exception
 75  
     {
 76  0
         SessionDetails session = castConnector().getSessionDetails(endpoint);
 77  
 
 78  0
         Store store = session.newStore();
 79  0
         store.connect();
 80  0
         folder = store.getFolder(castConnector().getMailboxFolder());
 81  0
         if (castConnector().getMoveToFolder() != null)
 82  
         {
 83  0
             moveToFolder = store.getFolder(castConnector().getMoveToFolder());
 84  0
             moveToFolder.open(Folder.READ_WRITE);
 85  
         }
 86  
 
 87  
         // set default value if empty/null
 88  0
         if (StringUtils.isEmpty(backupFolder))
 89  
         {
 90  0
             this.backupFolder = connector.getMuleContext().getConfiguration().getWorkingDirectory()
 91  
                                 + "/mail/" + folder.getName();
 92  
         }
 93  
 
 94  0
         if (backupFolder != null && !this.backupFolder.endsWith(File.separator))
 95  
         {
 96  0
             this.backupFolder += File.separator;
 97  
         }
 98  0
     }
 99  
 
 100  
     @Override
 101  
     protected void doDisconnect() throws Exception
 102  
     {
 103  
         // nothing to do here
 104  0
     }
 105  
 
 106  
     @Override
 107  
     protected void doStop()
 108  
     {
 109  0
         synchronized (folderLock)
 110  
         {
 111  0
             if (folder != null)
 112  
             {
 113  0
                 folder.removeMessageCountListener(this);
 114  
             }
 115  0
         }
 116  0
     }
 117  
 
 118  
     @Override
 119  
     protected void doStart() throws MuleException
 120  
     {
 121  0
         super.doStart();
 122  0
         synchronized (folderLock)
 123  
         {
 124  0
             folder.addMessageCountListener(this);
 125  0
         }
 126  0
     }
 127  
 
 128  
     public void messagesAdded(MessageCountEvent event)
 129  
     {
 130  0
         Message messages[] = event.getMessages();
 131  0
         List<Message> processedMessages = new ArrayList<Message>();
 132  0
         if (messages != null)
 133  
         {
 134  0
             MuleMessage message = null;
 135  0
             for (int i = 0; i < messages.length; i++)
 136  
             {
 137  0
                 if (getLifecycleState().isStopping() || getLifecycleState().isStopped())
 138  
                 {
 139  0
                     break;
 140  
                 }
 141  0
                 processedMessages.add(messages[i]);
 142  
                 try
 143  
                 {
 144  0
                     if (!messages[i].getFlags().contains(Flags.Flag.DELETED)
 145  
                         && !messages[i].getFlags().contains(Flags.Flag.SEEN))
 146  
                     {
 147  0
                         MimeMessage mimeMessage = new MimeMessage((MimeMessage) messages[i]);
 148  0
                         storeMessage(mimeMessage);
 149  0
                         message = createMuleMessage(mimeMessage, endpoint.getEncoding());
 150  
 
 151  0
                         if (castConnector().isDeleteReadMessages())
 152  
                         {
 153  
                             // Mark as deleted
 154  0
                             messages[i].setFlag(Flags.Flag.DELETED, true);
 155  
                         }
 156  
                         else
 157  
                         {
 158  0
                             if (this.getEndpoint().getFilter() != null && this.getEndpoint().getFilter().accept(message))
 159  
                             {
 160  0
                                 Flags.Flag flag = castConnector().getDefaultProcessMessageAction();
 161  0
                                 if (flag != null)
 162  
                                 {
 163  0
                                     messages[i].setFlag(flag, true);
 164  
                                 }
 165  0
                             }
 166  
                             else
 167  
                             {
 168  0
                                 messages[i].setFlag(Flags.Flag.SEEN, false);
 169  
                             }
 170  
                         }
 171  
 
 172  0
                         routeMessage(message);
 173  
                     }
 174  
                 }
 175  0
                 catch (MuleException e)
 176  
                 {
 177  0
                     getConnector().getMuleContext().getExceptionListener().handleException(e);
 178  
                 }
 179  0
                 catch (Exception e)
 180  
                 {
 181  
                     Exception forwarded;
 182  
 
 183  0
                     if (message != null)
 184  
                     {
 185  0
                         forwarded = new org.mule.api.MessagingException(EmailMessages.routingError(), message, e);
 186  
                     }
 187  
                     else
 188  
                     {
 189  0
                         forwarded = new ReceiveException(endpoint, -1, e);
 190  
                     }
 191  
 
 192  0
                     getConnector().getMuleContext().getExceptionListener().handleException(forwarded);
 193  0
                 }
 194  
             }
 195  
             // Lets move all messages in one go
 196  0
             if (moveToFolder != null)
 197  
             {
 198  
                 try
 199  
                 {
 200  0
                     folder.copyMessages(processedMessages.toArray(new Message[processedMessages.size()]), moveToFolder);
 201  
                 }
 202  0
                 catch (MessagingException e)
 203  
                 {
 204  0
                     getConnector().getMuleContext().getExceptionListener().handleException(e);
 205  0
                 }
 206  
             }
 207  
         }
 208  0
     }
 209  
 
 210  
     public void messagesRemoved(MessageCountEvent event)
 211  
     {
 212  0
         if (logger.isDebugEnabled())
 213  
         {
 214  0
             Message messages[] = event.getMessages();
 215  0
             for (int i = 0; i < messages.length; i++)
 216  
             {
 217  
                 try
 218  
                 {
 219  0
                     logger.debug("Message removed: " + messages[i].getSubject());
 220  
                 }
 221  0
                 catch (MessagingException ignore)
 222  
                 {
 223  0
                     logger.debug("ignoring exception: " + ignore.getMessage());
 224  0
                 }
 225  
             }
 226  
         }
 227  0
     }
 228  
 
 229  
     /** @return the current Mail folder */
 230  
     public Folder getFolder()
 231  
     {
 232  0
         return folder;
 233  
     }
 234  
 
 235  
     /** @param folder */
 236  
     public void setFolder(Folder folder)
 237  
     {
 238  0
         synchronized (folderLock)
 239  
         {
 240  0
             if (folder == null)
 241  
             {
 242  0
                 throw new IllegalArgumentException("Mail folder cannot be null");
 243  
             }
 244  0
             this.folder = folder;
 245  0
             if (!this.folder.isOpen())
 246  
             {
 247  
                 try
 248  
                 {
 249  0
                     this.folder.open(Folder.READ_WRITE);
 250  
                 }
 251  0
                 catch (MessagingException e)
 252  
                 {
 253  0
                     logger.warn("Failed to open folder: " + folder.getFullName(), e);
 254  0
                 }
 255  
             }
 256  0
         }
 257  0
     }
 258  
 
 259  
     /**
 260  
      * Helper method for testing which stores a copy of the message locally as the
 261  
      * POP3
 262  
      * <p/>
 263  
      * message will be deleted from the server
 264  
      *
 265  
      * @param msg the message to store
 266  
      * @throws IOException If a failure happens writing the message
 267  
      * @throws MessagingException If a failure happens reading the message
 268  
      */
 269  
     protected void storeMessage(Message msg) throws IOException, MessagingException
 270  
     {
 271  0
         if (backupEnabled)
 272  
         {
 273  0
             String filename = msg.getFileName();
 274  0
             if (filename == null)
 275  
             {
 276  0
                 Address[] from = msg.getFrom();
 277  0
                 if (from != null && from.length > 0)
 278  
                 {
 279  0
                     filename = from[0] instanceof InternetAddress
 280  
                                                                  ? ((InternetAddress) from[0]).getAddress()
 281  
                                                                  : from[0].toString();
 282  
                 }
 283  
                 else
 284  
                 {
 285  0
                     filename = "(no from address)";
 286  
                 }
 287  0
                 filename += "[" + UUID.getUUID() + "]";
 288  
             }
 289  0
             filename = FileUtils.prepareWinFilename(filename);
 290  0
             filename = backupFolder + filename + ".msg";
 291  0
             if (logger.isDebugEnabled())
 292  
             {
 293  0
                 logger.debug("Writing message to: " + filename);
 294  
             }
 295  0
             File f = FileUtils.createFile(filename);
 296  0
             FileOutputStream fos = new FileOutputStream(f);
 297  0
             msg.writeTo(fos);
 298  
         }
 299  0
     }
 300  
 
 301  
     @Override
 302  
     public void poll()
 303  
     {
 304  0
         synchronized (folderLock)
 305  
         {
 306  
             try
 307  
             {
 308  
                 try
 309  
                 {
 310  0
                     if (!folder.isOpen())
 311  
                     {
 312  0
                         folder.open(Folder.READ_WRITE);
 313  
                     }
 314  
                 }
 315  0
                 catch (Exception e)
 316  
                 {
 317  0
                     if (logger.isDebugEnabled())
 318  
                     {
 319  0
                         logger.debug("ignoring exception: " + e.getMessage());
 320  
                     }
 321  0
                 }
 322  
 
 323  0
                 int count = folder.getMessageCount();
 324  0
                 if (count > 0)
 325  
                 {
 326  0
                     Message[] messages = folder.getMessages();
 327  0
                     MessageCountEvent event = new MessageCountEvent(folder, MessageCountEvent.ADDED, true,
 328  
                         messages);
 329  0
                     messagesAdded(event);
 330  0
                 }
 331  0
                 else if (count == -1)
 332  
                 {
 333  0
                     throw new MessagingException("Cannot monitor folder: " + folder.getFullName()
 334  
                                                  + " as folder is closed");
 335  
                 }
 336  
             }
 337  0
             catch (MessagingException e)
 338  
             {
 339  0
                 getConnector().getMuleContext().getExceptionListener().handleException(e);
 340  
             }
 341  
             finally
 342  
             {
 343  0
                 try
 344  
                 {
 345  0
                     folder.close(true); // close and expunge deleted messages
 346  
                 }
 347  0
                 catch (Exception e)
 348  
                 {
 349  0
                     logger.error("Failed to close pop3 inbox: " + e.getMessage());
 350  0
                 }
 351  0
             }
 352  0
         }
 353  0
     }
 354  
 
 355  
     @Override
 356  
     protected void doDispose()
 357  
     {
 358  0
         synchronized (folderLock)
 359  
         {
 360  0
             if (null != folder)
 361  
             {
 362  0
                 folder.removeMessageCountListener(this);
 363  0
                 if (folder.isOpen())
 364  
                 {
 365  
                     try
 366  
                     {
 367  0
                         folder.close(true);
 368  
                     }
 369  0
                     catch (Exception e)
 370  
                     {
 371  0
                         logger.debug("ignoring exception: " + e.getMessage(), e);
 372  0
                     }
 373  
                 }
 374  
             }
 375  0
         }
 376  0
     }
 377  
 
 378  
     @Override
 379  
     protected MuleMessage handleUnacceptedFilter(MuleMessage message)
 380  
     {
 381  0
         super.handleUnacceptedFilter(message);
 382  0
         if (message.getPayload() instanceof Message)
 383  
         {
 384  0
             Message msg = (Message) message.getPayload();
 385  
             try
 386  
             {
 387  0
                 msg.setFlag(Flags.Flag.DELETED, endpoint.isDeleteUnacceptedMessages());
 388  
             }
 389  0
             catch (MessagingException e)
 390  
             {
 391  0
                 logger.error("failed to set message deleted: " + e.getMessage(), e);
 392  0
             }
 393  
         }
 394  0
         return message;
 395  
     }
 396  
 }