2 Copyright (C) 2010-2014 MegaBrutal
4 This unit is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This unit is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 For reference, here are the C declarations of the used
25 functions and structures:
27 DNS_STATUS WINAPI DnsQuery(
28 __in PCTSTR lpstrName,
31 __inout_opt PVOID pExtra,
32 __out_opt PDNS_RECORD *ppQueryResultsSet,
33 __out_opt PVOID *pReserved
36 void WINAPI DnsRecordListFree(
37 __inout_opt PDNS_RECORD pRecordList,
38 __in DNS_FREE_TYPE FreeType
41 typedef struct _DnsRecord {
53 DNS_MX_DATA MX, Mx, AFSDB, Afsdb, RT, Rt;
55 } DNS_RECORD, *PDNS_RECORD;
61 } DNS_MX_DATA, *PDNS_MX_DATA;
66 uses SysUtils
, Classes
;
76 DnsMXData
= packed record
77 pNameExchange
: pWideChar
;
82 ppDnsRecord
= ^pDnsRecord
;
83 pDnsRecord
= ^DnsRecord
;
84 DnsRecord
= packed record
95 { Better to have a Pascal-format DnsMXData: }
101 TDNSMXRecordArray
= array of TDNSMXRecord
;
104 function DnsQuery(lsstrName
: PChar
; wType
: word; Options
: longword
;
105 pExtra
: pointer; ppQueryResultsSet
: ppDnsRecord
; pReserved
: pointer): longword
; stdcall;
106 external 'dnsapi.dll' name
'DnsQuery_A';
108 procedure DnsRecordListFree(pRecordList
: pDnsRecord
; FreeType
: word); stdcall;
109 external 'dnsapi.dll' name
'DnsRecordListFree';
112 function GetMXRecordArray(HostName
: string; var ResultArray
: TDNSMXRecordArray
): boolean;
113 procedure SortMXRecordArray(var DNSMXRecordArray
: TDNSMXRecordArray
);
114 function MakeMXRecordList(const DNSMXRecordArray
: TDNSMXRecordArray
): TStrings
;
115 function GetCorrectMXRecordList(HostName
: string): TStrings
;
122 function GetMXRecordArray(HostName
: string; var ResultArray
: TDNSMXRecordArray
): boolean;
123 var P
, N
: pDnsRecord
; DNSMXRecord
: TDNSMXRecord
; ap
: integer;
126 DnsQuery(PChar(HostName
), DNS_TYPE_MX
, 0, nil, @P
, nil);
128 while N
<> nil do begin
129 if N
^.wType
= DNS_TYPE_MX
then begin
130 DNSMXRecord
.Preference
:= N
^.Data
.wPreference
;
131 DNSMXRecord
.HostName
:= N
^.Data
.pNameExchange
;
132 ap
:= Length(ResultArray
);
133 SetLength(ResultArray
, ap
+ 1);
134 ResultArray
[ap
]:= DNSMXRecord
;
138 if P
<> nil then DnsRecordListFree(P
, 0);
139 Result
:= Length(ResultArray
) <> 0;
142 procedure SortMXRecordArray(var DNSMXRecordArray
: TDNSMXRecordArray
);
143 var i
, j
: integer; T
: TDNSMXRecord
;
145 for i
:= 1 to Length(DNSMXRecordArray
) - 1 do begin
146 T
:= DNSMXRecordArray
[i
];
148 while (j
> 0) and (DNSMXRecordArray
[j
-1].Preference
> T
.Preference
) do begin
149 DNSMXRecordArray
[j
]:= DNSMXRecordArray
[j
-1];
152 DNSMXRecordArray
[j
]:= T
;
156 function MakeMXRecordList(const DNSMXRecordArray
: TDNSMXRecordArray
): TStrings
;
159 Result
:= TStringList
.Create
;
160 for i
:= 0 to Length(DNSMXRecordArray
) - 1 do
161 Result
.Add(DNSMXRecordArray
[i
].HostName
);
164 function GetCorrectMXRecordList(HostName
: string): TStrings
;
165 var DNSMXRecordArray
: TDNSMXRecordArray
;
167 SetLength(DNSMXRecordArray
, 0);
168 if GetMXRecordArray(HostName
, DNSMXRecordArray
) then begin
169 SortMXRecordArray(DNSMXRecordArray
);
170 Result
:= MakeMXRecordList(DNSMXRecordArray
);
173 { If the domain has no MX record, the A record shall be used. }
174 Result
:= TStringList
.Create
;
175 Result
.Add(HostName
);