Skip to content

Setting up Microsoft 365 Journaling for Piler#

This documentation applies to Piler enterprise edition 2.1.0

Revision #1

Publication date: 2026-FEB-09

Microsoft 365 (Exchange Online) can be configured to send a copy of every email to Piler in real-time using journal transport rules. This is the recommended method for ongoing email archiving. For one-time migration of historical emails, see Import from Microsoft 365.

Overview#

There are two ways to archive M365 emails with Piler:

Method Use case How it works
Journaling (this guide) Ongoing real-time archiving M365 sends a copy of every email as it's sent/received
Graph API import One-time historical migration Script downloads existing emails via Microsoft Graph API

You can use both: import historical emails first, then enable journaling for everything going forward.

Prerequisites#

  • A running Piler instance with the SMTP daemon (piler-smtp) accessible on port 25
  • A Microsoft 365 tenant with Exchange Online
  • Exchange administrator role in your M365 tenant
  • DNS MX record for your journal domain pointing to the archive server

How it works#

Single-node deployment#

In a single-node setup, M365 delivers journal emails directly to piler-smtp. No separate MX relay is needed.

M365 tenant                    Archive server
┌──────────────┐              ┌────────────┐      ┌───────┐
│ Exchange     │── journal ──>│ piler-smtp │─────>│ Piler │
│ Online       │   (SMTP)     │ (port 25)  │      │       │
└──────────────┘              └────────────┘      └───────┘

Multi-node deployment#

If you run multiple worker nodes, an MX relay (e.g. postfix) distributes journal emails across them. See the postfix examples for a working setup.

M365 tenant                    Your infrastructure
┌──────────────┐              ┌─────────┐      ┌────────────────┐
│ Exchange     │── journal ──>│ Postfix │─────>│ piler-smtp (1) │
│ Online       │   (SMTP)     │ (MX)    │─────>│ piler-smtp (2) │
└──────────────┘              └─────────┘      └────────────────┘

When a user sends or receives an email in M365, the journal transport rule sends a BCC copy to your designated journal address (e.g. journal@archive.example.com). The piler-smtp daemon receives it, processes, and archives the email.

Step 1: DNS setup#

  1. Choose a journal recipient address, e.g. journal@archive.example.com

  2. Create a DNS MX record for archive.example.com pointing to your archive server (single-node) or your MX relay (multi-node)

Step 2: Create a journal transport rule in Exchange Online#

Using Exchange Admin Center (web UI)#

  1. Sign in to the Exchange Admin Center

  2. Go to Mail flow > Rules

  3. Click Add a rule > Create a new rule

  4. Configure the rule:

    • Name: Piler Email Archiving
    • Apply this rule if: [Apply to all messages] — select "The sender" > "is internal or external" > "Inside or outside the organization"
    • Do the following: Select "BCC the message to..." and enter your journal address, e.g. journal@archive.example.com
  5. Click Next, review the settings, and Save

  6. Make sure the rule is enabled (toggle it on if needed)

Using PowerShell#

If you prefer PowerShell, connect to Exchange Online and run:

Connect-ExchangeOnline

New-TransportRule -Name "Piler Email Archiving" `
  -FromScope "InOrganization" `
  -BccMessageTo "journal@archive.example.com"

New-TransportRule -Name "Piler Email Archiving Inbound" `
  -FromScope "NotInOrganization" `
  -SentToScope "InOrganization" `
  -BccMessageTo "journal@archive.example.com"

The first rule captures outbound and internal emails. The second rule captures inbound emails from external senders.

Step 3: Verify emails are being archived#

  1. Send a test email from an M365 mailbox to an external address (or between two M365 users)

  2. Wait 1-2 minutes for the journal rule to trigger

  3. Check the piler-smtp logs for the incoming message:

journalctl -u piler-smtp -f

You should see the journal email being received and processed.

  1. Log in to the Piler web UI and search for the test email. It should appear in the archive.

Multi-tenant setup (for MSPs)#

If you manage multiple M365 tenants with a multi-tenant Piler deployment, each tenant needs its own journal rule pointing to a tenant-specific address. The tenant-specific address is @archive.example.com.

Addressing scheme#

Use a per-tenant journal address, for example:

M365 tenant Journal address
Client A clienta@archive.example.com
Client B clientb@archive.example.com
Client C clientc@archive.example.com

Postfix routing#

Configure postfix to route each tenant's journal emails. All journal addresses go to the same piler-smtp instance — Piler handles tenant separation internally based on the recipient domains configured per tenant.

Per-tenant journal rules#

In each client's M365 tenant, create the transport rule (Step 2) using their specific journal address. This keeps each tenant's email stream identifiable.

Troubleshooting#

Emails not arriving in the archive#

  • Check DNS: Verify the MX record for your journal domain resolves correctly: dig MX archive.example.com
  • Check firewall: Ensure port 25 is open between M365 (outbound SMTP) and your archive server
  • Check piler-smtp logs: journalctl -u piler-smtp -f — look for incoming connections and processing
  • Check postfix logs (multi-node only): journalctl -u postfix -f — look for connection attempts from M365
  • M365 delivery delay: Journal rules may take a few minutes to activate after creation. Send another test email after 5-10 minutes.

Duplicate emails in the archive#

  • If you see duplicates, check that you don't have overlapping rules (e.g. both a BCC rule and a journal rule for the same scope)
  • Piler deduplicates by message-id, so exact duplicates are automatically handled. If you see near-duplicates, check your rule scope.

M365 connector / SPF issues#

If your server rejects journal emails from M365:

  • Ensure piler-smtp is configured to accept connections from M365's IP ranges
  • Or create an inbound connector in M365 that routes journal emails through a specific IP range you trust

Testing the SMTP path manually#

To verify piler-smtp is working independently of M365:

echo "Subject: test" | sendmail -f test@example.com journal@archive.example.com