Powershell script to configure POP3 isolation for mailboxes in Azure as part of the Amtelco MergeComm POP3 trigger account configuration for inbound email
  • PowerShell 100%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Patrick Labbett ffd649557d Move tenant-specific values into git-ignored config.psd1
Add-POP3Account.ps1 and Audit-POP3Isolation.ps1 now read tenant domain,
tenant ID, and legacy app/group identifiers from config.psd1 via
Import-PowerShellDataFile. config.example.psd1 is the committed template.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 03:02:09 -04:00
.gitignore Move tenant-specific values into git-ignored config.psd1 2026-10-10 03:02:09 -04:00
Add-POP3Account.ps1 Move tenant-specific values into git-ignored config.psd1 2026-10-10 03:02:09 -04:00
Audit-POP3Isolation.ps1 Move tenant-specific values into git-ignored config.psd1 2026-10-10 03:02:09 -04:00
config.example.psd1 Move tenant-specific values into git-ignored config.psd1 2026-10-10 03:02:09 -04:00
mailboxes.example.txt Initial commit: POP3 isolation scripts, README, gitignored mailbox list 2026-10-10 02:58:51 -04:00
README.md Move tenant-specific values into git-ignored config.psd1 2026-10-10 03:02:09 -04:00

POP3 Mailbox Isolation for Amtelco

Scripts for giving each Amtelco POP3 client mailbox its own Entra ID app registration and an Exchange Online application access policy, so no app can read any mailbox except its own.

How the isolation works

Each mailbox gets three things:

Piece Where it lives Purpose
App registration (POP3-<name>) Entra ID (Azure Portal) Identity the POP3 client authenticates as. Holds the client ID and secret.
Mail-enabled security group (POP3-<name>) Exchange Online Contains exactly one member: the mailbox.
Application access policy Exchange Online RestrictAccess scoping the app ID to that group only.

Because every app is restricted to a group containing only its own mailbox, a compromised client ID and secret can only ever reach that one mailbox. The audit script proves this by testing every app against every mailbox and expecting Denied everywhere except the diagonal.

Files

File Purpose
Add-POP3Account.ps1 Add a single new mailbox (group + policy + verification). Day-to-day script.
Audit-POP3Isolation.ps1 Full audit. Produces an HTML report and CSVs in a timestamped POP3-Audit-* folder.
config.psd1 Tenant domain, tenant ID, and legacy app/group identifiers. Git-ignored.
config.example.psd1 Template for config.psd1.
mailboxes.txt List of mailboxes the audit checks. One per line. Git-ignored.
mailboxes.example.txt Template for mailboxes.txt.

Prerequisites

  • PowerShell 5.1 or later.
  • The ExchangeOnlineManagement module: Install-Module ExchangeOnlineManagement -Scope CurrentUser
  • An account with Exchange Administrator rights.
  • Rights to create app registrations and grant admin consent in Entra ID.

First-time setup after cloning

Copy-Item config.example.psd1 config.psd1
Copy-Item mailboxes.example.txt mailboxes.txt

Then edit config.psd1 with your tenant's values and mailboxes.txt with the real mailbox addresses, one per line. Both scripts refuse to run until config.psd1 exists.

Adding a new mailbox

1. Create the mailbox in Exchange Online

Create it in the Microsoft 365 admin center (or with New-Mailbox) and confirm it has a license and a primary SMTP address. The scripts do not create the mailbox.

2. Create a dedicated app registration in Entra ID

Every client gets its own app. This is what makes the isolation work.

  1. Entra ID > App registrations > New registration.
  2. Name it POP3-<clientname>. Single tenant. No redirect URI.
  3. API permissions > Add a permission > APIs my organization uses > search Office 365 Exchange Online > Application permissions > tick POP.AccessAsApp.
  4. Click Grant admin consent for the tenant.
  5. Certificates & secrets > New client secret. Copy the Value column immediately (not the Secret ID). It is only shown once.
  6. From Overview, copy the Application (client) ID.

3. Run the add script

.\Add-POP3Account.ps1 -Email "newclient@yourdomain.com" -ClientId "<client id from step 2>"

You will be prompted to sign in to Exchange Online. The script then:

  1. Creates a mail-enabled security group POP3-<name> containing only that mailbox.
  2. Creates an application access policy restricting the app ID to that group.
  3. Tests the policy against the new mailbox and against one other existing mailbox.

Expected result: Granted on its own mailbox, Denied on the other one.

4. Wait if the result is PENDING

Policies can take up to 30 minutes to propagate. Re-check with:

Test-ApplicationAccessPolicy -Identity "newclient@yourdomain.com" -AppId "<client id>"

5. Configure the POP3 client in Amtelco

You need the client ID, the secret value from step 2, the mailbox address, and the tenant ID. The tenant ID is printed at the end of the add script (it comes from config.psd1).

6. Add the mailbox to the audit list

Append the new address to mailboxes.txt on its own line. Without this the account will not appear in the next audit report.

7. Run the audit

.\Audit-POP3Isolation.ps1

This regenerates the HTML report and the cross-reference matrix that proves every app is denied on every mailbox except its own. The report opens automatically when complete. Output folders are git-ignored.

Removing a mailbox

  1. Delete the app registration in Entra ID (this revokes the secret immediately).
  2. Remove the policy and group in Exchange Online:
Get-ApplicationAccessPolicy | Where-Object { $_.AppId -eq "<client id>" } | Remove-ApplicationAccessPolicy -Confirm:$false
Remove-DistributionGroup -Identity "POP3-<name>" -Confirm:$false
  1. Remove the address from mailboxes.txt.

Notes

  • Tenant domain and tenant ID come from config.psd1. The add script also accepts -TenantDomain to override the configured domain for a single run.
  • Client secrets are never stored in this repo. Keep them in Amtelco's config and your password manager only.
  • The legacy shared app policy is left in place pointed at a POP3-Disabled group as a safety net. Its app registration has been deleted.