0

I am setting up a flow to organize and save emails as PDF in a Dropbox folder. The first email that will arrive includes a 10 digit identification number which I extract along with an address. My flow creates a folder in Dropbox named in this format: 2023568684 : 123 Main St. Over a few weeks, additional emails arrive that I need to put into that folder. The subject always has a 10 digit number in it. I was building around each email and using functions like split, first, last, etc. to isolate the 10 digits ID. The problem is that there is no consistency in the subjects or bodies of the messages to be able to easily find the ID with that method. I ended up starting to build around each email format individually but there are way too many, not to mention the possibility of new senders or format changes.

My idea is to use List files in folder when a new message arrives which will create an array that I can filter to find the folder ID the message needs to be saved to. I know there is a limitation on this because of the 20 file limit but that is a different topic and question.

For now, how do I find a random 10 digit number in a randomly formatted email subject line so I can use it with the filter function?

Shaido
  • 27,497
  • 23
  • 70
  • 73
DryBSMT
  • 51
  • 2
  • 12

1 Answers1

2

For this requirement, you really need regex and at present, PowerAutomate doesn't support the use of regex expressions but the good news is that it looks like it's coming ...

https://powerusers.microsoft.com/t5/Power-Automate-Ideas/Support-for-regex-either-in-conditions-or-as-an-action-with/idi-p/24768

There is a connector but it looks like it's not free ...

https://plumsail.com/actions/request-free-license

To get around it for now, my suggestion would be to create a function app in Azure and let it do the work. This may not be your cup of tea but it will work.

I created a .NET (C#) function with the following code (straight in the portal) ...

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    
    string strToSearch = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String((string)data?.Text));
    string regularExpression = data?.Pattern;

    var matches = System.Text.RegularExpressions.Regex.Matches(strToSearch, regularExpression);

    var responseString = JsonConvert.SerializeObject(matches, new JsonSerializerSettings()
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    });

    return new ContentResult()
    {
        ContentType = "application/json",
        Content = responseString
    };
}

Then in PowerAutomate, call the HTTP action passing in a base64 encoded string of the content you want to search ...

HTTP

The is the expression in the JSON ... base64(variables('String to Search')) ... and this is the json you need to pass in ...

{
    "Text": "@{base64(variables('String to Search'))}",
    "Pattern": "[0-9]{10}"
}

This is an example of the response ...

[
  {
    "Groups": {},
    "Success": true,
    "Name": "0",
    "Captures": [],
    "Index": 33,
    "Length": 10,
    "Value": "2023568684"
  },
  {
    "Groups": {},
    "Success": true,
    "Name": "0",
    "Captures": [],
    "Index": 98,
    "Length": 10,
    "Value": "8384468684"
  }
]

Next, add a Parse JSON action and use this schema ...

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "Groups": {
                "type": "object",
                "properties": {}
            },
            "Success": {
                "type": "boolean"
            },
            "Name": {
                "type": "string"
            },
            "Captures": {
                "type": "array"
            },
            "Index": {
                "type": "integer"
            },
            "Length": {
                "type": "integer"
            },
            "Value": {
                "type": "string"
            }
        },
        "required": [
            "Groups",
            "Success",
            "Name",
            "Captures",
            "Index",
            "Length",
            "Value"
        ]
    }
}

Parse JSON

Finally, extract the first value that you find which matches the regex pattern. It returns multiple results if found so if you need to, you can do something with those.

Variable

This is the expression ... @{first(body('Parse_JSON'))?['value']}

From this string ...

We're going to search for string 2023568684 within this text and we're also going to try and find 8384468684, this should work.

... this is the result ...

Result

Don't have a Premium PowerAutomate licence so can't use the HTTP action?

You can do this exact same thing using the LogicApps service in Azure. It's the same engine with some slight differences re: connectors and behaviour.

Instead of the HTTP, use the Azure Functions action.

Azure Function Action

In relation to your action to fire when an email is received, in LogicApps, it will poll every x seconds/minutes/hours/etc. rather than fire on event. I'm not 100% sure which email connector you're using but it should exist.

Dropbox connectors exist, that's no problem.

You can export your PowerAutomate flow into a LogicApps format so you don't have to start from scratch.

https://learn.microsoft.com/en-us/azure/logic-apps/export-from-microsoft-flow-logic-app-template

Export

If you're concerned about cost, don't be. Just make sure you use the consumption plan. Costs only really rack up for these services when the apps run for minutes at a time on a regular basis. Just keep an eye on it for your own mental health.

TO get the function URL, you can find it in the function itself. You have to be in the function ...

Function URL

Skin
  • 9,085
  • 2
  • 13
  • 29
  • 1
    WOW, That looks mazing. So much detail. I am overwhelmed by your help. Thank you. I am fairly new and just getting my head around Power Automate and have zero knowledge of Azure but now armed with your help, I will plunge in and figure that part out too. I don't have an azure subscription but I believe there is some functionality available with an office 365 account. I will work on that next and let you know how it goes. Once I have it, I will mark your answer. – DryBSMT Jan 13 '22 at 01:37
  • @DryBSMT, no worries. Believe it or not, I find this sort of stuff to be quite fun. I enjoy trying to solve these challenged with the Lego pieces I have on hand. It may useful for me one day. :-) Anyway, good luck, if you need help on the Azure side, let me know. – Skin Jan 13 '22 at 01:55
  • I was able to sign up for Azure because my Azure was only Azure AD. I haven't figured out the cost going forward but I have 30 days to see if I can make this work and decide from there. Back in Power Automate, HTTP is a pemium action. Do you know if any of the other non-premium actions would work? – DryBSMT Jan 13 '22 at 15:17
  • @DryBSMT, as long as you use consumption in your Azure Function app, it'll be neglible to none, like, less than a cent a month. Seriously! If you run it 100's of times a day, it will still be very VERY cheap. Price of a coffee cheap. As for your problem with the premium licence, I'll update my answer, it should help. – Skin Jan 13 '22 at 21:55
  • When I enter the azure address in the URI field, you conclude it with code=***. What should this be? Is it the Function key? Nope, just tried it and it says `Not a valid uri`. – DryBSMT Jan 16 '22 at 22:29
  • @DryBSMT, yes, that's correct, you can get the function URL (which has the code) from a button at the top when you're in the function itself in Azure. – Skin Jan 16 '22 at 22:31
  • Are you in Logic Apps or in PowerAutomate? I assume Logic Apps given you don't have a premium licence?!? – Skin Jan 16 '22 at 22:33
  • The button only has https://l******r.azurewebsites.net and nothing else. Yours includes /api/SearchStringWithRegexPattern? code= – DryBSMT Jan 16 '22 at 22:38
  • Yes, Logic Apps. – DryBSMT Jan 16 '22 at 22:38
  • Changed my answer. I think you're getting the URL from the function app. You shouldn't need to do that though, you just need to use the Azure Functions action. It will list the functions you have available to choose from. – Skin Jan 16 '22 at 22:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241115/discussion-between-skin-and-drybsmt). – Skin Jan 16 '22 at 22:44