Back to Checks
m365

Mailbox primary SMTP address must use a custom domain

exchange_mailbox_primary_smtp_uses_custom_domain
Service: exchangeSeverity: low
OfficialBuilt-inVerified
Categories:email-security
Resource Type:NotDefined

Exchange Online mailboxes should use a custom domain as their primary SMTP address, not the default *.onmicrosoft.com routing domain assigned by Microsoft on tenant creation. This check verifies that the PrimarySmtpAddress of every user-facing mailbox does not end with .onmicrosoft.com.

Risk

Mailboxes still using .onmicrosoft.com as their primary SMTP address leak the internal tenant identifier in every From: header, helping attackers fingerprint the tenant for spear-phishing. They also bypass DMARC/DKIM hardening that organisations deploy on their custom domains and are frequently treated as low-trust by recipient anti-phishing engines.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler m365 --checks exchange_mailbox_primary_smtp_uses_custom_domain

Recommendation

Update the primary SMTP address of all affected mailboxes to use a custom domain. Ensure your custom domain is verified in the Microsoft 365 admin center before making this change.

Remediation

CLI

Get-Mailbox -ResultSize Unlimited | Where-Object { $_.PrimarySmtpAddress -like '*.onmicrosoft.com' } | ForEach-Object { Set-Mailbox -Identity $_.Identity -PrimarySmtpAddress '<user>@<customdomain.com>' }

Other

1Navigate to the Microsoft 365 admin center (https://admin.microsoft.com/)
2Go to Users > Active users and select the affected user
3Under the Aliases section, add the custom domain email address
4Set the custom domain address as the primary SMTP address
5Save changes and repeat for all affected mailboxes

Check Code

from typing import List

from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.exchange.exchange_client import exchange_client


class exchange_mailbox_primary_smtp_uses_custom_domain(Check):
    """
    Verify that every Exchange Online mailbox uses a custom domain as its
    primary SMTP address, not the default .onmicrosoft.com routing domain.

    The .onmicrosoft.com domain is assigned by Microsoft on tenant creation
    and is not intended for ongoing mail. Mailboxes still using it leak the
    internal tenant identifier in every From: header (aiding spear-phishing),
    bypass DMARC/DKIM hardening on custom domains and are often treated as
    low-trust by recipient anti-phishing engines.

    - PASS: Primary SMTP address does not use the .onmicrosoft.com domain.
    - FAIL: Primary SMTP address uses the .onmicrosoft.com domain.
    - MANUAL: Exchange Online PowerShell unavailable; check cannot run.
    """

    def execute(self) -> List[CheckReportM365]:
        """
        Execute the check against all recipient-facing Exchange Online mailboxes.

        Returns:
            List[CheckReportM365]: A report for each mailbox with its SMTP
                domain status, or a single MANUAL report if PowerShell was
                unavailable.
        """
        findings = []

        # mailboxes is None when Exchange Online PowerShell could not be
        # reached or the cmdlet raised. An empty list means PowerShell ran
        # but the tenant has no recipient-facing mailboxes (no findings).
        if exchange_client.mailboxes is None:
            report = CheckReportM365(
                metadata=self.metadata(),
                resource={},
                resource_name="Exchange Online Mailboxes",
                resource_id="exchange_mailboxes",
            )
            report.status = "MANUAL"
            report.status_extended = (
                "Exchange Online PowerShell is unavailable. "
                "Enable EXO PowerShell access to run this check."
            )
            findings.append(report)
            return findings

        for mailbox in exchange_client.mailboxes:
            report = CheckReportM365(
                metadata=self.metadata(),
                resource=mailbox,
                resource_name=mailbox.name or mailbox.identity,
                resource_id=mailbox.identity,
            )

            if mailbox.primary_smtp_address.endswith(".onmicrosoft.com"):
                report.status = "FAIL"
                report.status_extended = (
                    f"Mailbox {mailbox.identity} "
                    f"({mailbox.recipient_type_details}) has primary SMTP "
                    f"address {mailbox.primary_smtp_address} using the "
                    f".onmicrosoft.com domain instead of a custom domain."
                )
            else:
                report.status = "PASS"
                report.status_extended = (
                    f"Mailbox {mailbox.identity} "
                    f"({mailbox.recipient_type_details}) has primary SMTP "
                    f"address {mailbox.primary_smtp_address} using a "
                    f"custom domain."
                )

            findings.append(report)

        return findings