SAP Process Integration

MAIL OAuth using PI/PO

Overview:

  • Business Requirement: Read mails from a specific mail-folder having specific subject line of a Microsoft outlook mail-account, extract the attachments (.csv files) and store them into local directories.
  • Mail OAuth can also be achieved using Mail Adapters “Configure OAuth” Authentication feature.
  • This blog gives an overview of an alternative (Java-Map) can be used into the PI/PO interface, where “Mail OAuth 2.0” (access token based) authentication mechanism is been applied.

Pre-requisites:

Following pre-requisites needs to be taken care of:

1. Get specific mail-id’s credentials like Client_ID, Client_Secret, Tenant_ID. For same, below Microsoft Guide link can be referred:

2. Understand how to fetch Access-Token using Microsoft-outlook-API protocols as below:

  • URL: https://login.microsoftonline.com/<token-ID>/oauth2/v2.0/token
  • Method: POST
  • Headers: “Content-Type”, “application/x-www-form-urlencoded”
  • Request:
    • grant_type client_credentials
    • client_id <mail-id’s secret value>
    • client_secret <mail-id’s secret value>
    • scope https://outlook.office365.com/.default
grant_type=client_credentials&client_id=<client-ID-value>&client_secret=<client-secret-value>&scope=https://outlook.office365.com/.default​
  • Response:
{
    "token_type": "Bearer",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "<access token value>"
}
  • Using POSTMAN tool, we can call access-token API as depicted in below screen
  • Here, TLS version and Cipher Suite required for this API also needs to be understood, the same should be present in PI/PO layer as well.

3. To allow connection between PI/PO and outlook mail, the Firewall whitelisting rule should be in place having source as PI/PO system and destination having below Microsoft’s FQDN

  • login.microsoftonline.com HTTPS-Port 443
  • outlook.office.com HTTPS-Port 443
  • outlook.office365.com HTTPS-Port 443, IMAP-Port 993, 143, POP3-Port 110, SMTP-Port 25

4. PI/PO system should support/have below:

  • TLS Protocol TLSv1.2
  • Cipher Suite ECDHE-RSA-AES256-GCM-SHA384 [ in PI/PO ssl.properties having “cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384” ]
  • SSL ICM parameter at Kernel/OS layer “icm/HTTPS/client_sni_enabled = TRUE”
  • In PI/PO, import below SSL certificate chain of ‘https://login.microsoftonline.com’
  • Note: While running Java-Map from PI/PO layer, using XPI_INSPECTOR LOG, we can understand in below screen, how SSL handshake takes place between PI/PO and login.microsoftonline.com while fetching the access-token :

Mail OAuth using Java-Map Technique:

  • Create a PI/PO interface as asynchronous outbound FILE-to-FILE
  • Here, we need to have a dummy file in SAP-Folder. Configure Sender-FILE adapter channel to read this file on an fix poll interval (hourly, daily etc. as per business needs), keep processing mode ‘Test’.
  • Configure Receiver-FILE adapter channel to create a dummy file with different name having overwrite feature enabled.
  • In ESR, create a SWCP and Namespace with dummy Data & Message Type. Import this Java-Map jar file and utilize into Operation Map.
  • In ID, create integration configuration object (ICO), utilize the operation map having Java-Map program.
  • Working of this PI/PO interface will be as follows:
    • On fix poll interval, say 2 hours, Sender-FILE-CC will keep reading dummy file from sap folder, which interns invokes Java-Map program and post Java-Program logic processing a dummy file will be created using Receiver-FILE-CC having Java-Map logs.
  • The functionalities of Java-Map program is as follows:
    • Get Mail-ID’s access token
    • Utilize the access-Token in next API, which is to read the unread mails of a specific mail-folder with specific subject-line.
    • Note: For reference, this Java-Map also has option about how to perform basic authentication (user-id/password based) to a mail account

Contents of the Java map program:

  1. Jar file ‘aii_map_api.jar’
    • Import it in Eclipse but no need to import in PI/PO ‘Enterprise Service Repository (ESR)’
  2. Jar file ‘javax.mail-1.6.2.jar’
    • Import it in Eclipse but no need to import in PI/PO ‘ESR’
  3. XML file ‘credentialsMail.xml’
    • Import this into Java-Program as resource file | This has mail account credentials (Test / Production both) in below XML structure manner
