Is there any Solution to download attachment from gmail in WSO2 ESB / WSO2 EI? - gmail-api

I am working on wso2 esb since last 6 months. I want to download attachment from gmail in wso2 esb/ei and save them into local folder.Google it and get solution only for sending attachment using gmail connector, not downloading attachment.
Note: Already seen,but can't able to get solution by referring the following link-
WSO2 esb get attach files from email
Code:
ProxyService
<proxy name="GmailConfigAttachment-TaskProxy" startOnLoad="true"
transports="http https" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<log level="custom">
<property name="Log Text"
value="Inside GmailConfigAttachment-TaskProxy Service"></property>
</log>
<property name="FORCE_SC_ACCEPTED" scope="axis2" type="STRING"
value="true" />
<property description="serviceName" name="serviceName"
scope="operation" type="STRING"
value="TaskScheduler_ASG_Read_Email_Body_Dummy_Service" />
<property description="messageId" expression="get-property('MessageID')"
name="messageId" scope="operation" type="STRING" />
<sequence key="Load_Gmail_Configuration" />
<gmail.init>
<userId>{$ctx:userId}</userId>
<accessToken>{$ctx:accessToken}</accessToken>
<apiUrl>{$ctx:apiUrl}</apiUrl>
<clientId>{$ctx:clientId}</clientId>
<clientSecret>{$ctx:clientSecret}</clientSecret>
<refreshToken>{$ctx:refreshToken}</refreshToken>
<accessTokenRegistryPath>{$ctx:registryPath}</accessTokenRegistryPath>
</gmail.init>
<gmail.listAllMails>
<labelIds>INBOX</labelIds>
<q>is:unread</q>
</gmail.listAllMails>
<log level="full" />
<iterate description="MailIterator" expression="//jsonObject/messages" sequential="true" id="listUnread">
<target>
<sequence>
<log description="Iterate Logger" level="custom" separator=",**, ">
<property expression="fn:concat('GmailConfigAttachment-TaskProxy_Service ESB-MessageId:',get-property('operation','messageId'))" name="LogText" />
<property expression="//id/text()" name="Gmail-MessageId" />
</log>
<property description="emailMsgId" expression="//id/text()" name="emailMsgId" scope="default" type="STRING" />
<property description="emailSubject" expression="//headers/name[text()='Subject']/../value/text()" name="emailSubject" scope="default" type="STRING"/>
<property description="emailDate" expression="//headers/name[text()='Date']/../value/text()" name="emailDate" scope="operation" type="STRING"/>
<property description="toAddress" expression="//headers/name[text()='To']/../value/text()" name="toAddress" scope="operation" type="STRING"/>
<header expression="fn:concat('Bearer ', $ctx:uri.var.gmail.accessToken)" name="Authorization" scope="transport" />
<gmail.readMail>
<id>{$ctx:emailMsgId}</id>
</gmail.readMail>
<payloadFactory media-type="xml">
<format>
<htmlProcessEmailBody xmlns="">
<emailMessageId>$1</emailMessageId>
<emailSubject>$2</emailSubject>
<emailBody>$3</emailBody>
</htmlProcessEmailBody>
</format>
<args>
<arg evaluator="xml" expression="get-property('emailMsgId')"/>
<arg evaluator="xml" expression="get-property('emailSubject')"/>
<arg evaluator="xml" expression="//payload"/>
</args>
</payloadFactory>
<log level="custom">
<property description="emailMsgId" expression="get-property('emailMsgId')" name="emailMsgId" scope="default" type="STRING" />
<property description="emailSubject" expression="//headers/name[text()='Subject']/../value/text()" name="emailSubject" scope="default" type="STRING"/>
<property description="emailDate" expression="//headers/name[text()='Date']/../value/text()" name="emailDate" scope="default" type="STRING"/>
<property description="toAddress" expression="//headers/name[text()='To']/../value/text()" name="toAddress" scope="default" type="STRING"/>
</log>
<!-- here i need further process to download attachment from gmail -->
</sequence>
</target>
</iterate>
</inSequence>
<outSequence />
<faultSequence />
</target>
Output of ESB
So Can anyone help me to provide solution?
Awaiting for your response.
Thank you.

