Invoking a Web Service via Email

Sample Number

505

Level

Intermediary

Description

Demonstrates the usage of UltraESB poll an email account, and forward the message payloads to a web service, and respond back via email with the Web Service response

Use Case

The UltraESB supports polling both POP3 and IMAP email boxes, according to a schedule specified as a repeating delay, or as a fully customizable CRON expression. In this example, we will poll a Gmail account "mail.maildemo.demo@gmail.com" every 10 seconds and forward any messages found to the SimpleStockQuoteService hosted using the test ToolBox.

A sample email message expected at this email account is shown below, and contains the stock symbol of interest to retrieve a quote.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.services.samples/">
   <soapenv:Body><soap:getQuote><request><symbol>ADRT</symbol></request></soap:getQuote></soapenv:Body>
</soapenv:Envelope>

The sample #505 configuration defines a proxy service "demo-proxy" bound to the transport defined with the id "mail-listener". Any service specific transport listener properties maybe specified at the service level [lines #4-5], and any common properties set at the transport listener level.

 1<u:proxy id="demo-proxy">
 2    <u:transport id="mail-listener">
 3        <u:property name="ultra.transport.url" value="mail.maildemo.demo@gmail.com"/>
 4        <u:property name="mail.pop3.user" value="mail.maildemo.demo"/>
 5        <u:property name="mail.pop3.password" value="password"/>
 6        <u:property name="ultra.polling.start_delay" value="2000"/>
 7        <u:property name="ultra.polling.repeat_interval" value="10000"/>
 8        <u:property name="ultra.mail.preserve_headers" value="From"/>
 9    </u:transport>
10    <u:target>
11        <u:inSequence>
12            <u:java><![CDATA[
13                logger.info("Sender Address : " + msg.getFirstTransportHeader("From"));
14                msg.addResponseCorrelation("correlatedFrom", msg.getFirstTransportHeader("From"));
15                msg.setContentType("text/xml");
16            ]]></u:java>
17        </u:inSequence>
18        <u:inDestination>
19            <u:address>http://localhost:9000/service/SimpleStockQuoteService</u:address>
20        </u:inDestination>
21        <u:outSequence>
22            <u:java><![CDATA[
23                msg.addTransportHeader("subject", "Custom Subject for Response");
24                msg.setDestinationURL("mailto:" + msg.getMessageProperty("correlatedFrom"));
25                logger.info("Sending Reply to : " + msg.getDestinationURL() + " : " + mediation.readPayloadAsString(msg));
26                mediation.sendToEndpoint(msg, "smtp-gmail");
27            ]]></u:java>
28        </u:outSequence>
29    </u:target>
30</u:proxy>
31<u:endpoint id="smtp-gmail">
32    <u:address type="default"/>
33</u:endpoint>

The service uses the inSequence specified in-line to process the emails received, and extracts the "From" address to send the response. This attribute is correlated to the asynchronous response when received from the SOAP web service call. While line #14 sets "correlatedFrom" attribute, line #24 reads it back in the response flow processing sequence.

When a raw email is received, it usually consists of many transport level headers - e.g. Return-Path, Message-ID, References, Received, In-Reply-To, DKIM-Signature, Received-SPF etc. Forwarding these headers to a SOAP service would be undesirable. The mail transport listener allows one to drop all specific headers while keeping only required headers - or to drop specific headers retaining everything else. Again these rules maybe specified at thre transport level [lines #10-11 below] or the service level [line #8 above]. In our example, we will retain only the "From" header to be used to send the response.

The inSequence explicitly sets the content type of the message to "text/xml" before forwarding to the SOAP service, as the email message we used for testing was a "text/plain" message the SOAP service will reject otherwise. The message is now sent to the inDestination - i.e. the SimpleStockQuoteService, and the response processed with the outSequence.

When executing the outSequence, a custom email subject is set by adding a message property "subject", and then the target destination email address set using the saved from email address. We then send this message using the endpoint "gmail-smtp" which is a "default" endpoint - i.e. its destination is selected as the current default target address as set in each message.

Debugging any Issues

Setting a property "mail.debug" as true on the transport - or setting the Log4J log level of the transport to TRACE will cause a complete JavaMail debug to be generated during processing. If accessing your specific mail server causes any issues, the detailed logs will be helpful to identify the underlying cause and rectify the issue.

mail-listener Configuration
 1<bean id="mail-listener" class="org.adroitlogic.ultraesb.transport.mail.MailTransportListener">
 2    <property name="properties">
 3        <map>
 4            <entry key="mail.pop3.socketFactory.fallback" value="false"/>
 5            <entry key="mail.pop3.host" value="pop.gmail.com"/>
 6            <entry key="mail.pop3.socketFactory.class" value="javax.net.ssl.SSLSocketFactory"/>
 7            <entry key="mail.pop3.socketFactory.port" value="995"/>
 8            <entry key="mail.pop3.port" value="995"/>
 9            <!--<entry key="removeHeaders" value="RemoveHeader, AnotherHeaderToRemove"/>-->
10            <!--<entry key="preserveHeaders" value="To, Subject, From"/>-->
11        </map>
12    </property>
13</bean>
14
15<!--Defines the mail transport sender. See http://api.adroitlogic.org/ for a complete list of the many configuration properties -->
16<bean id="mail-sender" class="org.adroitlogic.ultraesb.transport.mail.MailTransportSender">
17    <property name="properties">
18        <map>
19            <entry key="mail.smtp.host" value="smtp.gmail.com"/>
20            <entry key="mail.smtp.port" value="587"/>
21            <entry key="mail.smtp.user" value="username"/>
22            <entry key="mail.smtp.password" value="password"/>
23            <entry key="mail.smtp.from" value="username@gmail.com"/>
24            <entry key="mail.smtp.starttls.enable" value="true"/>
25            <entry key="mail.smtp.auth" value="true"/>
26            <!--uncomment to debug any issues entry key="mail.debug" value="true"/-->
27        </map>
28    </property>
29</bean>

Trying out the Sample

Do not use your real email account for testing, as the mail transport would delete emails after processing

Ensure that your have a Java Development Kit (JDK and not JRE) on your system with the PATH and JAVA_HOME properly set. Refer to getting started documentation to familiarize yourself if you are new. Replace the Gmail sample account credentials with your own test account username and password etc. Then start the sample #505.

asankha@asankha:~/java/ultraesb-1.7.0/bin$./ultraesb.sh -sample 505

Start the sample Jetty server hosting the SimpleStockQuoteServer from the ToolBox as bin/toolbox.sh (or the .bat on Windows). Now, send an email with the payload at the start of this article to the email account configured against the proxy service above. The Proxy service will process the request, retrieve a stock quote from the SimpleStockQuoteService service, and email you back the response!

In this topic
In this topic
Contact Us