<?xml version="1.0" encoding="UTF-8"?>
<MailCredentials>
	<TEST>
		<mail_clientId>***</mail_clientId>
		<mail_tenantId>***</mail_tenantId>
		<mail_secret>***</mail_secret>
		<mail_scopeUrl>https://outlook.office365.com/.default</mail_scopeUrl>	
		<mail_accessTokenUrl>https://login.microsoftonline.com/(mail_tenantId)/oauth2/v2.0/token</mail_accessTokenUrl>
		<mail_protocol>imaps</mail_protocol>
		<mail_userEmail>XSD@ASD.com</mail_userEmail>
		<mail_userPassword>ASA@ASASFDFD</mail_userPassword>
		<mail_host>outlook.office365.com</mail_host>
		<mail_port>993</mail_port>
		<mail_folderToRead>Testing</mail_folderToRead>
		<mail_subjectSerachText>Test Mail-OAuth</mail_subjectSerachText>		
		<mail_readCountFiletr>20</mail_readCountFiletr>
		<mail_sapFolderOut>C:\\Users\\SDA\\TRun</mail_sapFolderOut>
	</TEST>
	<PRODUCTION>
		<mail_clientId>***</mail_clientId>
		<mail_tenantId>***</mail_tenantId>
		<mail_secret>***</mail_secret>
		<mail_scopeUrl>https://outlook.office365.com/.default</mail_scopeUrl>	
		<mail_accessTokenUrl>https://login.microsoftonline.com/(mail_tenantId)/oauth2/v2.0/token</mail_accessTokenUrl>
		<mail_protocol>imaps</mail_protocol>
		<mail_userEmail>XSD@ASD.com</mail_userEmail>
		<mail_userPassword>ASA@ASASFDFD</mail_userPassword>
		<mail_host>outlook.office365.com</mail_host>
		<mail_port>993</mail_port>
		<mail_folderToRead>Inbox</mail_folderToRead>
		<mail_subjectSerachText>REVENUE RPT</mail_subjectSerachText>		
		<mail_readCountFiletr>20</mail_readCountFiletr>
		<mail_sapFolderOut>/FLD1/FLD3/FLD3/FLD4/</mail_sapFolderOut>
	</PRODUCTION>
</MailCredentials>

4. Jar File ‘readMailOAuth.jar’

  • Import this in ‘ESR’ as an ‘Imported Archive’ under desired new interface namespace. | This is the Java-Map jar file, this will be only used in ‘Operation Map’

Java-Map program sample is as below:

This java program’s step wise functionalities are as follows:

  1. How to read attached resource file (‘credentialsMail.xml’) and as per PI/PO-system-ID instances, how to select the Test or Production credentials.
  2. How to get access token of ‘Microsoft outlook mail-account’
  3. How to use access token in next Microsoft API to read unread mails of a specific mail-folder with specific mail-subject line following IMAP protocols.
  4. How to read only current date’s unread mail
  5. How to store extracted attachments/files into SAP folder
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeBodyPart;
import javax.mail.search.FlagTerm;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.StreamTransformation;
import com.sap.aii.mapping.api.StreamTransformationConstants;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.DynamicConfiguration;
import com.sap.aii.mapping.api.DynamicConfigurationKey;

public class readMailOAuth implements StreamTransformation{
		
	private Map param;
	public void setParameter(Map map) {
		param = map;
		if (param == null) {
			param = new HashMap();
		}
	}
	