Finally i found the solution for my question.
Idea :
Iterating each parts then getting email attachment id which will be passed to gmail api in order to get base64 encoded format.
Code snippet:
<iterate continueParent="true" description="MailIterator" expression="//parts" id="listUnread" sequential="true">
<target>
<sequence>
<property expression="//filename[text()!=' ']" name="AttachedFileName" scope="default" type="STRING"/>
<property expression="substring-after(get-property('AttachedFileName'),'.')" name="Attachmentextension" scope="default" type="STRING"/>
<filter description="check emailSubject" regex="jpg|jpeg|png|gif|webp|tiff|tif|psd|raw|bmp|dib|heif|heic|indd|ind|jp2" source="lower-case(get-property('Attachmentextension'))">
<then>
<property description="emailAttachmentId" expression="//attachmentId/text()" name="uri.var.attachmentId" scope="default" type="STRING"/>
<log level="custom">
<property expression="get-property('AttachedFileName')" name="=====ValidAttachmentFileName===="/>
<property expression="get-property('uri.var.attachmentId')" name="====emailAttachmentId====="/>
</log>
<header expression="fn:concat('Bearer ', $ctx:uri.var.gmail.accessToken)" name="Authorization" scope="transport"/>
<call>
<endpoint>
<http method="get" uri-template="{+uri.var.gmail.apiUrl}/{+uri.var.gmail.apiVersion}/users/{+uri.var.gmail.userId}/messages/{+uri.var.id}/attachments/{+uri.var.attachmentId}"/>
</endpoint>
</call>
<property description="emailAttachment" expression="//data/text()" name="emailAttachment" scope="default" type="STRING"/>
<!-- ==========Script for Base64 url to Base64 Encoding Format ========== -->
<script language="js"><![CDATA[var log=mc.getServiceLog();
var emailAttachment = mc.getProperty('emailAttachment');
emailAttachment=emailAttachment.replaceAll("_","/").replaceAll("-","+");
mc.setProperty("modifiedemailAttachment",emailAttachment)]]></script>
<log level="custom">
<property expression="get-property('modifiedemailAttachment')" name="========modifiedemailAttachment========"/>
</log>

Related

Extract information of request in response mediator in wso2 apim 4.1.0

I need to use some information from request such as "query params" or "headers" in response mediator. for example use url query parameter in response flow. I tried to use <"inSequence"> and <"outSequence"> but I could'nt get any result.
For example I want to use this "log mediator" in response flow. "firstname" is query param in request:
<log level="custom">
<property name="firstname" expression="$url:firstname"/>
</log>
If you want to access the query parameters being sent in the original request from the out-sequence, simply set it to a property in the in-sequence. Then that property will be accessible in the out-sequence. See the example below.
In Sequence
<inSequence>
<property expression="$url:firstname" name="firstname" scope="default" type="STRING"/>
<log level="simple">
<property expression="$ctx:firstname" name="Firstname====" scope="default" type="STRING"/>
</log>
</inSequence>
Out Sequence
<outSequence>
<log level="simple">
<property expression="$ctx:firstname" name="Firstname====" scope="default" type="STRING"/>
</log>
<send/>
</outSequence>
I solved this problem by using two mediator. one for request flow and second for response flow. We can access in response flow, initial request properties.
This xml is for request flow:
<sequence name="main">
<property expression="$url:firstname" name="firstname" scope="default" type="STRING"/>
<log level="simple">
<property expression="$ctx:firstname" name="Firstname====" scope="default" type="STRING"/>
</log>
</sequence>
This request is for response flow:
<sequence name="main">
<log level="simple">
<property value="response$$$$$$$$$$$$$$$$$$$$$$$$$$" name="resp"
scope="default" type="STRING"/>
</log>
<log level="simple">
<property expression="$ctx:firstname" name="Firstname"
scope="default" type="STRING"/>
</log>
</sequence>

How to Store Message ActiveMQ into SQL Server

I did the configuration for storing the message in SQL Server according to the examples that were in the internet.
Tables are created when ActiveMQ is executed, but when I create and send messages via localhost:8161/admin/queues.jsp a record is not inserted into the database table ACTIVEMQ_MSGS.
I tested the changes that were possible, and I saw some things on the internet. I applied them in the config file, but it didn't work.
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:${activemq.conf}/credentials.properties</value>
</property>
</bean>
<!-- Allows accessing the server log -->
<bean id="logQuery" class="io.fabric8.insight.log.log4j.Log4jLogQuery" lazy-init="false" scope="singleton" init-method="start" destroy-method="stop" />
<bean id="mssql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost:1433;DatabaseName=activedb" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="poolPreparedStatements" value="true" />
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" producerFlowControl="true">
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000" />
</pendingMessageLimitStrategy>
</policyEntry>
<policyEntry queue=">" producerFlowControl="true" memoryLimit="1mb" />
</policyEntries>
</policyMap>
</destinationPolicy>
<managementContext>
<managementContext createConnector="false" />
</managementContext>
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.data}" dataSource="#mssql-ds" lockKeepAlivePeriod="0">
<adapter>
<transact-jdbc-adapter />
</adapter>
<locker>
<lease-database-locker lockAcquireSleepInterval="10000" dataSource="#mssql-ds">
<statements>
<statements lockTableName="activemq_lock" />
</statements>
</lease-database-locker>
</locker>
</jdbcPersistenceAdapter>
</persistenceAdapter>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit="64 mb" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb" />
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb" />
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:0?maximumConnections=1000" />
</transportConnectors>
<shutdownHooks>
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
</shutdownHooks>
</broker>
<import resource="jetty.xml" />
</beans>
Ensure you check the "Persistent Delivery" check-box when you send the message via the web console.

