# Printing MX records with Go DNS, take 3


> I'm starting to get really happy about the Go DNS API, so invasive API changes are less and
> less likely.

We want to create a little program that prints out the MX records of domains, like so:

    % mx miek.nl
    miek.nl.        86400   IN      MX      10 elektron.atoom.net.

Or

    % mx microsoft.com
    microsoft.com.  3600    IN      MX      10 mail.messaging.microsoft.com.

We are using my [Go DNS package](https://github.com/miekg/dns).
First the normal header of a Go program, with a bunch of imports. We
need the `dns` package:

    package main

    import (
        "github.com/miekg/dns"
        "os"
        "net"
        "fmt"
        "log"
    )

Next we need to get the local nameserver to use:

    config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")

Then we create a `dns.Client` to perform the queries for us. In Go:

    c := new(dns.Client)

We skip some error handling and assume a zone name is given. So we prepare our
question. For that to work, we need:

1. a new packet (`dns.Msg`);
2. setting some header bits;
3. define a question section;
4. fill out the question section: `os.Args[1]` contains the zone name.

Which translates into:

    m := new(dns.Msg)
    m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
    m.RecursionDesired = true

Then we need to finally 'ask' the question. We
do this by calling the `Exchange()` function. The unused return value
is the `rtt` (round trip time).

    r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))

Check if we got something sane. The following code snippet prints
the answer section of the received packet:

Bail out on an error:

    if r == nil {
        log.Fatalf("*** error: %s\n", err.Error())
    }

    if r.Rcode != dns.RcodeSuccess {
            log.Fatalf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
    }

    // Stuff must be in the answer section
    for _, a := range r.Answer {
            fmt.Printf("%v\n", a)
    }

And we are done.

# Full Source

    package main

    import (
        "github.com/miekg/dns"
        "net"
        "os"
        "log"
        "fmt"
    )

    func main() {
        config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
        c := new(dns.Client)

        m := new(dns.Msg)
        m.SetQuestion(dns.Fqdn(os.Args[1]), dns.TypeMX)
        m.RecursionDesired = true

        r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
        if r == nil {
            log.Fatalf("*** error: %s\n", err.Error())
        }

        if r.Rcode != dns.RcodeSuccess {
                log.Fatalf(" *** invalid answer name %s after MX query for %s\n", os.Args[1], os.Args[1])
        }
        // Stuff must be in the answer section
        for _, a := range r.Answer {
                fmt.Printf("%v\n", a)
        }
    }

