What are the ways to Check SPF records on a domain?
There is a website where i can do it manually using - http://www.mxtoolbox.com/SuperTool.aspx
How can i do it via ASP.NET and C#? Basically i want to verify/check SPF records on a domain if its supporting out own mail web server.
What is the SPF lookup for? With the SPF lookup you analyze the SPF record of a domain for errors, security risks and authorized IP addresses. Optionally, you can specify an IP address to check if it is authorized to send e-mail on behalf of the domain. The SPF lookup analyzes registered TXT records in real time.
All domains, regardless if they send email, should include a Sender Policy Framework (SPF) record. SPF is a widely adopted mechanism that identifies legitimate sending IP addresses and is taken into account by mailbox providers when treating received email.
I have the same problem, and managed to find two three solutions:
nslookup
solutionYou can get the SPF by typing the following command in the command line:
nslookup -type=TXT <hostname>
You can automate this in C# using System.Diagonstics.Process
, as described in this blog post.
I found this CodeProject article about DNS resolution. It comes with demo project. I ran the project and got the following result for stackexchange.com
:
Note: Make sure that the QType field is set to TXT before you press the Send button
The section highlighted in yellow represents the SPF record. I haven't yet dug into the code to see how it's done, but this seems like a good alternative to the nslookup
solution above.
If all you need to do is check whether a domain supports a mail server, you can use the ARSoft.Tools.Net library (also available as a NuGet Package).
After installing the package, I managed to perform the SPF check with this code:
var spfValidator = new ARSoft.Tools.Net.Spf.SpfValidator();
var mailIpAddress = IPAddress.Parse("X.X.X.X");
var domain = "example.com";
var senderAddress = "[email protected]";
ARSoft.Tools.Net.Spf.SpfQualifier result =
spfValidator.CheckHost(mailIpAddress, domain, senderAddress);
Even though .NET has a lot of support for networking including doing host name to address mapping it lacks a general way to query DNS.
However, you can use P/Invoke to call the DnsQuery function directly. The API is somewhat cumbersome but it is not impossible to create the correct P/Invoke signature for your requirement.
A SPF record is stored as a TXT record in DNS. The corresponding structure you will have to work with is the DNS_TXT_DATA structure. If you can find an example of querying a MX record you can reuse the code and use DNS_TYPE_TEXT
for the query type and unmarshal the data to a DNS_TXT_DATA
structure.
Or you could just use this code:
using System.ComponentModel;
using System.Runtime.InteropServices;
public String DnsGetTxtRecord(String name) {
const Int16 DNS_TYPE_TEXT = 0x0010;
const Int32 DNS_QUERY_STANDARD = 0x00000000;
const Int32 DNS_ERROR_RCODE_NAME_ERROR = 9003;
const Int32 DNS_INFO_NO_RECORDS = 9501;
var queryResultsSet = IntPtr.Zero;
try {
var dnsStatus = DnsQuery(
name,
DNS_TYPE_TEXT,
DNS_QUERY_STANDARD,
IntPtr.Zero,
ref queryResultsSet,
IntPtr.Zero
);
if (dnsStatus == DNS_ERROR_RCODE_NAME_ERROR || dnsStatus == DNS_INFO_NO_RECORDS)
return null;
if (dnsStatus != 0)
throw new Win32Exception(dnsStatus);
DnsRecordTxt dnsRecord;
for (var pointer = queryResultsSet; pointer != IntPtr.Zero; pointer = dnsRecord.pNext) {
dnsRecord = (DnsRecordTxt) Marshal.PtrToStructure(pointer, typeof(DnsRecordTxt));
if (dnsRecord.wType == DNS_TYPE_TEXT) {
var lines = new List<String>();
var stringArrayPointer = pointer
+ Marshal.OffsetOf(typeof(DnsRecordTxt), "pStringArray").ToInt32();
for (var i = 0; i < dnsRecord.dwStringCount; ++i) {
var stringPointer = (IntPtr) Marshal.PtrToStructure(stringArrayPointer, typeof(IntPtr));
lines.Add(Marshal.PtrToStringUni(stringPointer));
stringArrayPointer += IntPtr.Size;
}
return String.Join(Environment.NewLine, lines);
}
}
return null;
}
finally {
const Int32 DnsFreeRecordList = 1;
if (queryResultsSet != IntPtr.Zero)
DnsRecordListFree(queryResultsSet, DnsFreeRecordList);
}
}
[DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
static extern Int32 DnsQuery(String lpstrName, Int16 wType, Int32 options, IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved);
[DllImport("Dnsapi.dll")]
static extern void DnsRecordListFree(IntPtr pRecordList, Int32 freeType);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct DnsRecordTxt {
public IntPtr pNext;
public String pName;
public Int16 wType;
public Int16 wDataLength;
public Int32 flags;
public Int32 dwTtl;
public Int32 dwReserved;
public Int32 dwStringCount;
public String pStringArray;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With