why CAMEL_MESSAGEPROCESSED created in SQL server db

I want to run Camel built application as stanalone. I am using maven to create standalone jar and execute route.When I run MainApp.java main method from eclipse or run using camel run then code runs as expected. But when I run using java -jar then 3 tables CAMEL_MESSAGEPROCESSED, CAMEL_MESSAGETRACED,hibernate_sequence are created into db. I do not want these tables created. Please help me find what I am doing wrong.
Camel, camel-jpa version 2.19.1
hibernate-entitymanager version 5.2.7.Final
Camel-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:prop="http://camel.apache.org/schema/placeholder"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-4.3.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="properties"
class="org.apache.camel.component.properti
es.PropertiesComponent">
<property name="location" value="classpath:db.properties" />
</bean>
<bean id="bridgePropertyPlaceholder"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location" value="classpath:db.properties" />
</bean>
<camelContext id="camel5" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="myBuilder" />
</camelContext>
<bean id="myBuilder"
class="com.aexp.gsnt.insight.updateCentralData.InsightRouterBuilder" />
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="transactionManager" ref="jpaTxManager" />
</bean>
<bean id="jpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect" />
<property name="showSql" value="${showSQL}" />
<property name="generateDdl" value="${generateDdl}" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.format_sql">${formatSQL}</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
</beans>
Persistence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="persistenceUnit"
transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>
MainApp.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
private static ClassPathXmlApplicationContext classPathXmlApplicationContext;
/* Invoked from Jar */
public static void main(String args[]) throws Exception {
System.out.println("Started Central Data Extractor");
System.setProperty("jsse.enableSNIExtension", "false");
classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/camel-context.xml");
classPathXmlApplicationContext.start();
}
}

WSO2 ESB How we can split Property's value and log after split chars?

I want get char after spilt messagetext !
<api xmlns="http://ws.apache.org/ns/synapse" name="iterate" context="/tokenize">
<resource methods="GET" uri-template="/{temp}">
<inSequence>
<property name="MessageText" value="a,b,c," scope="default"></property>
<log>
<property name="MessageText" expression="get-property('MessageText')"></property>
</log>
[how ergodic this MessageText?]
<iterate continueParent="true" expression="MessageText" sequential="true">
<target>
<sequence>
<log level="full" separator=",">
<property name="arrayChar" value="?"></property>
</log>
</sequence>
</target>
</iterate>
</inSequence>
</resource>
</api>
I want result!
arrayChar = a
arrayChar = b
arrayChar = c
iterate mediator need a list of xml nodes so, create a new XML message with the list of values extracted from your property 'MessageText' (the purpose of script mediator) and then, iterate the nodes from this message with iterate mediator
<inSequence>
<property name="MessageText" value="a,b,c" scope="default"/>
<script language="js"><![CDATA[
var payloadXML = new XML(<root/>);
for each (var item in String(mc.getProperty("MessageText")).split(',')) {
payloadXML.appendChild(new XML(<item>{item}</item>));
}
mc.setPayloadXML(payloadXML);
]]></script>
<iterate xmlns:fn="http://www.w3.org/2005/xpath-functions" continueParent="true" expression="//item" sequential="true">
<target>
<sequence>
<log level="full" separator=",">
<property name="arrayChar" expression="$body/item"></property>
</log>
</sequence>
</target>
</iterate>
</inSequence>

BreezeJS unable to parse EDM metadata with more than one namespace?

I am writing a web application with Breeze, OData, WebAPI, and Angular (BOWA) using the integrated WebAPI ASP Identity schema. When breeze consumes the $metadata it is unable to finish and gives a 'null' error and fails. I disabled the ASP Identity to test and it works fine. Is Breeze unable to address more than a single namespace? The namespace is posted below. Are there any known work arounds to this? (OData v3)
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="Microsoft.AspNet.Identity.EntityFramework">
<ComplexType Name="IdentityUserRole">
<Property Name="UserId" Type="Edm.String"/>
<Property Name="RoleId" Type="Edm.String"/>
</ComplexType>
<EntityType Name="IdentityUserClaim">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false"/>
<Property Name="UserId" Type="Edm.String"/>
<Property Name="ClaimType" Type="Edm.String"/>
<Property Name="ClaimValue" Type="Edm.String"/>
</EntityType>
<ComplexType Name="IdentityUserLogin">
<Property Name="LoginProvider" Type="Edm.String"/>
<Property Name="ProviderKey" Type="Edm.String"/>
<Property Name="UserId" Type="Edm.String"/>
</ComplexType>
</Schema>
Take a look at the section "Correcting the namespace for EdmBuilder" on this page: http://www.getbreezenow.com/documentation/odata-server

Resources