Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I want to check to see if the email addresses in my contact management system are valid and the best way I can think to do this is to get the MX record for their domain, then open an SMTP connection and see if the remote server accepts the email address as a valid "TO".

share|improve this question
    
I know everyone loves to script everything, but why not just use nslookup? –  joeqwerty Jul 27 '10 at 16:34
2  
'nslookup -type=MX domain.of.choice' will give it. But the output is a bit ugly. –  sysadmin1138 Jul 27 '10 at 16:46
    
Ugly is in the eye of the beholder ;) –  joeqwerty Jul 27 '10 at 16:56
1  
@joe parsing text programatically is downright evil, and if the output format of the tool you're using ever changes then chances are there goes your parsing script. Much better to have some kind of scripting framework that supports it. –  squillman Jul 27 '10 at 17:48
    
@joe: Why not just use nslookup? Frankly only because I am a developer and came to serverfault in complete ignorance. Thanks for pointing me to this tool. In this case, I am specifically looking for a PoSh script, but thanks for this info 'cause I won't have PowerShell everywhere I may need this information. (And I've parsed a whole lot of text results, so that's cool too.) Thanks, Joe! +1 –  Kevin Buchan Jul 29 '10 at 11:12

3 Answers 3

up vote 5 down vote accepted

Have a look at the Powershell Dig Cmdlet.

Using this you are able to do this:

PS> $allRecords = Get-Dns -Name mydomain.com -Type MX
PS> write-host $allRecords.RecordsMX

$allRecords is of type PoshNet.Dns.Response so you can read the properties on it to get your records.

Something else nice about this cmdlet is that you can have it return multiple types of records in a single query.

share|improve this answer
    
This looks so perfect. Thanks for the solution and also for pointing me to that cool website. +1 –  Kevin Buchan Jul 29 '10 at 11:14
function Get-DnsAddressList
{
    param(
        [parameter(Mandatory=$true)][Alias("Host")]
          [string]$HostName)

    try {
        return [System.Net.Dns]::GetHostEntry($HostName).AddressList
    }
    catch [System.Net.Sockets.SocketException] {
        if ($_.Exception.ErrorCode -ne 11001) {
            throw $_
        }
        return = @()
    }
}

function Get-DnsMXQuery
{
    param(
        [parameter(Mandatory=$true)]
          [string]$DomainName)

    if (-not $Script:global_dnsquery) {
        $Private:SourceCS = @'
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace PM.Dns {
  public class MXQuery {
    [DllImport("dnsapi", EntryPoint="DnsQuery_W", CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
    private static extern int DnsQuery(
        [MarshalAs(UnmanagedType.VBByRefStr)]
        ref string pszName, 
        ushort     wType, 
        uint       options, 
        IntPtr     aipServers, 
        ref IntPtr ppQueryResults, 
        IntPtr pReserved);

    [DllImport("dnsapi", CharSet=CharSet.Auto, SetLastError=true)]
    private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType);

    public static string[] Resolve(string domain)
    {
        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
            throw new NotSupportedException();

        List<string> list = new List<string>();

        IntPtr ptr1 = IntPtr.Zero;
        IntPtr ptr2 = IntPtr.Zero;
        int num1 = DnsQuery(ref domain, 15, 0, IntPtr.Zero, ref ptr1, IntPtr.Zero);
        if (num1 != 0)
            throw new Win32Exception(num1);
        try {
            MXRecord recMx;
            for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recMx.pNext) {
                recMx = (MXRecord)Marshal.PtrToStructure(ptr2, typeof(MXRecord));
                if (recMx.wType == 15)
                    list.Add(Marshal.PtrToStringAuto(recMx.pNameExchange));
            }
        }
        finally {
            DnsRecordListFree(ptr1, 0);
        }

        return list.ToArray();
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MXRecord
    {
        public IntPtr pNext;
        public string pName;
        public short  wType;
        public short  wDataLength;
        public int    flags;
        public int    dwTtl;
        public int    dwReserved;
        public IntPtr pNameExchange;
        public short  wPreference;
        public short  Pad;
    }
  }
}
'@

        Add-Type -TypeDefinition $Private:SourceCS -ErrorAction Stop
        $Script:global_dnsquery = $true
    }

    [PM.Dns.MXQuery]::Resolve($DomainName) | % {
        $rec = New-Object PSObject
        Add-Member -InputObject $rec -MemberType NoteProperty -Name "Host"        -Value $_
        Add-Member -InputObject $rec -MemberType NoteProperty -Name "AddressList" -Value $(Get-DnsAddressList $_)
        $rec
    }
}

Get-DnsMXQuery -DomainName "gmail.com"
share|improve this answer
    
Thanks for the code, Marian. Works like a champ. My solution is already in place, but you can bet I'm saving this code for the future! +1 –  Kevin Buchan Dec 12 '11 at 12:37

Get-WmiObject -Class MicrosoftDNS_MXType -Namespace root\microsoftdns -ComputerName DC1 -Filter "DomainName='domain.com.'"

share|improve this answer
    
I'm not sure what DC to use for this. I tried my firm's internal domain controllers, but got nothing back for "gmail.com" as the domain. –  Kevin Buchan Aug 2 '10 at 16:52
    
Try the one that authenticated your account. You can get it with: $env:LOGONSERVER. BTW dod you try: 'gmail.com.', notice the dot after the domain name. –  Shay Levy Aug 2 '10 at 19:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.