PowerShell script for analyzing Exchange Online email headers

Source = 

https://github.com/directorcia/Office365/blob/master/email-header-report.ps1

Overview

The Email Header Report Tool is a PowerShell script that analyzes email headers to identify potential spam, phishing, and security concerns in messages processed by Exchange Online and Microsoft 365. This tool provides security administrators and email analysts with a comprehensive report of authentication results, spam filtering decisions, and other security-related information embedded in email headers.

Features

    • Authentication Analysis: Evaluates SPF, DKIM, and DMARC authentication results
    • Spam Filter Analysis: Examines SCL (Spam Confidence Level) and other spam indicators
    • Defender for Office 365 Analysis: Analyzes Safe Links and Safe Attachments processing results
    • Transport Rule Detection: Identifies if mail flow rules were applied to the message
    • Risk Assessment: Provides an overall verdict with color-coded risk indicators
    • Recommendations: Suggests appropriate actions based on analysis results

Requirements

    • PowerShell 5.0 or higher
    • Access to email headers from Exchange Online/Microsoft 365 environment
    • Windows with support for color console output (for optimal viewing experience)

Usage

.\email-header-report.ps1 -HeaderFilePath "C:\path\to\email_header.txt"

Parameters

Parameter Type Required Description
HeaderFilePath String Yes Path to the text file containing the raw email header

How to Extract Email Headers

From Outlook Desktop

    1. Open the email message
    2. Click File > Properties
    3. The headers appear in the “Internet headers” box
    4. Select all and copy to a text file

From Outlook Web App (OWA)

    1. Open the email message
    2. Click the three dots (⋯) in the top-right corner
    3. Select “View message details” or “View > Message details”
    4. Copy the headers to a text file

From Microsoft 365 Security Portal

    1. Navigate to the message in quarantine or Explorer view
    2. Select the message and view details
    3. Find and copy the headers to a text file

Understanding the Report

The report is divided into several sections:

Authentication Analysis

Shows the results of email authentication protocols:

    • SPF (Sender Policy Framework): Verifies if the sending server is authorized to send email for the domain
    • DKIM (DomainKeys Identified Mail): Validates the digital signature attached to the message
    • DMARC (Domain-based Message Authentication, Reporting, and Conformance): Evaluates alignment between the sender’s domain and the authenticated domain
    • CompAuth: Microsoft’s composite authentication result

Spam Filtering Analysis

Details how Exchange Online Protection and Microsoft 365 evaluated the message:

    • SCL (Spam Confidence Level): Score from -1 to 9 indicating spam probability
    • BCL (Bulk Complaint Level): Score from 0 to 9 for bulk email
    • Forefront Anti-Spam Report: Detailed anti-spam processing information
    • Delivery Destination: Where the message was delivered (Inbox, Junk, Quarantine, etc.)

Safe Attachments Analysis

Shows results from Defender for Office 365 attachment scanning:

    • CLEAN: No malicious content detected
    • BLOCK: Malicious content detected and blocked
    • REPLACE: Malicious attachment replaced with a placeholder
    • DYNAMICDELIVERY: Attachment analysis performed with temporary placeholder

Safe Links Analysis

Shows results from Defender for Office 365 URL scanning:

    • CLEAN: No malicious URLs detected
    • BLOCK: Malicious URLs detected and rewritten/blocked
    • PENDING: Analysis in progress
    • NOT SCANNED: URLs were not evaluated

General Message Analysis

Provides additional information about the message:

    • Originating IP: Source IP address of the sender
    • Message ID: Unique identifier for the message
    • Return-Path vs From: Compares the envelope sender with the display sender

Analysis Summary

Provides an overall verdict based on all factors:

    • HIGH RISK / SPAM DETECTED: Strong indicators of being spam or malicious
    • POTENTIAL RISK / LIKELY SPAM: Several characteristics of spam or unwanted mail
    • LIKELY LEGITIMATE: Message appears to be legitimate based on key checks
    • MIXED RESULTS / CAUTION ADVISED: Some checks passed, others raised concerns

Interpreting Key Values

SCL (Spam Confidence Level)

Value Meaning Typical Action
-1 Trusted sender Bypasses spam filtering
0-1 Not spam Delivered to inbox
2-4 Low spam probability Usually delivered to inbox
5-6 Spam Usually delivered to junk folder
7-9 High confidence spam Quarantined or rejected

Authentication Results

Result Meaning
Pass Authentication successful
Fail Authentication failed
SoftFail Weak failure (typically for SPF)
Neutral No policy assertion
None No policy found
PermError Permanent error in policy
TempError Temporary error during lookup

Examples

Legitimate Message Example

AUTHENTICATION ANALYSIS
-----------------------
  [SPF] PASS
  [DKIM] PASS
  [DMARC] PASS
  [Composite Auth (CompAuth)] PASS

EXCHANGE ONLINE SPAM FILTERING ANALYSIS
--------------------------------------
  [SCL (Spam Confidence Level)] 0 - Not spam (message determined to be clean by EOP content filter).
  
MESSAGE VERDICT:
──────────────────────────────────────────────────
  ✅ LIKELY LEGITIMATE
     This message appears to be legitimate based on key checks.
            

Spam Message Example

AUTHENTICATION ANALYSIS
-----------------------
  [SPF] FAIL
  [DKIM] FAIL
  [DMARC] FAIL
  [Composite Auth (CompAuth)] FAIL

EXCHANGE ONLINE SPAM FILTERING ANALYSIS
--------------------------------------
  [SCL (Spam Confidence Level)] 9 - Definite spam (highest confidence, typically quarantined or rejected).
  
MESSAGE VERDICT:
──────────────────────────────────────────────────
   HIGH RISK / SPAM DETECTED
     This message shows strong indicators of being spam or malicious.
            

