3using System.Net.Sockets;
 
    5using System.Threading.Tasks;
 
   15        private string domain;
 
   16        private bool expanded = 
false;
 
   26            if (
Term.PeekNextChar() == 
this.Separator)
 
   33                while ((ch = 
Term.PeekNextChar()) > 
' ' && ch != 
'/')
 
   36                this.domain = 
Term.s.Substring(Start, 
Term.pos - Start);
 
   39                throw new Exception(this.
Separator + 
" expected.");
 
   53            StringBuilder sb = 
new StringBuilder();
 
   56            while ((ch = this.
term.PeekNextChar()) > 
' ')
 
   62                    switch (ch = this.
term.PeekNextChar())
 
   86                            char MacroLetter = 
char.ToLower(this.
term.NextChar());
 
   90                            if (
char.IsDigit(this.
term.PeekNextChar()))
 
   92                                Digit = this.
term.NextInteger();
 
   95                                    throw new Exception(
"Invalid number of digits.");
 
  100                            if (
char.ToLower(this.
term.PeekNextChar()) == 
'r')
 
  108                            int Start = this.
term.pos;
 
  109                            while ((ch = this.
term.PeekNextChar()) == 
'.' || ch == 
'-' || ch == 
'+' ||
 
  110                                ch == 
',' || ch == 
'/' || ch == 
'_' || ch == 
'=')
 
  115                            string Delimiter = this.
term.s.Substring(Start, this.
term.pos - Start);
 
  117                            ch = this.
term.NextChar();
 
  119                                throw new Exception(
"Expected }");
 
  126                                    s = this.
term.sender;
 
  130                                    s = this.
term.sender;
 
  131                                    int i = s.IndexOf(
'@');
 
  135                                        s = s.Substring(0, i);
 
  139                                    s = this.
term.sender;
 
  142                                        s = s.Substring(i + 1);
 
  146                                    s = this.
term.domain;
 
  150                                    switch (this.
term.ip.AddressFamily)
 
  152                                        case AddressFamily.InterNetwork:
 
  153                                            s = this.
term.ip.ToString();
 
  156                                        case AddressFamily.InterNetworkV6:
 
  157                                            byte[] Bin = this.
term.ip.GetAddressBytes();
 
  159                                            StringBuilder sb2 = 
new StringBuilder();
 
  162                                            for (i = 0; i < 16; i++)
 
  168                                                    sb2.Append((
char)(
'0' + b2));
 
  170                                                    sb2.Append((
char)(
'a' + b2 - 10));
 
  176                                                    sb2.Append((
char)(
'0' + b2));
 
  178                                                    sb2.Append((
char)(
'a' + b2 - 10));
 
  188                                            throw new Exception(
"Invalid client address.");
 
  195                                        if (this.
term.dnsLookupsLeft-- <= 0)
 
  196                                            throw new Exception(
"DNS Lookup maximum reached.");
 
  203                                        foreach (
string DomainName 
in DomainNames)
 
  205                                            if (
string.Compare(DomainName, this.
term.domain, 
true) == 0 &&
 
  206                                                await 
this.MatchReverseIp(DomainName))
 
  217                                            foreach (
string DomainName 
in DomainNames)
 
  219                                                if (DomainName.EndsWith(
"." + 
this.term.domain, StringComparison.CurrentCultureIgnoreCase) &&
 
  220                                                    await 
this.MatchReverseIp(DomainName))
 
  229                                                if (DomainNames.Length == 0)
 
  236                                    catch (ArgumentException)
 
  240                                    catch (TimeoutException)
 
  247                                    switch (this.
term.ip.AddressFamily)
 
  249                                        case AddressFamily.InterNetwork:
 
  253                                        case AddressFamily.InterNetworkV6:
 
  258                                            throw new Exception(
"Invalid client address.");
 
  263                                    s = this.
term.helloDomain;
 
  268                                    s = this.
term.ip.ToString();
 
  273                                    s = this.
term.hostDomain;
 
  278                                    int Seconds = (int)Math.Round((DateTime.UtcNow - 
UnixEpoch).TotalSeconds);
 
  279                                    s = Seconds.ToString();
 
  283                                    throw new Exception(
"Unknown macro.");
 
  286                            if (Reverse || Digit.HasValue || !
string.IsNullOrEmpty(Delimiter))
 
  288                                if (
string.IsNullOrEmpty(Delimiter))
 
  291                                string[] Parts = s.Split(
new string[] { Delimiter }, StringSplitOptions.None);
 
  292                                int i = Parts.Length;
 
  295                                    Array.Reverse(Parts);
 
  297                                if (Digit.HasValue && Digit.Value < i)
 
  301                                int j = Parts.Length - i;
 
  310                                    sb.Append(Parts[j++]);
 
  328            this.domain = sb.ToString();
 
  331        internal async Task<bool> MatchReverseIp(
string DomainName)
 
  333            if (this.
term.dnsLookupsLeft-- <= 0)
 
  334                throw new Exception(
"DNS Lookup maximum reached.");
 
  336            IPAddress[] Addresses;
 
  338            switch (this.
term.ip.AddressFamily)
 
  340                case AddressFamily.InterNetwork:
 
  344                case AddressFamily.InterNetworkV6:
 
  349                    throw new Exception(
"Invalid client address.");
 
  352            string Temp = this.
term.ip.ToString();
 
  354            foreach (IPAddress Addr 
in Addresses)
 
  356                if (
string.Compare(Addr.ToString(), Temp, 
true) == 0)
 
  366        public static readonly DateTime 
UnixEpoch = 
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 
  368        private void AssertExp()
 
  371                throw new Exception(
"Macro only available in exp");
 
  392        public string TargetDomain => 
string.IsNullOrEmpty(this.domain) ? this.term.domain : this.domain;
 
DNS resolver, as defined in:
 
static async Task< string[]> LookupDomainName(IPAddress Address)
Looks up the domain name pointing to a specific IP address.
 
static async Task< IPAddress[]> LookupIP6Addresses(string DomainName)
Looks up the IPv6 addresses related to a given domain name.
 
static async Task< IPAddress[]> LookupIP4Addresses(string DomainName)
Looks up the IPv4 addresses related to a given domain name.
 
static int Next(int MaxValue)
Returns a non-negative random integer that is less than the specified maximum.
 
If check_host() results in a "fail" due to a mechanism match (such as "-all"), and the "exp" modifier...
 
Abstract base class for SPF mechanisms with a domain specification.
 
string Domain
Domain specification
 
MechanismDomainSpec(Term Term, SpfQualifier Qualifier)
Abstract base class for SPF mechanisms with a domain specification.
 
virtual char Separator
Mechanism separator
 
string TargetDomain
Target domain.
 
override async Task Expand()
Expands any macros in the domain specification.
 
static readonly DateTime UnixEpoch
UNIX Epoch, started at 1970-01-01, 00:00:00 (GMT)
 
virtual bool DomainRequired
If the domain specification is required.
 
Abstract base class for SPF Mechanisms.
 
readonly Term term
Current request.
 
SpfQualifier Qualifier
Mechanism qualifier
 
void Reset(string String)
Resets the string representation of the term.
 
SpfQualifier
SPF Mechanism qualifier