In this article, we will discuss an automated email processing solution built using Power Automate. This flow is designed to monitor a shared mailbox, extract relevant email information, format the data, and send it securely to an external system using a REST API.
This automation helps eliminate manual effort, improves accuracy, and ensures consistent handling of incoming emails.
Flow Overview:
The automation performs the following key actions:
Detects new emails in a shared mailbox
Extracts sender details and email metadata
Identifies correct timestamps, including forwarded emails
Cleans and formats email content
Sends structured data to an external API
Creating the Email Processing Flow
Configuration of Trigger action: When a New Email Arrives in a Shared Mailbox (V2)
The flow starts with the “When a new email arrives in a shared mailbox (V2)” trigger. This trigger continuously monitors the shared mailbox and automatically starts the flow whenever a new email is received. In the trigger, add in the shared mailbox to be used in the “Original Mailbox Address” field:
![1]()
Export Email (V2) action configuration:
The Export Email (V2) action retrieves the complete email content. This step is required to accurately extract sender details, especially in cases where emails are forwarded and sender information is embedded inside the email body. In this action, configure the Message Id by using the Add dynamic content option. Ensure that the Message Id is selected from the trigger. In the subsequent field, select the same shared mailbox that is used in the trigger.
![2]()
Extract Sender Name and Email Address:
Add a “Compose” action (rename as ‘Extract Name and Email’) and use the following expression to extract the sender’s “From” line from the output of the Export Email (V2) action by isolating the text that appears immediately after From: and before the next line break. Using this approach, the flow extracts the complete sender information from the raw email content.
first(split(split(outputs('Export_email_(V2)')?['body'], 'From: ')[1], decodeUriComponent('%0D%0A')))
trim(split(outputs('Extract_Name_and_Email'), '<')[0])
trim(replace(split(split(outputs('Extract_Name_and_Email'), '<')[1], '>')[0], '>', ''))
This ensures that the correct sender information is captured.
Note: All these three compose actions can be added in a single scope action.
Parse Email Metadata Using Parse JSON action:
triggerBody()?['body']
![3]()
Save and test the flow by sending a test email to the configured shared mailbox.
Once the flow runs successfully, copy the output of the Compose action. This output will be used to generate the schema for the Parse JSON action.
Add “Parse JSON” action in the next step and configure it as follows:
triggerBody()?['body']
![4]()
![5]()
![6]()
![8]()
This structured data can then be conveniently referenced in subsequent steps of the flow.
Convert and Clean Email Content:
To ensure the content can be safely sent to external systems, the flow performs the following actions:
Converts HTML email content to plain text
Cleans special characters
Normalizes line breaks and formatting for JSON compatibility
![9]()
replace(replace(replace(replace(replace(replace(replace(replace(body('Html_to_text'),'’',''''),'‘',''''),'“','"'),'”','"'),'\\','\\\\'),'"','\"'),decodeUriComponent('%0A%0A'),decodeUriComponent('%0A')),'’','''')
This step helps prevent formatting and parsing errors when sending the email content to external systems.
Create Structured JSON Payload:
To prepare the email data for integration with an external system, a Compose action is used to build a structured JSON object.
Add a Compose action and rename it to ‘JSONBody’.
In the Inputs field, use the following expression to construct the JSON payload:
json(
concat(
'{',
'"subject":"',
if(
or(
empty(body('Parse_JSON_2')?['subject']),
equals(trim(body('Parse_JSON_2')?['subject']), '')
),
'No Subject',
replace(body('Parse_JSON_2')?['subject'], '"', '''')
),
'",',
'"priorityCode":"',
if(
equals(toLower(body('Parse_JSON_2')?['importance']), 'normal'),
'M',
if(
equals(toLower(body('Parse_JSON_2')?['importance']), 'high'),
'H',
if(
equals(toLower(body('Parse_JSON_2')?['importance']), 'low'),
'L',
'M'
)
)
),
'",',
'"commentDate":"',
formatDateTime(utcNow(), 'yyyy-MM-dd'),
'","',
'"senderName":"',
replace(outputs('SenderName'), '"', ''),
'","',
'"senderEmailId":"',
replace(outputs('SenderEmail'), '"', ''),
'","',
'"toEmailId":"',
if(
empty(body('Parse_JSON_2')?['toRecipients']),
'No Address',
replace(string(body('Parse_JSON_2')?['toRecipients']), '"', '')
),
'",',
'"ccEmailId":"',
if(
empty(body('Parse_JSON_2')?['ccRecipients']),
'No Address',
replace(string(body('Parse_JSON_2')?['ccRecipients']), '"', '')
),
'",',
'"allEmailIds":["',
if(
empty(body('Parse_JSON_2')?['toRecipients']),
'',
replace(string(body('Parse_JSON_2')?['toRecipients']), '"', '')
),
'"],',
'"gwMessageId":"',
if(
empty(body('Parse_JSON_2')?['id']),
'NoID',
body('Parse_JSON_2')?['id']
),
'",',
'"gwConversationId":"',
if(
empty(body('Parse_JSON_2')?['conversationId']),
'NoConversation',
body('Parse_JSON_2')?['conversationId']
),
'",',
'"threadTopic":"',
if(
empty(trim(body('Parse_JSON_2')?['subject'])),
'NoTopic',
trim(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
body('Parse_JSON_2')?['subject'],
'RE:', ''
),
'Re:', ''
),
're:', ''
),
'FW:', ''
),
'Fw:', ''
),
'fw:', ''
),
'FWD:', ''
),
'Fwd:', ''
),
'fwd:', ''
)
)
),
'",',
'"emailReceivedDate":"',
if(
or(
contains(toLower(body('Parse_JSON_2')?['subject']), 'fw:'),
contains(toLower(body('Parse_JSON_2')?['subject']), 'fwd:')
),
if(
contains(body('Parse_JSON_2')?['bodyPreview'], 'Sent:'),
formatDateTime(
trim(
first(
split(
last(
split(body('Parse_JSON_2')?['bodyPreview'], 'Sent:')
),
'To:'
)
)
),
'yyyy-MM-ddTHH:mm:ss'
),
formatDateTime(
body('Parse_JSON_2')?['receivedDateTime'],
'yyyy-MM-ddTHH:mm:ss'
)
),
formatDateTime(
body('Parse_JSON_2')?['receivedDateTime'],
'yyyy-MM-ddTHH:mm:ss'
)
),
'","',
'"commentDateTimeStamp":"',
formatDateTime(utcNow(), 'yyyy-MM-ddTHH:mm:ss'),
'","',
'"comment":"',
replace(outputs('Comment'), '"', ''''),
'","',
'"From":"',
if(
or(
contains(toLower(body('Parse_JSON_2')?['subject']), 'fw:'),
contains(toLower(body('Parse_JSON_2')?['subject']), 'fwd:')
),
trim(
first(
split(
trim(
first(
split(
trim(
last(
split(body('Parse_JSON_2')?['bodyPreview'], 'From:')
)
),
'Sent:'
)
)
),
'\r'
)
)
),
replace(outputs('SenderName'), '"', '')
),
'"',
'}'
)
)
The JSONBody Compose action consolidates all extracted and transformed email data into a single structured format, including:
Email subject (defaults to No Subject if empty)
Priority code derived from email importance
Sender name and email address
To and CC email addresses
Message ID and conversation ID
Cleaned thread topic (without RE / FW / FWD prefixes)
Email received date and comment timestamp
Cleaned email body content
Sender details for forwarded and non-forwarded emails
This step ensures that:
All required email information is captured consistently
Default values are applied where data is missing
The payload is properly formatted and safe for JSON transmission
The data is ready for secure submission to the external REST API
Retrieve Access Token
Before calling the external API, the flow retrieves an access token using a REST API call. This token is used for secure authentication.
Method: POST
URI: Enter the appropriate token endpoint URL
Headers:
Body: grant_type=client_credentials
Authentication:
Username: Enter the appropriate client ID
Password: Enter the appropriate client secret
In the next step, add a Compose action (rename it to AccessToken) to extract the access token from the response. Update the Input field as follows:
body('HTTPGetToken')?['access_token']
This Compose action stores the access token, which is then used as a Bearer token in the Authorization header of the subsequent API call.
Send Data to External REST API:
In the final step, the structured email data is sent to the external system using a REST API call.
Add the HTTP (Choose a REST API to invoke) action to invoke action and configure it as follows:
![10]()
Method: POST
URI: Enter the appropriate API endpoint URL
Headers:
Content-Type: application/json
Accept: application/json
This step completes the flow by securely submitting the structured email data to the external REST API. After a successful API call, an optional notification email can be sent to the original sender, informing them that their request has been successfully received and processed.