Troubleshooting

Script Errors

    • Ensure you’re using PowerShell 5.0 or higher
    • Verify the header file exists and is readable
    • Check that the header file contains valid email headers

Missing Information

Some headers might not be present depending on:

    • Email routing path
    • Microsoft 365 subscription level
    • Security features enabled in your tenant
    • Age of the message (older messages might use different headers)

False Positives/Negatives

    • The tool analyzes only what’s present in the headers
    • It doesn’t re-evaluate the message content
    • Discrepancies may occur if policies changed after message delivery

Advanced Usage

Piping Output

You can redirect the output to a file:

.\email-header-report.ps1 -HeaderFilePath "C:\path\to\header.txt" > "report.txt"

Incorporating into Other Scripts

The script can be called from other PowerShell scripts or functions:

& "C:\path\to\email-header-report.ps1" -HeaderFilePath $headerPath

References

License

This script is provided as-is with no warranties. Use at your own risk.

Documentation for Email Header Report Tool v1.1

Author: CIAOPS

For updates and more information: GitHub Wiki

PowerShell script to report EntraID signin update

One the things that I have tasked myself with is to go back through my scripts and using AI (aka Github Copilot) to improve my code.

Screenshot 2025-04-18 095201

The latest script to get this treatment is:

https://github.com/directorcia/Office365/blob/master/graph-signins-get.ps1

which now has greater flexibility and speed. I also used Copilot to produce documentation for the script which is here:

https://github.com/directorcia/Office365/wiki/Get-tenant-signins

In my Visual Studio Code editor what I did was simply to open up the script.

Screenshot 2025-04-18 100356

I then set Copilot to operate in ‘agent’ mode, as shown above. I also selected an AI model to use. I have the default choices of:

Screenshot 2025-04-18 100555

I can also configure others like Gemini if I want. This time I selected Claude 3.7 and then basically told Copilot to ‘improve’ my code. After that I asked it to provide options for using paging to get more results as well as ensuring the output was in local time.

After one update to the time format it produced an error when it ran but I simply told Copilot to fix that error and it did so. The code once again executed.

Thus, the updated script and documentation is now available via the links above and I am amazed at how easy it was to make all these changes to get the result that I wanted without having to type any additional code myself into the script! I suppose he downside is that the code is more complex and I don’t intrinsically understand it as well as if I had written every line, but I have Copilot to help explain any part of the code to me if needed and the time savings getting to a result speak for themselves.

The functionality that AI provided for me via Github Copilot is enormous and should make short work of any PowerShell automation I do in the future. If you are using PowerShell (or any code) then you really need to be looking at the benefits AI will provide you.

Script to delete old installed PowerShell module versions

image

A while ago I wrote a script that report all the previous versions of PowerShell modules that have been installed.

https://blog.ciaops.com/2025/03/28/report-installed-powershell-module-versions/

I’ve now done a script that will allow yoru to delete all these previous versions while retaining the current version. You’ll find that script here:

https://github.com/directorcia/Office365/blob/master/psmodules-del.ps1

# Example usage:
# Remove-OldPSModules                                                  # Process all modules without confirmation
# Remove-OldPSModules -SummaryOnly                                     # Only show summary info, minimize verbose output
# Remove-OldPSModules -ModuleNames “Microsoft.Graph”, “Az”            # Process specific modules
# Remove-OldPSModules -ConfirmUninstall                               # Ask before each removal
# Remove-OldPSModules -WhatIf                                         # Simulation mode, no actual changes
# Remove-OldPSModules -ModuleNames “Az” -ConfirmUninstall -WhatIf     # Combine parameters as needed

You can modify the execution part of the script at the bottom to suit your needs.

Updated Defender for Endpoint Security Baseline

image

Microsoft has updated the Defender for Endpoint Security Baseline policy in Intune to Version 24H1 as shown above.

I have managed to extract my own best practice JSON configuration file for this policy and make it available at:

https://github.com/directorcia/bp/blob/main/Intune/Policies/Endpoint/Baselines/dep.json

which means you can import this directly into your environment programmatically (I used PowerShell to do exactly this).

The updates to this policy are huge! The previous version config file was about 350 lines, this new 24H1 version is now about 2,300 lines long! This indicated to me that Microsoft is moving more and more settings into theses baselines.

Script to report tenant directory activity

image

I have created a script that uses the Microsoft Graph to report directory activity for the tenant as shown above. You’ll find it here:

https://github.com/directorcia/Office365/blob/master/graph-diraudit-get.ps1

along with the documentation here:

https://github.com/directorcia/Office365/wiki/Report-directory-activity-in-a-tenant

You will need to have the Microsoft Graph PowerShell module installed and up to date.

The first time you run the script you maybe prompted to login to your tenant and then you may also be asked to provide permissions This script requires:

AuditLog.Read.All
Directory.Read.All

which you may need to consent to the first time.

After the script executes you should see an output as shown above showing the logging service, activity, result, operation, category and time stamp.

You can also use the –csv command line option to put the results to a CSV file in the parent directory.

Script to report tenant signins

image

I have created a script that uses the Microsoft Graph to report signins for the tenant as shown above. You’ll find it here:

https://github.com/directorcia/Office365/blob/master/graph-signins-get.ps1

along with the documentation here:

https://github.com/directorcia/Office365/wiki/Get-tenant-signins

You will need to have the Microsoft Graph PowerShell module installed and up to date.

The first time you run the script you maybe prompted to login to your tenant and then you may also be asked to provide permissions This script requires:

AuditLog.Read.All
Directory.Read.All

which you may need to consent to the first time.

After the script executes you should see an output as shown above showing the Client App used, IP Address, is an interactive login and the user principal name.

You can also use the –csv command line option to put the results to a CSV file in the parent directory.