10

I am writing an application that is requiring me to do a DNS lookup for an MX record. I'm not sure if anyone has had experience doing this kind of work but if you do, any help would be appreciated.

EDIT: The thing that I'm going for is an application that will send an e-mail alert. The problem is I need to have the application be able to lookup the MX record for a domain.

JasonMArcher
  • 12,386
  • 20
  • 54
  • 51
Suroot
  • 4,155
  • 1
  • 19
  • 28
  • What is your actual question? It is a little diffuse at the moment. Also if you have code related to the the problem at hand, please provide it. – Skurmedel Jul 07 '09 at 16:39
  • Yea, sorry about that; I don't have code available at the moment as I'm trying to figure out how to write the code. Basically I'm trying to write an application to find the MX record. – Suroot Jul 07 '09 at 16:46
  • No problem. This might help you. http://tools.ietf.org/html/rfc1035 – Skurmedel Jul 07 '09 at 17:10
  • Thanks for the link, I know that I could do something like do a DGRAM send and then listen on DGRAM for the response but that would be a pain as I'd need to know the source port to listen on but seems like it might be the best choice if resolver(3) doesn't pan out. – Suroot Jul 07 '09 at 17:39
  • 53 is default for DNS. It could be another one, but it will work for the root DNS-servers. – Skurmedel Jul 07 '09 at 18:01
  • Thanks @Great Turtle ! To extend his answer, this code has to be compiled with the "-lresolv" flag – Math Jan 13 '17 at 16:00

5 Answers5

20

The simplest method is to simply use commonly available tools.

The basic "dig" command will return the records to you via this query:

dig mx example.com

If you want just the lines with the mx records...

dig mx example.com | grep -v '^;' | grep example.com

dig is available on most linux / unix boxes.

If you're on windows you can use nslookup

nslookup -type=mx example.com

Then just parse the output of these common tools.

EDIT: Simple C example of sockets from the web

Since you put "C" as a tag, I guess you're looking for source code to do MX lookups using raw sockets. I copied this from http://www.developerweb.net/forum/showthread.php?t=3550. It may be more what you're looking for?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <resolv.h>

int main (int argc, char *argv[])
{
    u_char nsbuf[4096];
    char dispbuf[4096];
    ns_msg msg;
    ns_rr rr;
    int i, j, l;

    if (argc < 2) {
        printf ("Usage: %s <domain>[...]\n", argv[0]);
        exit (1);
    }

    for (i = 1; i < argc; i++) {
        l = res_query (argv[i], ns_c_any, ns_t_mx, nsbuf, sizeof (nsbuf));
        if (l < 0) {
            perror (argv[i]);
        } else {
#ifdef USE_PQUERY
/* this will give lots of detailed info on the request and reply */
            res_pquery (&_res, nsbuf, l, stdout);
#else
/* just grab the MX answer info */
            ns_initparse (nsbuf, l, &msg);
            printf ("%s :\n", argv[i]);
            l = ns_msg_count (msg, ns_s_an);
            for (j = 0; j < l; j++) {
                ns_parserr (&msg, ns_s_an, j, &rr);
                ns_sprintrr (&msg, &rr, NULL, NULL, dispbuf, sizeof (dispbuf));
                printf ("%s\n", dispbuf);
            }
#endif
        }
    }

    exit (0);
}
Great Turtle
  • 3,215
  • 7
  • 29
  • 36
  • Sorry for the confusion, I'm trying to find the code that would be used in dig to find the MX record. I know that dig and nslookup exist, my thing is that I want to write an application that will do these lookups without an external application. – Suroot Jul 07 '09 at 16:47
  • You can download the source code for it here: https://www.isc.org/downloadables/11 – Greg Rogers Jul 07 '09 at 16:58
  • Thanks, the I'm checking out the code you had posted a bit ago, seems relatively close and more importantly the resolver(3) man page seems pretty useful there. – Suroot Jul 07 '09 at 17:37
  • I reverted to the answer that included the code since you thought it was useful. – Great Turtle Jul 09 '09 at 04:22
  • I know it's late :-), but I've had occasion to bump into this question in 2021. You may want to replace res_query with res_search. The latter will expand shortnames to the paths listed in the "search" entry in resolv.conf. – Mike S Jan 22 '21 at 20:13
1

I notice that you're writing for Linux. The idomatic way for a regular program to send mail on Unix-like systems is either:

  • Run /usr/bin/mail in a subprocess and send it the mail message on its standard input (see the mail manpage); or
  • Connect to 127.0.0.1:25 and give the local mail daemon the message to deliver.

Both ways presume that the local mailer is configured to pass mail on to where it has to go; on a well-configured Linux box this is a fair assumption.

If that doesn't appeal, the second-best way is for your program to accept the address of a local mail relay server to use, and just connect to that server on port 25.

In other words, wherever possible, use an existing mail relay to send your mail on. Those mail relays will have all the local knowledge that might be necessary to get mail out of the network that you're running on - just looking up the MX and trying to send directly to the destination is not always going to work.

If you've read all that and you still want to look up MX records, try the adns library, it takes care of all the tedious details involved in DNS resolution (and believe me, it is tedious, and easy to get wrong!).

caf
  • 216,678
  • 34
  • 284
  • 434
1

on linux:

host -t mx google.com
Patrick Hofman
  • 143,714
  • 19
  • 222
  • 294
kierzo
  • 103
  • 4
0

[Disclaimer: I used to be a happy beta tester of SnertSoft's stuff, and I'm still running several of their products]

Actually doing this by hand has its pitfalls, e.g. when you have to handle a truncated response and need to switch from UDP to TCP.

SnertSoft's libsnert (free, click-through-license required) already has a C implementation for this returning a vector of entries. Try to avoid "not-invented-here" if possible :)

Do you indeed have to reimplement an MTA instead of using some existing solution?

Volker Stolz
  • 6,914
  • 29
  • 47
0

Take a look at ldns, from NLnet Labs. This library handles low level packet handling and has its own resolver client built-in.

The documentation includes example code that does exactly what you require.

Alnitak
  • 313,276
  • 69
  • 379
  • 466