3
votes

I am new to Mule 3.3 and I am trying to use it to retrieve emails from a POP3 server and download the CSV attachments if the sender field and subject field contain certain keywords. I have used the example provided on Mulesoft website and I have successfully managed to scan my inbox for new emails and only download CSV attachments. However, I am now stuck because I can't figure out how to filter emails by subject and sender fields.

Doing some research I have come across a message-property-filter pattern tag that can be applied to an endpoint, but I am not sure exactly to which endpoint to apply it, incoming or outgoing. Neither approach seems to work and I can't find a decent example showing how to use this tag. The basic algorithm I want to implement is as follows:

if email is from "Bob"
  if attachment of type "CSV"
    then download CSV attachment

if email subject field contains "keyword"
  if attachment of type CSV
    then download CSV attachment

Here's the Mule xml I have so far:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:pop3s="http://www.mulesoft.org/schema/mule/pop3s" xmlns:pop3="http://www.mulesoft.org/schema/mule/pop3" 
xmlns="http://www.mulesoft.org/schema/mule/core" 
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" 
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/pop3s http://www.mulesoft.org/schema/mule/pop3s/current/mule-pop3s.xsd 
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd 
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd 
http://www.mulesoft.org/schema/mule/pop3 http://www.mulesoft.org/schema/mule/pop3/current/mule-pop3.xsd ">


<expression-transformer expression="#[attachments-list:*.csv]" 
   name="returnAttachments" doc:name="Expression">
</expression-transformer>

<pop3s:connector name="POP3Connector" 
    checkFrequency="5000" 
    deleteReadMessages="false" 
    defaultProcessMessageAction="RECENT" 
    doc:name="POP3" 
    validateConnections="true">
</pop3s:connector>

<file:connector name="fileName" doc:name="File">
    <file:expression-filename-parser />
</file:connector>

<flow name="incoming-orders" doc:name="incoming-orders">

    <pop3s:inbound-endpoint user="my_username" 
        password="my_password" 
        host="pop.gmail.com" 
        port="995" 
        transformer-refs="returnAttachments"
        doc:name="GetMail" 
        connector-ref="POP3Connector" 
        responseTimeout="10000"/>
    <collection-splitter doc:name="Collection Splitter"/>

    <echo-component doc:name="Echo"/>

    <file:outbound-endpoint path="/attachments" 
        outputPattern="#[function:datestamp].csv"
        doc:name="File" responseTimeout="10000"> 
        <expression-transformer expression="payload.inputStream"/>
        <message-property-filter pattern="from=(.*)([email protected])(.*)" caseSensitive="false"/>
    </file:outbound-endpoint>           
</flow>

What is the best way to tackle this problem?

Thanks in advance.

2

2 Answers

8
votes

To help you, here are two configuration bits:

  • The following filter accepts only messages where fromAddress is 'Bob' and where subject contains 'keyword':

    <expression-filter
        expression="#[message.inboundProperties.fromAddress == 'Bob' || message.inboundProperties.subject contains 'keyword']" />
    
  • The following transformer extracts all the attachments whose names end with '.csv':

    <expression-transformer
        expression="#[($.value in message.inboundAttachments.entrySet() if $.key ~= '.*\\.csv')]" />
    
3
votes

Welcome to Mule! A few month ago I implemented a similar proejct for a customer. I take a look at your flow, let´s start refactoring.

  • Remove the transformer-refs="returnAttachments" from inbound-endpoint
  • Add the following elements to your flow

    <pop3:inbound-endpoint ... />
    <custom-filter class="com.benasmussen.mail.filter.RecipientFilter"> 
        <spring:property name="regex" value=".*bob.bent@.*" />
    </custom-filter>
    <expression-transformer>
        <return-argument expression="*.csv" evaluator="attachments-list" />
    </expression-transformer>
    <collection-splitter doc:name="Collection Splitter" />
    
  • Add my RecipientFilter as java class to your project. All messages will be discard if they don't match to the regex pattern.

    package com.benasmussen.mail.filter;
    
    import java.util.Collection;
    import java.util.Set;
    import java.util.regex.Pattern;      
    import org.mule.api.MuleMessage;
    import org.mule.api.lifecycle.Initialisable;
    import org.mule.api.lifecycle.InitialisationException;
    import org.mule.api.routing.filter.Filter;
    import org.mule.config.i18n.CoreMessages;
    import org.mule.transport.email.MailProperties;
    
    public class RecipientFilter implements Filter, Initialisable
    {
        private String regex;
        private Pattern pattern;
    
        public boolean accept(MuleMessage message)
        {
            String from = message.findPropertyInAnyScope(MailProperties.FROM_ADDRESS_PROPERTY, null);
            return isMatch(from);
        }
    
        public void initialise() throws InitialisationException
        {
            if (regex == null)
            {
                throw new InitialisationException(CoreMessages.createStaticMessage("Property regex is not set"), this);
            }
            pattern = Pattern.compile(regex);
        }
    
        public boolean isMatch(String from)
        {
            return pattern.matcher(from).matches();
        }
    
        public void setRegex(String regex)
        {
            this.regex = regex;
        }
    }
    

The mule expression framework is powerful, but in some use cases I prefer my own business logic.

Improvment

Documentation

  • MailProperties shows you all available message properties (EMail)
  • Take a look at the mule schema doc to see all available elements
  • Incoming payload (mails, etc) are transported by an DefaultMuleMessage (Payload, Properties, Attachments)