Retrieve Email DNS records using PowerShell

I have been doing a lot of Exchange on-prem to Exchange Online migrations over the last few years, and because of that, I use mxtoolbox.com a lot for querying MX, SPF, DMARC, and DKIM records. Wouldn’t getting a simple overview of those records in a PowerShell function be convenient? This blog post will show you how 🙂

How it works

PowerShell has a built-in cmdlet for retrieving DNS records, Resolve-DnsName. With this, you can query records and specify what DNS server to connect to and what type of record (A, CNAME, MX, NS, etc.) to retrieve. The function Get-MailDomainInfo that I made uses this cmdlet and shows you the information you need to get a good overview of the servers and options used for one or more domains. By default, it connects to the 1.1.1.1 (CloudFlare) DNS server, but you can specify another one using the -DNSServer parameter.

Example output

In the screenshot below, the output is shown for microsoft.com:

If you specify a domain that can’t be found, it will show an error message:

If the domain does exist but does not have all records or services configured… It will return ‘Not enabled’ for those. In this example, for my domain, it returns the Domain Name, the autodiscover, SPF (Including the values from Include statements, if any), DMARC, and the DKIM records. (I used the -DNSserver parameter here to specify another DNS server in this example.)

Note: You can specify multiple domains with a comma as a separator. Get-MailDomainInfo -DomainName powershellisfun.com, microsoft.com will return info for both domains.

The script

Below is the contents of the script. you can save it to c:\data, for example, and use it as a function in all your PowerShell sessions by adding it to your profile:

- Notepad $profile
- Add ". c:\data\Get-MailDomainInfo.ps1"
- Quit/Save and start a new PowerShell session

You can also run it in your PowerShell session, as mentioned below.

Afterward, you can use Get-MailDomainInfo -DomainName Microsoft.com, for example.

function Get-MailDomainInfo {
    param(
        [parameter(Mandatory = $true)][string[]]$DomainName,
        [parameter(Mandatory = $false)][string]$DNSserver = '1.1.1.1'
    )
     
    $info = foreach ($domain in $DomainName) {
        
        #Check if domain name is valid, output warning it not and continue to the next domain (if any)
        try {
            Resolve-DnsName -Name $domain -Server $DNSserver -ErrorAction Stop | Out-Null

            #Retrieve all mail DNS records
            $autodiscoverA = (Resolve-DnsName -Name "autodiscover.$($domain)" -Type A -Server $DNSserver -ErrorAction SilentlyContinue).IPAddress
            $autodiscoverCNAME = (Resolve-DnsName -Name "autodiscover.$($domain)" -Type CNAME -Server $DNSserver -ErrorAction SilentlyContinue).NameHost
            $dkim1 = Resolve-DnsName -Name "selector1._domainkey.$($domain)" -Type CNAME -Server $DNSserver -ErrorAction SilentlyContinue
            $dkim2 = Resolve-DnsName -Name "selector2._domainkey.$($domain)" -Type CNAME -Server $DNSserver -ErrorAction SilentlyContinue
            $dmarc = (Resolve-DnsName -Name "_dmarc.$($domain)" -Type TXT -Server $DNSserver -ErrorAction SilentlyContinue | Where-Object Strings -Match 'DMARC').Strings
            $mx = (Resolve-DnsName -Name $domain -Type MX -Server $DNSserver -ErrorAction SilentlyContinue).NameExchange
            $spf = (Resolve-DnsName -Name $domain -Type TXT -Server $DNSserver -ErrorAction SilentlyContinue | Where-Object Strings -Match 'v=spf').Strings
            $includes = (Resolve-DnsName -Name $domain -Type TXT -Server $DNSserver -ErrorAction SilentlyContinue | Where-Object Strings -Match 'v=spf').Strings -split ' ' | Select-String 'Include:'
 
            #Set variables to Not enabled or found if they can't be retrieved
            $errorfinding = 'Not enabled'
           
 
            if ($null -eq $dkim1 -and $null -eq $dkim2) {
                $dkim = $errorfinding
            }
            else {
                $dkim = "$($dkim1.Name) , $($dkim2.Name)"
            }
 
            if ($null -eq $dmarc) {
                $dmarc = $errorfinding
            }
 
            if ($null -eq $mx) {
                $mx = $errorfinding
            }
 
            if ($null -eq $spf) {
                $spf = $errorfinding
            }

            if ($null -eq $autodiscoverCNAME) {
                $autodiscoverCNAME = $errorfinding
            }

            if (($autodiscoverA).count -gt 1 -or $null -ne $autodiscoverCNAME) {
                $autodiscoverA = $errorfinding
            }

            if ($null -eq $includes) {
                $includes = $errorfinding
            }
            else {
                $foundincludes = foreach ($include in $includes) {
                    if ((Resolve-DnsName -Server $DNSserver -Name $include.ToString().Split(':')[1] -Type txt -ErrorAction SilentlyContinue).Strings) {
                        [PSCustomObject]@{
                            SPFIncludes = "$($include.ToString().Split(':')[1]) : " + $(Resolve-DnsName -Server $DNSserver -Name $include.ToString().Split(':')[1] -Type txt).Strings
                        }
                    }
                    else {
                        [PSCustomObject]@{
                            SPFIncludes = $errorfinding
                        }
                    }
                }
            }
 
            [PSCustomObject]@{
                'Domain Name'             = $domain
                'Autodiscover IP-Address' = $autodiscoverA
                'Autodiscover CNAME '     = $autodiscoverCNAME
                'DKIM Record'             = $dkim
                'DMARC Record'            = "$($dmarc)"
                'MX Record(s)'            = $mx -join ', '
                'SPF Record'              = "$($spf)"
                'SPF Include values'      = "$($foundincludes.SPFIncludes)" -replace "all", "all`n`b"
            }
        }
        catch {
            Write-Warning ("{0} not found" -f $domain)
        }     
    }
    return $info 
}

Download the script(s) from GitHub here

3 thoughts on “Retrieve Email DNS records using PowerShell

  1. Pingback: PowerShell is fun :)PowerShell Profile

  2. Hello,

    Nice script, maybe I am missing something, but it didn’t return any information.

    Please advise.
    Thanks

    • It’s a Function, if you run it… Then it becomes available in your session (PowerShell prompt, ISE or VSCode) So, you can run it from powershell.exe of pwsh.exe by “. c:\scripts\get-MailDomainInfo.ps1), for example. Then you can use Get-MailDomainInfo and use the function like described in the blog post.

      I updated this blog post to explain it better, my bad!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.