	private static AbstractTrace trace = null;
	private static String mapTrace = "";
	public void execute(InputStream in, OutputStream out) throws StreamTransformationException {
		try {
			mapTrace = "";			
			mapTrace = mapTrace + "=> Begin of JavaMap 'readMailOAuth()' | JavaMap to read mails with OAuth 2.0 | fetch mail attachments and store into SAP folder" + "\n" ;	
								
			mapTrace = mapTrace + "=> 1. Fetching the 'Mail credentials' " + "\n" ;
			readRscFile_MailCrd();
					
			mapTrace = mapTrace + "=> 2. Reading the mail " + "\n" ;				
			readMail();
							
			mapTrace = mapTrace + "=> End   of JavaMap 'readMailOAuth()' | JavaMap to read mails with OAuth 2.0 | fetch mail attachments and store into SAP folder" + "\n" ;							
			String outputXML = "<?xml version=\"1.0\"?>"
					+ "<Response>" + "\n" 
					+ "<JavaMap_Trace><![CDATA[" + mapTrace	+ "]]></JavaMap_Trace>"	+ "\n" 		
					+ "</Response>";
			Document docOut = convertStringToDocument(outputXML);
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transform = tf.newTransformer();		
			transform.transform(new DOMSource(docOut), new StreamResult(out));
					
			trace = (AbstractTrace)param.get(StreamTransformationConstants.MAPPING_TRACE);
			trace.addInfo(mapTrace);
			//System.out.println(mapTrace);							
		}catch(Exception e){
			trace.addInfo("==> Exception in FM execute(): " + e.getMessage());
			//System.out.println("==> Exception in FM execute(): " + e.getMessage());			
		}
	}
	
	private void readRscFile_MailCrd() throws IOException, ParserConfigurationException, SAXException{
				
		/**Based on SAPPO-SystemIDs, fetching the TEST or Production Mail-credentials
		 * Here, XML-Element /MailCredentials/TEST/ 		stores Test-System Credentials
		 * and 	 XML-Element /MailCredentials/PRODUCTION/ 	stores Production-System Credentials
		 */
		String systemID = "";	
		try {	
			//systemID = "DEV"; //For Eclipse-Platform-Testing
			systemID = (String) System.getProperty("SAPSYSTEMNAME");	//Get the systemID of PI/PO system (DEV or QAS or PRD)
			if(systemID.equals("DEV") || systemID.equals("QAS")){					
				readRscFile_MailCrd_Elements("TEST");
			}
			if(systemID.equals("PRD")){				
				readRscFile_MailCrd_Elements("PRODUCTION");
			}
		}catch (Exception e) {			
			mapTrace = mapTrace + "==>   Exception in FM 'readRscFile_MailCrd()'==> " + e.getMessage() + "\n";			
		}	
	}
	
	private static String mail_clientId;
	private static String mail_tenantId;
	private static String mail_secret;
	private static String mail_scopeUrl;
	private static String mail_accessTokenUrl;
	private static String mail_protocol;
	private static String mail_userEmail;
	private static String mail_userPassword;
	private static String mail_host;
	private static String mail_port;
	private static String mail_folderToRead;
	private static String mail_subjectSerachText;
	private static String mail_readCountFiletr;
	private static String mail_sapFolderOut;


