Filtering Spam Emails with Power Automate

It's New Year's Eve and I've spent the last few days reviewing goals, projects, and tools in preparation for a streamlined 2023. Over the past 2 months, I've received more spam than usual in my email at Outlook.com and today is the perfect day to revamp the spam filters.

Built-In Email Features

Outlook.com has a built-in spam filter that moves emails to the spam folder but it might mislabel some newsletters as spam and so I can't clear the spam folder without reviewing it. It takes time and I don't want to spend time manually confirming spam emails and deleting them anymore. I've also used the "Junk email" feature found in settings to block senders and domains but spammers generate domains and emails too often for me to manually keep my block list up-to-date.

Outlook.com also allows users to create inbox rules that will automatically perform specific actions on emails that arrive in the inbox. I use this feature to categorize and move emails to my folders but find it cumbersome for spam filtering. Rule conditions can be specified with AND conditions (not OR) and so one rule would have to be set up for one condition.

Fortunately, Microsoft's Power Automate can be used to create a more customized spam filter.

Spam Filter Criteria

My criteria for a successful email spam filter are:

  1. If an email is identified as spam, it will be marked as read and moved to trash.
  2. Filtering will apply to other folders in addition to the inbox.
  3. The spam filter can be tested to ensure proper operation.

Assumptions & Caveats

  1. The body of spam emails typically include images and similar image hosting servers are used across multiple spammers.
  2. If a spammer uses a new image hosting server, the filter will need to be updated. Fortunately, it is a bigger lift to set up an image hosting server than it is for spammers to create new emails and domains.
  3. Any non-spam emails using blacklisted image hosting servers will be marked as spam. Only add servers you're comfortable with.

Spam Filter Setup

Creating a cloud flow

  1. Go to http://powerautomate.microsoft.com and log in with your Outlook.com email credentials.
  2. On the menu on the left side, select Create > Automated cloud flow.
  3. In the "Build an automated cloud flow" pop up window:
    1. Name the flow
    2. Select "When a new email arrives (V2)" under trigger (Office 365 Outlook users should use V3)
    3. Select "Create"
  4. A temporary flow is now created. Click on the folder button if you want your spam filter to monitor another folder.
  5. Select the "+ New step" button and then select "Condition" under Actions.
  6. Let's skip the Condition section for now and complete the rest so we can save the flow.
  7. Select "Add an action" in the "If yes" box to determine what should happen to an email if it meets the search criteria.
  8. Similarly to step 3.2 above, choose your Actions according to the type of user. My steps are:
    1. Select "Mark as read" and select "Message Id" under the "Dynamic content" pop-up. Each email message, even if the subject and body contents are not unique, has a unique id and "Message Id" is how Outlook.com identifies that email.
    2. Select "Add an action" underneath the "Mark as read" action and select "Move email".
    3. Select "Message Id" for the "Message Id" field like in step 8.1 and specify the folder you want to move the email to. I selected "Deleted Items" so that emails go to trash if they are considered spam.
  9. Select "Save" in the top right corner so that your flow is saved and let's jump back to the "Condition" section we skipped in step 6 to specify our criteria for spam emails.

Setting up conditions

Conditions are either categorized as an individual rule or a group of rules. The "Condition" section has a limitation of 10 rules/groups of rules. A workaround is to use multiple groups with OR conditions instead of individual rules. The other option is to add another condition under "If no" box and add more conditions there but this can get messy and make it more difficult to manage.

I'll be setting up my filter criteria with the multiple groups workaround. One group will be used for each category:

  1. Spam emails might have a empty subject or body. Expressions used in my setup are:
    • null
    • length(string(triggerBody()?['Body']))
  2. Spam emails might contain images and those image hosting servers can be targeted. To identify servers:
    1. Open your Outlook.com email in a web browser
    2. Open the spam email (don't click on its contents)
    3. Right click on the image and inspect the web page ("Inspect" for Chrome/"Inspect Element" for Safari)
    4. Copy the domain next to "src" for the "<img>" tag and use it for the filter condition
  3. Spam emails might contain my email in the subject. I don't recall coming across non-spammers using my email address in the subject.
  4. Spam emails might not have my email in the recipients list or might have my email listed in both the to: and cc: fields
  5. Spam emails may contain Greek alphabet letters in place of Latin alphabet letters and I don't expect non-spam emails to contain those letters so non-Latin characters can also be used as a filter. Text will be case-sensitive so you'll want to play around with Expressions if you want a case-insensitive filter (make everything lower case with toLower()).
  • Make sure all conditions are selected with "Or" unless you are trying to be more specific with your search criteria

Deployment

Don't forget to deploy your flow!

When complete, go back to the previous page and confirm that the "Status" is "On". If not, click on "Turn on" on the top menu.

Testing the Spam Filter

The built-in flow tester only works when some emails have passed through and the flow failed. When the flow is updated, you can rerun them on the emails that passed through to see if things wirj,

To test the filter when emails are already sitting in the mailbox, we will want to create a flow with the "When an email is flagged" trigger. This will run the spam filter if we flag an email in the folder.

  1. Before creating a new flow, copy the Condition section of the filter we created. Click on the menu and select "Copy to my clipboard (Preview)"
  2. Create a new flow by following steps 2 and 3 under Creating a cloud flow except select "When an email is flagged (V2)" as the trigger.
  3. Select the "+ New step" button and then select "Get emails (V2)" under Actions.
  4. Update "Fetch Only Unread Messages" to "No".
  5. Select the "+ New step" button and then select "Apply to each" under Actions.
  6. Select "value" for the "Select an output from previous steps" field.
  7. Select "Add an action", choose the "My clipboard" tab, and then select the copied Condition.
    • It may have a different name if you renamed your Condition box when we set up the initial flow.
    • If nothing is available, copy the Condition again from the previous flow by opening up a new browser window.
  8. Now that the condition is pasted, specify that the "Message Id" value needs to come from "Get emails (V2)" for the "Mark as read" and "Move email" boxes.
  9. Save the flow and turn it on. Test out the filter by flagging emails in the folder that the spam filter is monitoring. If there are emails that fit the specified condition, they should be marked as read and deleted. Some conditions may break the flow so fix those and once it works, update the flow that triggers when a new email is received.

I hope this guide helps you reduce email spam like it has for me and may your 2023 be spam-free!