Esempio n. 1
0
		internal static bool TryParse(string s, out SpfTerm value)
		{
			if (String.IsNullOrEmpty(s))
			{
				value = null;
				return false;
			}

			#region Parse Mechanism
			Regex regex = new Regex(@"^(\s)*(?<qualifier>[~+?-]?)(?<type>[a-z0-9]+)(:(?<domain>[^/]+))?(/(?<prefix>[0-9]+)(/(?<prefix6>[0-9]+))?)?(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
			Match match = regex.Match(s);
			if (match.Success)
			{
				SpfMechanism mechanism = new SpfMechanism();

				switch (match.Groups["qualifier"].Value)
				{
					case "+":
						mechanism.Qualifier = SpfQualifier.Pass;
						break;
					case "-":
						mechanism.Qualifier = SpfQualifier.Fail;
						break;
					case "~":
						mechanism.Qualifier = SpfQualifier.SoftFail;
						break;
					case "?":
						mechanism.Qualifier = SpfQualifier.Neutral;
						break;

					default:
						mechanism.Qualifier = SpfQualifier.Pass;
						break;
				}

				SpfMechanismType type;
				mechanism.Type = EnumHelper<SpfMechanismType>.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfMechanismType.Unknown;

				mechanism.Domain = match.Groups["domain"].Value;

				string tmpPrefix = match.Groups["prefix"].Value;
				int prefix;
				if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
				{
					mechanism.Prefix = prefix;
				}

				tmpPrefix = match.Groups["prefix6"].Value;
				if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
				{
					mechanism.Prefix6 = prefix;
				}

				value = mechanism;
				return true;
			}
			#endregion

			#region Parse Modifier
			regex = new Regex(@"^(\s)*(?<type>[a-z]+)=(?<domain>[^\s]+)(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
			match = regex.Match(s);
			if (match.Success)
			{
				SpfModifier modifier = new SpfModifier();

				SpfModifierType type;
				modifier.Type = EnumHelper<SpfModifierType>.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfModifierType.Unknown;
				modifier.Domain = match.Groups["domain"].Value;

				value = modifier;
				return true;
			}
			#endregion

			value = null;
			return false;
		}
        private async Task <SpfQualifier> CheckMechanismAsync(SpfMechanism mechanism, IPAddress ip, DomainName domain, string sender, State state, CancellationToken token)
        {
            switch (mechanism.Type)
            {
            case SpfMechanismType.All:
                return(mechanism.Qualifier);

            case SpfMechanismType.A:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DomainName aMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                bool?isAMatch = await IsIpMatchAsync(aMechanismDomain, ip, mechanism.Prefix, mechanism.Prefix6, token);

                if (!isAMatch.HasValue)
                {
                    return(SpfQualifier.TempError);
                }

                if (isAMatch.Value)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Mx:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DomainName mxMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                DnsResolveResult <MxRecord> dnsMxResult = await ResolveDnsAsync <MxRecord>(mxMechanismDomain, RecordType.Mx, token);

                if ((dnsMxResult == null) || ((dnsMxResult.ReturnCode != ReturnCode.NoError) && (dnsMxResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                int mxCheckedCount = 0;

                foreach (MxRecord mxRecord in dnsMxResult.Records)
                {
                    if (++mxCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isMxMatch = await IsIpMatchAsync(mxRecord.ExchangeDomainName, ip, mechanism.Prefix, mechanism.Prefix6, token);

                    if (!isMxMatch.HasValue)
                    {
                        return(SpfQualifier.TempError);
                    }

                    if (isMxMatch.Value)
                    {
                        return(mechanism.Qualifier);
                    }
                }
                break;

            case SpfMechanismType.Ip4:
            case SpfMechanismType.Ip6:
                IPAddress compareAddress;
                if (IPAddress.TryParse(mechanism.Domain, out compareAddress))
                {
                    if (ip.AddressFamily != compareAddress.AddressFamily)
                    {
                        return(SpfQualifier.None);
                    }

                    if (mechanism.Prefix.HasValue)
                    {
                        if ((mechanism.Prefix.Value < 0) || (mechanism.Prefix.Value > (compareAddress.AddressFamily == AddressFamily.InterNetworkV6 ? 128 : 32)))
                        {
                            return(SpfQualifier.PermError);
                        }

                        if (ip.GetNetworkAddress(mechanism.Prefix.Value).Equals(compareAddress.GetNetworkAddress(mechanism.Prefix.Value)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                    else if (ip.Equals(compareAddress))
                    {
                        return(mechanism.Qualifier);
                    }
                }
                else
                {
                    return(SpfQualifier.PermError);
                }

                break;

            case SpfMechanismType.Ptr:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                DnsResolveResult <PtrRecord> dnsPtrResult = await ResolveDnsAsync <PtrRecord>(ip.GetReverseLookupDomain(), RecordType.Ptr, token);

                if ((dnsPtrResult == null) || ((dnsPtrResult.ReturnCode != ReturnCode.NoError) && (dnsPtrResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                DomainName ptrMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                int ptrCheckedCount = 0;
                foreach (PtrRecord ptrRecord in dnsPtrResult.Records)
                {
                    if (++ptrCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isPtrMatch = await IsIpMatchAsync(ptrRecord.PointerDomainName, ip, 0, 0, token);

                    if (isPtrMatch.HasValue && isPtrMatch.Value)
                    {
                        if (ptrRecord.PointerDomainName.Equals(ptrMechanismDomain) || (ptrRecord.PointerDomainName.IsSubDomainOf(ptrMechanismDomain)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                }
                break;

            case SpfMechanismType.Exist:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                if (String.IsNullOrEmpty(mechanism.Domain))
                {
                    return(SpfQualifier.PermError);
                }

                DomainName existsMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                DnsResolveResult <ARecord> dnsAResult = await ResolveDnsAsync <ARecord>(existsMechanismDomain, RecordType.A, token);

                if ((dnsAResult == null) || ((dnsAResult.ReturnCode != ReturnCode.NoError) && (dnsAResult.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                if (dnsAResult.Records.Count(record => (record.RecordType == RecordType.A)) > 0)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Include:
                if (++state.DnsLookupCount > 10)
                {
                    return(SpfQualifier.PermError);
                }

                if (String.IsNullOrEmpty(mechanism.Domain))
                {
                    return(SpfQualifier.PermError);
                }

                DomainName includeMechanismDomain = String.IsNullOrEmpty(mechanism.Domain) ? domain : await ExpandDomainAsync(mechanism.Domain, ip, domain, sender, token);

                if (includeMechanismDomain.Equals(domain))
                {
                    return(SpfQualifier.PermError);
                }

                var includeResult = await CheckHostInternalAsync(ip, includeMechanismDomain, sender, false, state, token);

                switch (includeResult.Result)
                {
                case SpfQualifier.Pass:
                    return(mechanism.Qualifier);

                case SpfQualifier.Fail:
                case SpfQualifier.SoftFail:
                case SpfQualifier.Neutral:
                    return(SpfQualifier.None);

                case SpfQualifier.TempError:
                    return(SpfQualifier.TempError);

                case SpfQualifier.PermError:
                case SpfQualifier.None:
                    return(SpfQualifier.PermError);
                }
                break;

            default:
                return(SpfQualifier.PermError);
            }

            return(SpfQualifier.None);
        }
Esempio n. 3
0
        internal static bool TryParse(string s, out SpfTerm value)
        {
            if (String.IsNullOrEmpty(s))
            {
                value = null;
                return(false);
            }

            #region Parse Mechanism
            Match match = _parseMechanismRegex.Match(s);
            if (match.Success)
            {
                SpfMechanism mechanism = new SpfMechanism();

                switch (match.Groups["qualifier"].Value)
                {
                case "+":
                    mechanism.Qualifier = SpfQualifier.Pass;
                    break;

                case "-":
                    mechanism.Qualifier = SpfQualifier.Fail;
                    break;

                case "~":
                    mechanism.Qualifier = SpfQualifier.SoftFail;
                    break;

                case "?":
                    mechanism.Qualifier = SpfQualifier.Neutral;
                    break;

                default:
                    mechanism.Qualifier = SpfQualifier.Pass;
                    break;
                }

                SpfMechanismType type;
                mechanism.Type = EnumHelper <SpfMechanismType> .TryParse(match.Groups["type"].Value, true, out type) ? type : SpfMechanismType.Unknown;

                mechanism.Domain = match.Groups["domain"].Value;

                string tmpPrefix = match.Groups["prefix"].Value;
                int    prefix;
                if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
                {
                    mechanism.Prefix = prefix;
                }

                tmpPrefix = match.Groups["prefix6"].Value;
                if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
                {
                    mechanism.Prefix6 = prefix;
                }

                value = mechanism;
                return(true);
            }
            #endregion

            #region Parse Modifier
            match = _parseModifierRegex.Match(s);
            if (match.Success)
            {
                SpfModifier modifier = new SpfModifier();

                SpfModifierType type;
                modifier.Type = EnumHelper <SpfModifierType> .TryParse(match.Groups["type"].Value, true, out type) ? type : SpfModifierType.Unknown;

                modifier.Domain = match.Groups["domain"].Value;

                value = modifier;
                return(true);
            }
            #endregion

            value = null;
            return(false);
        }
Esempio n. 4
0
        private SpfQualifier CheckMechanism(SpfMechanism mechanism, IPAddress ip, string sender, string domain)
        {
            DnsMessage dnsMessage;

            switch (mechanism.Type)
            {
            case SpfMechanismType.All:
                return(mechanism.Qualifier);

            case SpfMechanismType.A:
                bool?isAMatch = IsIpMatch(String.IsNullOrEmpty(mechanism.Domain) ? domain : mechanism.Domain, ip, mechanism.Prefix, mechanism.Prefix6);
                if (!isAMatch.HasValue)
                {
                    return(SpfQualifier.TempError);
                }

                if (isAMatch.Value)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Mx:
                dnsMessage = ResolveDns(ExpandDomain(String.IsNullOrEmpty(mechanism.Domain) ? domain : mechanism.Domain, ip, sender, domain), RecordType.Mx);
                if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                int mxCheckedCount = 0;

                foreach (MxRecord mxRecord in dnsMessage.AnswerRecords.OfType <MxRecord>())
                {
                    if (++mxCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isMxMatch = IsIpMatch(mxRecord.ExchangeDomainName, ip, mechanism.Prefix, mechanism.Prefix6);
                    if (!isMxMatch.HasValue)
                    {
                        return(SpfQualifier.TempError);
                    }

                    if (isMxMatch.Value)
                    {
                        return(mechanism.Qualifier);
                    }
                }
                break;

            case SpfMechanismType.Ip4:
            case SpfMechanismType.Ip6:
                IPAddress compareAddress;
                if (IPAddress.TryParse(mechanism.Domain, out compareAddress))
                {
                    if (ip.AddressFamily != compareAddress.AddressFamily)
                    {
                        return(SpfQualifier.None);
                    }

                    if (mechanism.Prefix.HasValue)
                    {
                        if ((mechanism.Prefix.Value < 0) || (mechanism.Prefix.Value > (compareAddress.AddressFamily == AddressFamily.InterNetworkV6 ? 128 : 32)))
                        {
                            return(SpfQualifier.PermError);
                        }

                        if (ip.GetNetworkAddress(mechanism.Prefix.Value).Equals(compareAddress.GetNetworkAddress(mechanism.Prefix.Value)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                    else if (ip.Equals(compareAddress))
                    {
                        return(mechanism.Qualifier);
                    }
                }
                else
                {
                    return(SpfQualifier.PermError);
                }

                break;

            case SpfMechanismType.Ptr:
                dnsMessage = ResolveDns(ip.GetReverseLookupAddress(), RecordType.Ptr);
                if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                string ptrCompareName = String.IsNullOrEmpty(mechanism.Domain) ? domain : mechanism.Domain;

                int ptrCheckedCount = 0;
                foreach (PtrRecord ptrRecord in dnsMessage.AnswerRecords.OfType <PtrRecord>())
                {
                    if (++ptrCheckedCount == 10)
                    {
                        break;
                    }

                    bool?isPtrMatch = IsIpMatch(ptrRecord.PointerDomainName, ip, 0, 0);
                    if (isPtrMatch.HasValue && isPtrMatch.Value)
                    {
                        if (ptrRecord.PointerDomainName.Equals(ptrCompareName, StringComparison.InvariantCultureIgnoreCase) || (ptrRecord.PointerDomainName.EndsWith("." + ptrCompareName, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            return(mechanism.Qualifier);
                        }
                    }
                }
                break;

            case SpfMechanismType.Exist:
                if (String.IsNullOrEmpty(mechanism.Domain))
                {
                    return(SpfQualifier.PermError);
                }

                dnsMessage = ResolveDns(ExpandDomain(mechanism.Domain, ip, sender, domain), RecordType.A);
                if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                {
                    return(SpfQualifier.TempError);
                }

                if (dnsMessage.AnswerRecords.Count(record => (record.RecordType == RecordType.A)) > 0)
                {
                    return(mechanism.Qualifier);
                }
                break;

            case SpfMechanismType.Include:
                if (String.IsNullOrEmpty(mechanism.Domain) || (mechanism.Domain.Equals(domain, StringComparison.InvariantCultureIgnoreCase)))
                {
                    return(SpfQualifier.PermError);
                }

                string includeDomain = ExpandDomain(mechanism.Domain, ip, sender, domain);
                string explanation;
                switch (CheckHostInternal(ip, sender, includeDomain, false, out explanation))
                {
                case SpfQualifier.Pass:
                    return(mechanism.Qualifier);

                case SpfQualifier.Fail:
                case SpfQualifier.SoftFail:
                case SpfQualifier.Neutral:
                    return(SpfQualifier.None);

                case SpfQualifier.TempError:
                    return(SpfQualifier.TempError);

                case SpfQualifier.PermError:
                case SpfQualifier.None:
                    return(SpfQualifier.PermError);
                }
                break;

            default:
                return(SpfQualifier.PermError);
            }

            return(SpfQualifier.None);
        }
Esempio n. 5
0
		internal static bool TryParse(string s, out SpfTerm value)
		{
			if (String.IsNullOrEmpty(s))
			{
				value = null;
				return false;
			}

			#region Parse Mechanism
			Match match = _parseMechanismRegex.Match(s);
			if (match.Success)
			{
				SpfMechanism mechanism = new SpfMechanism();

				switch (match.Groups["qualifier"].Value)
				{
					case "+":
						mechanism.Qualifier = SpfQualifier.Pass;
						break;
					case "-":
						mechanism.Qualifier = SpfQualifier.Fail;
						break;
					case "~":
						mechanism.Qualifier = SpfQualifier.SoftFail;
						break;
					case "?":
						mechanism.Qualifier = SpfQualifier.Neutral;
						break;

					default:
						mechanism.Qualifier = SpfQualifier.Pass;
						break;
				}

				SpfMechanismType type;
				mechanism.Type = EnumHelper<SpfMechanismType>.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfMechanismType.Unknown;

				mechanism.Domain = match.Groups["domain"].Value;

				string tmpPrefix = match.Groups["prefix"].Value;
				int prefix;
				if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
				{
					mechanism.Prefix = prefix;
				}

				tmpPrefix = match.Groups["prefix6"].Value;
				if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
				{
					mechanism.Prefix6 = prefix;
				}

				value = mechanism;
				return true;
			}
			#endregion

			#region Parse Modifier
			match = _parseModifierRegex.Match(s);
			if (match.Success)
			{
				SpfModifier modifier = new SpfModifier();

				SpfModifierType type;
				modifier.Type = EnumHelper<SpfModifierType>.TryParse(match.Groups["type"].Value, true, out type) ? type : SpfModifierType.Unknown;
				modifier.Domain = match.Groups["domain"].Value;

				value = modifier;
				return true;
			}
			#endregion

			value = null;
			return false;
		}
Esempio n. 6
0
        internal static bool TryParse(string s, out SpfTerm value)
        {
            if (String.IsNullOrEmpty(s))
            {
                value = null;
                return(false);
            }

            #region Parse Mechanism
            Regex regex = new Regex(@"^(\s)*(?<qualifier>[~+?-]?)(?<type>[a-z]+)(:(?<domain>[^/]+))?(/(?<prefix>[0-9]+))?(//(?<prefix6>[0-9]+))?(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            Match match = regex.Match(s);
            if (match.Success)
            {
                SpfMechanism mechanism = new SpfMechanism();

                switch (match.Groups["qualifier"].Value)
                {
                case "+":
                    mechanism.Qualifier = SpfQualifier.Pass;
                    break;

                case "-":
                    mechanism.Qualifier = SpfQualifier.Fail;
                    break;

                case "~":
                    mechanism.Qualifier = SpfQualifier.SoftFail;
                    break;

                case "?":
                    mechanism.Qualifier = SpfQualifier.Neutral;
                    break;

                default:
                    mechanism.Qualifier = SpfQualifier.Pass;
                    break;
                }

                SpfMechanismType type;
                mechanism.Type = EnumHelper <SpfMechanismType> .TryParse(match.Groups["type"].Value, true, out type) ? type : SpfMechanismType.Unknown;

                mechanism.Domain = match.Groups["domain"].Value;

                string tmpPrefix = match.Groups["prefix"].Value;
                int    prefix;
                if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
                {
                    mechanism.Prefix = prefix;
                }

                tmpPrefix = match.Groups["prefix6"].Value;
                if (!String.IsNullOrEmpty(tmpPrefix) && Int32.TryParse(tmpPrefix, out prefix))
                {
                    mechanism.Prefix6 = prefix;
                }

                value = mechanism;
                return(true);
            }
            #endregion

            #region Parse Modifier
            regex = new Regex(@"^(\s)*(?<type>[a-z]+)=(?<domain>[^\s]+)(\s)*$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            match = regex.Match(s);
            if (match.Success)
            {
                SpfModifier modifier = new SpfModifier();

                SpfModifierType type;
                modifier.Type = EnumHelper <SpfModifierType> .TryParse(match.Groups["type"].Value, true, out type) ? type : SpfModifierType.Unknown;

                modifier.Domain = match.Groups["domain"].Value;

                value = modifier;
                return(true);
            }
            #endregion

            value = null;
            return(false);
        }
Esempio n. 7
0
        internal SpfQualifier CheckHost(SpfCheckHostParameter parameters)
        {
            DnsMessage dnsMessage;

            SpfMechanism spfMechanism = this as SpfMechanism;

            if (spfMechanism != null)
            {
                switch (spfMechanism.Type)
                {
                case SpfMechanismType.All:
                    return(spfMechanism.Qualifier);

                case SpfMechanismType.A:
                    bool?isAMatch = IsIpMatch(String.IsNullOrEmpty(spfMechanism.Domain) ? parameters.CurrentDomain : spfMechanism.Domain, parameters.ClientAddress, spfMechanism.Prefix, spfMechanism.Prefix6);
                    if (!isAMatch.HasValue)
                    {
                        return(SpfQualifier.TempError);
                    }

                    if (isAMatch.Value)
                    {
                        return(spfMechanism.Qualifier);
                    }
                    break;

                case SpfMechanismType.Mx:
                    dnsMessage = DnsClient.Default.Resolve(ExpandDomain(String.IsNullOrEmpty(spfMechanism.Domain) ? parameters.CurrentDomain : spfMechanism.Domain, parameters), RecordType.Mx);
                    if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                    {
                        return(SpfQualifier.TempError);
                    }

                    int mxCheckedCount = 0;

                    foreach (DnsRecordBase dnsRecord in dnsMessage.AnswerRecords)
                    {
                        MxRecord mxRecord = dnsRecord as MxRecord;
                        if (mxRecord != null)
                        {
                            if (++mxCheckedCount == 10)
                            {
                                break;
                            }

                            bool?isMxMatch = IsIpMatch(mxRecord.ExchangeDomainName, parameters.ClientAddress, spfMechanism.Prefix, spfMechanism.Prefix6);
                            if (!isMxMatch.HasValue)
                            {
                                return(SpfQualifier.TempError);
                            }

                            if (isMxMatch.Value)
                            {
                                return(spfMechanism.Qualifier);
                            }
                        }
                    }
                    break;

                case SpfMechanismType.Ip4:
                case SpfMechanismType.Ip6:
                    IPAddress compareAddress;
                    if (IPAddress.TryParse(spfMechanism.Domain, out compareAddress))
                    {
                        if (spfMechanism.Prefix.HasValue)
                        {
                            if (parameters.ClientAddress.GetNetworkAddress(spfMechanism.Prefix.Value).Equals(compareAddress.GetNetworkAddress(spfMechanism.Prefix.Value)))
                            {
                                return(spfMechanism.Qualifier);
                            }
                        }
                        else if (parameters.ClientAddress.Equals(compareAddress))
                        {
                            return(spfMechanism.Qualifier);
                        }
                    }
                    else
                    {
                        return(SpfQualifier.PermError);
                    }

                    break;

                case SpfMechanismType.Ptr:
                    dnsMessage = DnsClient.Default.Resolve(parameters.ClientAddress.GetReverseLookupAddress(), RecordType.Ptr);
                    if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                    {
                        return(SpfQualifier.TempError);
                    }

                    string ptrCompareName = String.IsNullOrEmpty(spfMechanism.Domain) ? parameters.CurrentDomain : spfMechanism.Domain;

                    int ptrCheckedCount = 0;
                    if ((from ptrRecord in dnsMessage.AnswerRecords.OfType <PtrRecord>().TakeWhile(ptrRecord => ++ ptrCheckedCount != 10)
                         let isPtrMatch = IsIpMatch(ptrRecord.PointerDomainName, parameters.ClientAddress, 0, 0)
                                          where isPtrMatch.HasValue && isPtrMatch.Value
                                          select ptrRecord).Any(ptrRecord => ptrRecord.PointerDomainName.Equals(ptrCompareName, StringComparison.InvariantCultureIgnoreCase) || (ptrRecord.PointerDomainName.EndsWith("." + ptrCompareName, StringComparison.InvariantCultureIgnoreCase))))
                    {
                        return(spfMechanism.Qualifier);
                    }
                    break;

                case SpfMechanismType.Exist:
                    if (String.IsNullOrEmpty(spfMechanism.Domain))
                    {
                        return(SpfQualifier.PermError);
                    }

                    dnsMessage = DnsClient.Default.Resolve(ExpandDomain(spfMechanism.Domain, parameters), RecordType.A);
                    if ((dnsMessage == null) || ((dnsMessage.ReturnCode != ReturnCode.NoError) && (dnsMessage.ReturnCode != ReturnCode.NxDomain)))
                    {
                        return(SpfQualifier.TempError);
                    }

                    if (dnsMessage.AnswerRecords.Count(record => (record.RecordType == RecordType.A)) > 0)
                    {
                        return(spfMechanism.Qualifier);
                    }
                    break;

                case SpfMechanismType.Include:
                    if (String.IsNullOrEmpty(spfMechanism.Domain))
                    {
                        return(SpfQualifier.PermError);
                    }

                    string includeDomain = ExpandDomain(spfMechanism.Domain, parameters);
                    switch (SpfRecord.CheckHost(includeDomain, new SpfCheckHostParameter(includeDomain, parameters)))
                    {
                    case SpfQualifier.Pass:
                        return(spfMechanism.Qualifier);

                    case SpfQualifier.Fail:
                    case SpfQualifier.SoftFail:
                    case SpfQualifier.Neutral:
                        return(SpfQualifier.None);

                    case SpfQualifier.TempError:
                        return(SpfQualifier.TempError);

                    case SpfQualifier.PermError:
                    case SpfQualifier.None:
                        return(SpfQualifier.PermError);
                    }
                    break;

                default:
                    return(SpfQualifier.PermError);
                }
            }

            SpfModifier spfModifier = this as SpfModifier;

            if (spfModifier != null)
            {
                switch (spfModifier.Type)
                {
                case SpfModifierType.Redirect:
                    if (String.IsNullOrEmpty(spfModifier.Domain))
                    {
                        return(SpfQualifier.PermError);
                    }

                    string redirectDomain = ExpandDomain(spfModifier.Domain, parameters);
                    return(SpfRecord.CheckHost(redirectDomain, new SpfCheckHostParameter(redirectDomain, parameters)));

                case SpfModifierType.Exp:
                    break;

                default:
                    return(SpfQualifier.PermError);
                }
            }

            return(SpfQualifier.None);
        }