	private void readRscFile_MailCrd_Elements(String XmlElementTagNm) throws IOException, ParserConfigurationException, SAXException{
							
		//Clear Global variables of this program			
		mail_clientId 		= "";
		mail_tenantId 		= "";
		mail_secret 		= "";	
		mail_scopeUrl 		= "";
		mail_accessTokenUrl	= "";
		mail_protocol		= "";
		mail_userEmail		= "";		
		mail_userPassword	= "";
		mail_host			= "";
		mail_port			= "";
		mail_folderToRead	= "";
		mail_subjectSerachText= "";
		mail_readCountFiletr = "";
		mail_sapFolderOut	= "";
			
		
		//Read Credentials stored in JavaMap-ResourceFile 'credentialsMail.xml'			
		String resFileName = "credentialsMail.xml";	
		
		//Parse the file into document
    	DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
 		DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
 		InputStream is_ShpCrd = getClass().getResourceAsStream(resFileName);
		Document xmlDocCrd = dbBuilder.parse(is_ShpCrd);	//Parse input to create document tree
		
		//----Start: Read Credentials from XmlFile ------	
		NodeList ndList_shp = xmlDocCrd.getElementsByTagName(XmlElementTagNm);
		for(int i1 = 0; i1 < ndList_shp.getLength(); i1++){
			Node nd_1 = ndList_shp.item(i1);
			for(Node nd_2 = nd_1.getFirstChild(); nd_2 != null; nd_2 = nd_2.getNextSibling()){
				if(nd_2.getNodeName().equals("mail_clientId")){					
					if(nd_2.getFirstChild() != null){	
						mail_clientId  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_tenantId")){					
					if(nd_2.getFirstChild() != null){	
						mail_tenantId  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_secret")){					
					if(nd_2.getFirstChild() != null){	
						mail_secret  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_scopeUrl")){				
					if(nd_2.getFirstChild() != null){	
						mail_scopeUrl  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_accessTokenUrl")){			
					if(nd_2.getFirstChild() != null){	
						mail_accessTokenUrl  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_protocol")){					
					if(nd_2.getFirstChild() != null){	
						mail_protocol  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_userEmail")){
					if(nd_2.getFirstChild() != null){	
						mail_userEmail  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_userPassword")){					
					if(nd_2.getFirstChild() != null){	
						mail_userPassword  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_host")){					
					if(nd_2.getFirstChild() != null){	
						mail_host  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_port")){					
					if(nd_2.getFirstChild() != null){	
						mail_port  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_folderToRead")){					
					if(nd_2.getFirstChild() != null){	
						mail_folderToRead  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_subjectSerachText")){					
					if(nd_2.getFirstChild() != null){	
						mail_subjectSerachText  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_sapFolderOut")){					
					if(nd_2.getFirstChild() != null){	
						mail_sapFolderOut  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				if(nd_2.getNodeName().equals("mail_readCountFiletr")){					
					if(nd_2.getFirstChild() != null){	
						mail_readCountFiletr  = nd_2.getFirstChild().getNodeValue();						
					}
				}
				
			}						
		}
					
		//----End  : Read Credentials from XmlFile ------	
		mapTrace = mapTrace + "=>    The JavaMap-ResourceFile '"+ resFileName + "' has been read.\n";	
		mapTrace = mapTrace + "=>     Email-ID user     : " + mail_userEmail + "\n" ;
		mapTrace = mapTrace + "=>     Email-ID password : " + "*****" + "\n" ;
		mapTrace = mapTrace + "=>     Client ID         : " + mail_clientId + "\n" ;
		mapTrace = mapTrace + "=>     Client Secret     : " + "*****" + "\n" ;
		mapTrace = mapTrace + "=>     Tenant ID         : " + mail_tenantId + "\n" ;
		mapTrace = mapTrace + "=>     Access-Token-Url  : " + mail_accessTokenUrl + "\n" ;
		mapTrace = mapTrace + "=>     Scope-Url         : " + mail_scopeUrl + "\n" ;
		mapTrace = mapTrace + "=>     Mail Protocol     : " + mail_protocol + "\n";
		mapTrace = mapTrace + "=>     Mail Host Name:   : " + mail_host + "\n";
		mapTrace = mapTrace + "=>     Mail Port         : " + mail_port + "\n";
		mapTrace = mapTrace + "=>     Mail Folder (to be read)             : " + mail_folderToRead + "\n";
		mapTrace = mapTrace + "=>     Mail Subject (prefix) to be serached : " + mail_subjectSerachText + "\n";
		mapTrace = mapTrace + "=>     SAP Folder to save mail-attachments  : " + mail_sapFolderOut + "\n";
	
	}

	private static String getAccessToken () {				
		mapTrace = mapTrace + "=>    [I] Fetching mail-OAuth Access Token the mail using below credentials" + "\n" ;		
		String accessToken = "";
		String httpResponseStr = "";
		try {	
			//Create HttpConenction
			URL url = new URL(mail_accessTokenUrl);
			URLConnection connection = url.openConnection(); 						
			HttpURLConnection httpConn = (HttpURLConnection) connection; 		
		
			//Set header
			httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");		
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);	
			httpConn.setRequestMethod("POST");
		
			//Prepare RequestData
			String jsonParam =
							"grant_type=" 		+	"client_credentials" 	+				
							"&client_id="		+	mail_clientId			+
							"&client_secret=" 	+ 	mail_secret 			+
							"&scope="			+	mail_scopeUrl ;						
			//Send Request
			DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream ());	
			wr.writeBytes(jsonParam);
			wr.flush();
			wr.close();
		
			//Read the response			
			InputStreamReader isr = null;
			if (httpConn.getResponseCode() == 200) {
				mapTrace = mapTrace +"           Status: HTTP Response Code 200 | Success | Access-Token is been found."+ "\n";
				
				//Reading response message
				isr = new InputStreamReader(httpConn.getInputStream());				
				BufferedReader in = new BufferedReader(isr); 	 		
				String strLine = "";
				while ((strLine = in.readLine()) != null) {
					httpResponseStr = httpResponseStr + strLine;
				}	
				
				if (httpResponseStr.indexOf("access_token") > -1) {
					accessToken = httpResponseStr.substring((httpResponseStr.indexOf("access_token") + 15), httpResponseStr.lastIndexOf("\""));
					//mapTrace = mapTrace +"           Response-AccessToken: " + accessToken;
				}
			} else {
				mapTrace = mapTrace +"           Response:  HTTP code " + httpConn.getResponseCode()+ " Error [" + httpConn.getResponseMessage() +"] while fetching accessToken."+ "\n";
				//throwCustomException = throwCustomException + " SharePoint-REST-Exception: AccessToken" + "\n";
			}			
		} catch (Exception e) {
			mapTrace = mapTrace + "          Exception in FM 'getAccessToken(): " + e.getMessage() + "\n";
			//throwCustomException = throwCustomException + " SharePoint-REST-Exception: AccessToken" + "\n";
		}	
		return accessToken;			
	}
	
	private static void readMail() {	
		try {

			boolean mailFound = false;

			// --------------------------------------------------
			Properties properties = new Properties();

			// Mail-Authentication method: OAUTH 2.0 ===================
			properties.put("mail.imaps.auth.plain.disable", "true");
			properties.setProperty("mail.imaps.starttls.enable", "true");
			properties.setProperty("mail.store.protocol", mail_protocol);
			properties.put("mail.imaps.auth.mechanisms", "XOAUTH2");

			Session emailSession = Session.getDefaultInstance(properties);
			Store store = emailSession.getStore(mail_protocol); // create the store object and connect with the server

			String accessToken = getAccessToken();
			store.connect(mail_host, Integer.parseInt(mail_port), mail_userEmail, accessToken);
			// =========================================================

			/*
			// Mail-Authentication method: Plain/Basic =================
			properties.put("mail.imaps.host", mail_host);
			properties.put("mail.imaps.port", mail_port);
			properties.put("mail.imaps.starttls.enable", "javax.net.ssl.SSLSocketFactory");
			properties.put("mail.imap.fetchsize", "1000000");

			Session emailSession = Session.getDefaultInstance(properties);
			Store store = emailSession.getStore(mail_protocol); // create the store object and connect with the server

			store.connect(mail_host, mail_userEmail, mail_userPassword);
			// =========================================================
			*/
			
			// create the folder object and open it
			Folder emailFolder = store.getFolder(mail_folderToRead);
			// emailFolder.open(Folder.READ_ONLY);
			emailFolder.open(Folder.READ_WRITE); // makes 'read' state to mail once it's been read by program

			// Read the mails of a specific folder
			// Message[] messages = emailFolder.getMessages(); //Reads all mails of a folder
			Message messages[] = emailFolder.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); // Reads only 'Unread' mails

			mapTrace = mapTrace + "=>    [II] Reading 'Unread' mails" + "\n";
			mapTrace = mapTrace + "=>         Status: " + "\n";
			mapTrace = mapTrace + "=>           Total mail count: " + emailFolder.getMessageCount() + "\n";
			mapTrace = mapTrace + "=>           Unread mail count: " + emailFolder.getUnreadMessageCount() + "\n";	

			/*
			//Get current Date-Time
			LocalDateTime now = LocalDateTime.now();
			int year = now.getYear();
			int month = now.getMonthValue();
			int day = now.getDayOfMonth();
			 */
			
			int mailReadLimit = Integer.parseInt(mail_readCountFiletr.trim());
			int mailReadCount = 0;
			for (int i = messages.length - 1; i >= 0; i--) {
				Message message = messages[i];
				/*
				//Filter only current date's mail only
				Calendar cal = Calendar.getInstance();
				cal.setTime(message.getReceivedDate());
				int yearMessage = cal.get(Calendar.YEAR);
				int monthMessage = cal.get(Calendar.MONTH) + 1;
				int dayMessage = cal.get(Calendar.DAY_OF_MONTH);			
				if(year == yearMessage && month == monthMessage && day == dayMessage) {
				*/	
					// To read specific Mail-subject mails
					String mailSub = message.getSubject().toString();
					//if (mailSub.startsWith(mail_subjectSerachText) && mailFound != true) {
					if ((mailSub.indexOf(mail_subjectSerachText) > -1)) {	
						mapTrace = mapTrace + "=>           Email Number: " + (i + 1) + "\n";		
						mapTrace = mapTrace + "=>           From: " + message.getFrom()[0] + "\n";
						mapTrace = mapTrace + "=>           Subject: " +  mailSub + "\n";
											
						Multipart multipart = (Multipart) message.getContent();

						// Read all unread mails having given Mail-Subjects
						for (int j = 0; j < multipart.getCount(); j++) {
							MimeBodyPart bodyPart = (MimeBodyPart) multipart.getBodyPart(j);
							if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
								/**
								 * AttachName is present into bodyPart.Type => 
								 * "application/octet-stream; \r\n	name=TestFileName_25011998155508.csv"
								 */
								String attachmentName = bodyPart.getContentType().toString();
								attachmentName = attachmentName.substring(attachmentName.indexOf("name=") + 5);		
								
								bodyPart.saveFile(mail_sapFolderOut + attachmentName); // save the attachment to folder
								mapTrace = mapTrace + "=>           Attachment name: " + attachmentName + "\n" ;							
								mapTrace = mapTrace + "=>           Attachment has been extracted and copied to folder '" + mail_sapFolderOut + "'\n" ;
								mapTrace = mapTrace + "=>         ----------------------" + "\n" ;	
							}
						}
					} else {		
						mapTrace = mapTrace + "=>           No 'UNREAD' mail in mail-folder '" + mail_folderToRead + "' having mail-subject '"+ mail_subjectSerachText + "'\n" ;
					}
				//}//current date mail filter			

				//limit mail read count	
				mailReadCount = mailReadCount + 1;
				if (mailReadCount >= mailReadLimit) {
					break;
				}
			}//end of mail-folder visit
			// close the store and folder objects
			emailFolder.close(false);
			store.close();
		} catch (Exception e) {
			mapTrace = mapTrace + "=>         Exception in  readMail() | " + e.getMessage() + "\n" ;
		}
	}

    private static Document convertStringToDocument(String xmlStr) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
        DocumentBuilder builder;  
        try  
        {  
            builder = factory.newDocumentBuilder();  
            Document doc = builder.parse( new InputSource( new StringReader( xmlStr ) ) ); 
            return doc;
        } catch (Exception e) {  
            e.printStackTrace();  
        } 
        return null;
    }

    /*
	public static void main(String[] args) {
		try {
			String filePath = "C:\\Users\\xyz\\";				
			String Fnm = "Test_01.txt";
			String inputFile = filePath + Fnm;	
			String outputFile = filePath + "OP_" + Fnm + ".xml" ;

			readMailOAuth myClass = new readMailOAuth();
			FileInputStream in = new FileInputStream(inputFile);
			FileOutputStream out = new FileOutputStream(outputFile);
			myClass.execute(in, out);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
    */
}

Testing:

For reference, test screen samples are give as follows:

Mail-Account having few unread mails. But Java-Program will checking mail-folder ‘Testing’ and filters unread mails having subject line ‘Test Mail-OAuth’

Mail account’s unread mail

Below Eclipse’ CONSOLE message log gives impression on step wise functionalities:

Eclipse Console log