Exemplo n.º 1
0
        public void TestMX(string name, string exchange)
        {
            MXRecord record       = new MXRecord(name, exchange);
            MXRecord parsedRecord = this.Roundtrip <MXRecord>(record);

            Assert.True(parsedRecord.Equals(record));
        }
Exemplo n.º 2
0
 public MantaOutboundClientSendResult(MantaOutboundClientResult result, string message, VirtualMTA vmta = null, MXRecord mx = null)
 {
     MantaOutboundClientResult = result;
     Message    = message;
     VirtualMTA = vmta;
     MXRecord   = mx;
 }
Exemplo n.º 3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="vmta"></param>
        /// <param name="mxRecord"></param>
        /// <param name="maxConnections"></param>
        public MantaOutboundClientPool(VirtualMTA vmta, MXRecord mxRecord)
        {
            _LastUsedTimestamp = DateTime.UtcNow.Ticks;
            MXRecord           = mxRecord;
            VirtualMTA         = vmta;

            var maxMessagesHour = OutboundRuleManager.GetMaxMessagesDestinationHour(vmta, mxRecord);

            if (maxMessagesHour > 0)
            {
                MaxMessagesMinute = (int?)Math.Floor(maxMessagesHour / 60d);
                SentMessagesLog   = new List <long>();
                Logging.Debug("MantaOutboundClientPool> for: " + vmta.IPAddress + "-" + mxRecord.Host + " MAX MESSAGES MIN: " + MaxMessagesMinute);
            }
            else
            {
                MaxMessagesMinute = null;
                SentMessagesLog   = null;
            }

            var maxConnections = OutboundRuleManager.GetMaxConnectionsToDestination(vmta, mxRecord);

            if (maxConnections > 0)
            {
                MaxConnections = maxConnections;
                Logging.Debug("MantaOutboundClientPool> for: " + vmta.IPAddress + "-" + mxRecord.Host + " MAX CONNECTION: " + MaxConnections);
            }
            else
            {
                MaxConnections = null;
            }

            SmtpClients = new List <MantaOutboundClient>();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Gets permission to attempt a send of a message.
        /// </summary>
        /// <param name="ipAddress">The IP Address we wan't to send from.</param>
        /// <param name="mxRecord">The MX Record of the destination.</param>
        /// <returns>TRUE if we can send FALSE if we should throttle.</returns>
        public bool TryGetSendAuth(VirtualMTA ipAddress, MXRecord mxRecord)
        {
            int mxPatternID     = -1;
            int maxMessagesHour = OutboundRuleManager.GetMaxMessagesDestinationHour(ipAddress, mxRecord, out mxPatternID);

            // If the Max messages is -1 then unlimited so can just return true here.
            // No need for any logging or calculating.
            if (maxMessagesHour == -1)
            {
                return(true);
            }

            // Create or get this outbound IP/mx pattern send history.
            ThrottleManager.MxPatternThrottlingSendHistory mxSndHist = null;
            if (!this._sendHistory.TryGetValue(ipAddress.IPAddress.ToString(), out mxSndHist))
            {
                mxSndHist = new ThrottleManager.MxPatternThrottlingSendHistory();
                this._sendHistory.AddOrUpdate(ipAddress.IPAddress.ToString(), mxSndHist, (string s, ThrottleManager.MxPatternThrottlingSendHistory sh) => mxSndHist);
            }
            //this._sendHistory.GetOrAdd(ipAddress.IPAddress.ToString(), new ThrottleManager.MxPatternThrottlingSendHistory());
            List <DateTime> sndHistory = mxSndHist.GetOrAdd(mxPatternID, new List <DateTime>());

            // Only calculate if needed.
            if (mxSndHist.IntervalValuesNeedRecalcTimestamp <= DateTime.UtcNow)
            {
                int maxMessages = 0;
                int maxMessagesIntervalMinute = 0;
                while (maxMessages < 1 && maxMessagesIntervalMinute <= 60)
                {
                    maxMessagesIntervalMinute++;
                    maxMessages = (int)Math.Floor((double)maxMessagesHour / 60d * (double)maxMessagesIntervalMinute);
                }

                mxSndHist.IntervalMaxMessages = maxMessages;
                mxSndHist.IntervalMinutes     = maxMessagesIntervalMinute;
                mxSndHist.IntervalValuesNeedRecalcTimestamp = DateTime.UtcNow.AddMinutes(MtaParameters.MTA_CACHE_MINUTES);
            }


            lock (sndHistory)
            {
                // Remove sends that happened over "Interval" minute(s) ago.
                DateTime sendsAfterTimestamp = DateTime.UtcNow.AddMinutes((double)(mxSndHist.IntervalMinutes * -1));
                sndHistory.RemoveAll((DateTime d) => d <= sendsAfterTimestamp);

                // Check for throttling
                if (sndHistory.Count < mxSndHist.IntervalMaxMessages)
                {
                    // Not hit throttle limit yet.
                    // Log send and return true.
                    sndHistory.Add(DateTime.UtcNow);
                    return(true);
                }
                else
                {
                    // THROTTLED!
                    return(false);
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Gets the maximum amount of simultaneous connections to specified host.
        /// </summary>
        /// <param name="ipAddress">IP Address connecting from.</param>
        /// <param name="record">MXRecord of the destination.</param>
        /// <returns>Max number of connections.</returns>
        internal static int GetMaxConnectionsToDestination(VirtualMTA ipAddress, MXRecord record)
        {
            int mxPatternID = -1;
            OutboundRuleCollection rules = OutboundRuleManager.GetRules(record, ipAddress, out mxPatternID);

            for (int i = 0; i < rules.Count; i++)
            {
                if (rules[i].Type == OutboundRuleType.MaxConnections)
                {
                    int tmp = 0;
                    if (int.TryParse(rules[i].Value, out tmp))
                    {
                        return(tmp);
                    }
                    else
                    {
                        Logging.Error("Failed to get max connections for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " value wasn't valid [" + rules[i].Value + "], defaulting to 1");
                        return(1);
                    }
                }
            }

            Logging.Error("Failed to get max connections for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " defaulting to 1");
            return(1);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets the MAX number of messages allowed to be sent through the connection.
        /// </summary>
        /// <param name="record">MX Record for the destination.</param>
        /// <param name="ipAddress">IPAddress that we are sending from.</param>
        /// <returns>Max number of messages per connection.</returns>
        public static int GetMaxMessagesPerConnection(MXRecord record, VirtualMTA ipAddress)
        {
            int mxPatternID = 0;
            OutboundRuleCollection rules = GetRules(record, ipAddress, out mxPatternID);

            for (int i = 0; i < rules.Count; i++)
            {
                if (rules[i].Type == OutboundRuleType.MaxMessagesConnection)
                {
                    int tmp = 0;
                    if (int.TryParse(rules[i].Value, out tmp))
                    {
                        return(tmp);
                    }
                    else
                    {
                        Logging.Error("Failed to get max messages per connection for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " value wasn't valid [" + rules[i].Value + "], defaulting to 1");
                        return(1);
                    }
                }
            }

            Logging.Error("Failed to get max messages per connection for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " defaulting to 1");
            return(1);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Attempt to connect to the specified MX server.
        /// </summary>
        /// <param name="mx">MX Record of the server to connect to.</param>
        public async Task <bool> ConnectAsync(MXRecord mx)
        {
            _LastActive = DateTime.UtcNow;
            IsActive    = true;
            await base.ConnectAsync(mx.Host, MtaParameters.Client.SMTP_PORT);

            _LastActive = DateTime.UtcNow;
            SmtpStream  = new SmtpStreamHandler(this as TcpClient);
            _MXRecord   = mx;

            // Read the Server greeting.
            string response = SmtpStream.ReadAllLines();

            _LastActive = DateTime.UtcNow;

            if (!response.StartsWith("2"))
            {
                // If the MX is actively denying use service access, SMTP code 421 then we should inform
                // the ServiceNotAvailableManager manager so it limits our attepts to this MX to 1/minute.
                if (response.StartsWith("421"))
                {
                    ServiceNotAvailableManager.Add(SmtpStream.LocalAddress.ToString(), MXRecord.Host, DateTime.UtcNow);
                }

                base.Close();
                return(false);
            }

            IsActive    = false;
            _LastActive = DateTime.UtcNow;
            return(true);
        }
Exemplo n.º 8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="vmta"></param>
        /// <param name="mxRecord"></param>
        private void AddClientPool(VirtualMTA vmta, MXRecord mxRecord)
        {
            var key = GetPoolKey(vmta, mxRecord);

            lock (AddClientPoolLock)
            {
                if (!ClientPools.ContainsKey(key))
                {
                    ClientPools[key] = new MantaOutboundClientPool(vmta, mxRecord);
                }
            }
        }
        private MXRecord DeserializeMxRr(string name, int ttl, byte[] bytes, int start, out int bytesRead)
        {
            var mx = new MXRecord()
            {
                Name       = name,
                TimeToLive = ttl,
            };

            mx.ExchangeDName = this.dnsSerializer.ParseQuestionName(bytes, start, out bytesRead);
            bytesRead       += 2; // preference

            return(mx);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Gets MX record collection.
        /// Each string is a single record formatted as "Priority,Host,TTL"
        /// If Null then no MX servers where found.
        /// </summary>
        /// <param name="domain">The domain to get MXs for.</param>
        /// <returns>See description.</returns>
        /// <throws>Win32 Exception. (123)</throws>
        internal static string[] GetMXRecords(string domain)
        {
            // Pointer to the first DNS result.
            IntPtr    ptrFirstRecord = IntPtr.Zero;
            ArrayList results        = new ArrayList();

            try
            {
                // Do the DNS query.
                int retVal = dnsapi.DnsQuery_W(ref domain, QueryTypes.DNS_TYPE_MX, QueryOptions.DNS_QUERY_STANDARD, 0, ref ptrFirstRecord, 0);

                // If the retVal isn't 0 then something went wrong
                if (retVal != 0)
                {
                    // There are no DNS records of type MX.
                    if (retVal == 9003 || retVal == 9501)
                    {
                        return(null);
                    }
                    else if (retVal == 123)
                    {
                        throw new DNSDomainNotFoundException();
                    }
                    else
                    {
                        //throw new Win32Exception(retVal);
                        System.Diagnostics.Trace.WriteLine("DNS_API:" + domain + " (" + retVal + ")");
                        return(null);
                    }
                }

                MXRecord recMx            = (MXRecord)Marshal.PtrToStructure(ptrFirstRecord, typeof(MXRecord));;
                IntPtr   ptrCurrentRecord = IntPtr.Zero;
                for (ptrCurrentRecord = ptrFirstRecord; !ptrCurrentRecord.Equals(IntPtr.Zero); ptrCurrentRecord = recMx.pNext)
                {
                    recMx = (MXRecord)Marshal.PtrToStructure(ptrCurrentRecord, typeof(MXRecord));
                    if (recMx.wType == 15)
                    {
                        string line = recMx.wPreference.ToString() + "," + Marshal.PtrToStringAuto(recMx.pNameExchange) + "," + recMx.dwTtl.ToString();
                        results.Add(line);
                    }
                }
            }
            finally
            {
                // Always cleanup.
                DnsRecordListFree(ptrFirstRecord, 0);
            }

            return((string[])results.ToArray(typeof(string)));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Creates a SmtpOutboundClient bound to the specified endpoint.
        /// </summary>
        /// <param name="ipAddress">The local IP address to bind to.</param>
        public MantaOutboundClient(VirtualMTA vmta, MXRecord mx) : base()
        {
            _VirtualMta = vmta;
            _MXRecord   = mx;
            TcpClient   = CreateTcpClient();

            _CanPipeline = false;

            _MaxMessagesConnection = OutboundRuleManager.GetMaxMessagesPerConnection(mx, vmta);
            if (_MaxMessagesConnection < 1)
            {
                _MaxMessagesConnection = null;
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Tests equality between this TXT record and the other <paramref name="record"/>.
        /// </summary>
        /// <param name="record">The other record.</param>
        /// <returns><c>true</c> if the RRs are equal, <c>false</c> otherwise.</returns>
        public override bool Equals(DnsResourceRecord record)
        {
            if (!base.Equals(record))
            {
                return(false);
            }

            MXRecord mxRecord = record as MXRecord;

            if (mxRecord == null)
            {
                return(false);
            }

            return(
                DnsStandard.Equals(m_exchange, mxRecord.m_exchange) &&
                this.Preference == mxRecord.Preference
                );
        }
Exemplo n.º 13
0
        /// <summary>
        /// Gets the Outbound Rules for the specified destination MX and optionally IP Address.
        /// </summary>
        /// <param name="mxRecord">MXRecord for the destination MX.</param>
        /// <param name="mtaIpAddress">Outbound IP Address</param>
        /// <param name="mxPatternID">OUT: the ID of MxPattern that caused match.</param>
        /// <returns></returns>
        public static IList <OutboundRule> GetRules(MXRecord mxRecord, VirtualMTA mtaIpAddress, out int mxPatternID)
        {
            // Get the data from the database. This needs to be cleverer and reload every x minutes.
            if (OutboundRuleManager._MXPatterns == null)
            {
                OutboundRuleManager._MXPatterns = OutboundRuleDB.GetOutboundRulePatterns();
            }
            if (OutboundRuleManager._Rules == null)
            {
                OutboundRuleManager._Rules = OutboundRuleDB.GetOutboundRules();
            }

            int patternID = OutboundRuleManager.GetMxPatternID(mxRecord, mtaIpAddress);

            mxPatternID = patternID;
            return((from r in OutboundRuleManager._Rules
                    where r.OutboundMxPatternID == patternID
                    select r).ToList());
        }
Exemplo n.º 14
0
        public DnsRecord ParseMX(string[] args)
        {
            string domainName = args.GetRequiredValue(0);
            string exchange   = args.GetRequiredValue(1);
            int    ttl        = this.ValidateTTL(args.GetOptionalValue <int>(2, 0));
            short  pref       = args.GetOptionalValue <short>(3, 10);
            string notes      = args.GetOptionalValue(4, string.Empty);

            MXRecord record = new MXRecord(domainName
                                           , exchange
                                           , pref)
            {
                TTL = ttl
            };

            DnsRecord dnsRecord = new DnsRecord(domainName, DnsStandard.RecordType.MX, record.Serialize(), notes);

            return(dnsRecord);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Get the MX records for the specified domain name using the specified DNS server.
        /// </summary>
        /// <param name="address">The domain name.</param>
        /// <param name="host">The host name of the DNS server to use.</param>
        /// <param name="port">The port number of the DNS server to use.</param>
        /// <param name="timeout">The timeout in miliseconds.</param>
        /// <returns>A collection of Mx Records.</returns>
        public static ActiveUp.Net.Mail.MxRecordCollection GetMxRecords(string address, string host, int port, int timeout)
        {
            MxRecordCollection mxRecords = new MxRecordCollection();

            DnsQuery query = new DnsQuery(IPAddress.Parse(host));

            query.RecursiveQuery = true;
            query.DnsServer.Port = port;
            query.Domain         = address;

            DnsAnswer answer = query.QueryServer(RecordType.MX, timeout);

            foreach (DnsEntry entry in answer.Answers)
            {
                MXRecord mxRecord = (MXRecord)entry.Data;

                mxRecords.Add(mxRecord.Domain, mxRecord.Preference);
            }

            return(mxRecords);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Gets the maximum amount of messages to send per hour from each ip address to mx.
        /// </summary>
        /// <param name="ipAddress">Outbound IP address</param>
        /// <param name="record">MX Record of destination server.</param>
        /// <param name="mxPatternID">ID of the pattern used to identify the rule.</param>
        /// <returns>Maximum number of messages per hour or -1 for unlimited.</returns>
        public static int GetMaxMessagesDestinationHour(VirtualMTA ipAddress, MXRecord record, out int mxPatternID)
        {
            OutboundRuleCollection rules = OutboundRuleManager.GetRules(record, ipAddress, out mxPatternID);

            for (int i = 0; i < rules.Count; i++)
            {
                if (rules[i].Type == OutboundRuleType.MaxMessagesPerHour)
                {
                    int tmp = 0;
                    if (int.TryParse(rules[i].Value, out tmp))
                    {
                        return(tmp);
                    }
                    else
                    {
                        Logging.Error("Failed to get max messages per hour for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " value wasn't valid [" + rules[i].Value + "], defaulting to unlimited");
                        return(-1);
                    }
                }
            }

            Logging.Error("Failed to get max messages per hour for " + record.Host + " using " + ipAddress.IPAddress.ToString() + " defaulting to unlimited");
            return(-1);
        }
Exemplo n.º 17
0
 /// <summary>
 /// This method handles message deferal.
 ///	Logs deferral
 ///	Fails the message if timed out
 /// or
 /// Sets the next rety date time
 /// </summary>
 /// <param name="defMsg">The deferal message from the SMTP server.</param>
 /// <param name="ipAddress">IP Address that send was attempted from.</param>
 /// <param name="mxRecord">MX Record of the server tried to send too.</param>
 /// <param name="isServiceUnavailable">If false will backoff the retry, if true will use the MtaParameters.MtaRetryInterval,
 /// this is needed to reduce the tail when sending as a message could get multiple try again laters and soon be 1h+ before next retry.</param>
 public static void HandleDeliveryDeferral(MtaQueuedMessage msg, string defMsg, VirtualMTA ipAddress, MXRecord mxRecord, bool isServiceUnavailable = false)
 {
     HandleDeliveryDeferralAsync(msg, defMsg, ipAddress, mxRecord, isServiceUnavailable).Wait();
 }
Exemplo n.º 18
0
        /// <summary>
        /// Gets an Array of MX Records for the specified domain. If none found returns null.
        /// </summary>
        /// <param name="domain"></param>
        /// <returns></returns>
        public static MXRecord[] GetMXRecords(string domain)
        {
            // Make sure the domain is all lower.
            domain = domain.ToLower();

            // This is what we'll be returning.
            MXRecord[] mxRecords = null;

            // Try and get DNS from internal cache.
            if (DNSManager._Records.TryGetValue(domain, out mxRecords))
            {
                // Found cached records.
                // Make sure they haven't expired.
                if (mxRecords.Count((MXRecord mx) => mx.Dead) < 1)
                {
                    return(mxRecords);
                }
            }

            string[] records = null;

            try
            {
                // Get the records from DNS
                records = dnsapi.GetMXRecords(domain);
            }
            catch (DNSDomainNotFoundException)
            {
                // Ensure records is null.
                records = null;
            }

            // No MX records for domain.
            if (records == null)
            {
                // If there are no MX records use the hostname as per SMTP RFC.
                MXRecord[] mxs = new MXRecord[]
                {
                    new MXRecord(domain, 10, 300u, MxRecordSrc.A)
                };
                _Records.AddOrUpdate(domain, mxs, (string key, MXRecord[] existing) => mxs);
                return(mxs);
            }

            mxRecords = new MXRecord[records.Length];
            for (int i = 0; i < mxRecords.Length; i++)
            {
                string[] split = records[i].Split(new char[] { ',' });
                if (split.Length == 3)
                {
                    mxRecords[i] = new MXRecord(split[1], int.Parse(split[0]), uint.Parse(split[2]), MxRecordSrc.MX);
                }
            }

            // Order by preferance
            mxRecords = (
                from mx in mxRecords
                where mx != null
                orderby mx.Preference
                select mx).ToArray <MXRecord>();
            DNSManager._Records.TryAdd(domain, mxRecords);
            return(mxRecords);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Attempt to create a new connection using the specified ip address and mx record.
        /// </summary>
        /// <returns>A connected outbound client or NULL</returns>
        public async Task <CreateNewConnectionAsyncResult> CreateNewConnectionAsync(VirtualMTA ipAddress, MXRecord mxRecord)
        {
            SmtpOutboundClient smtpClient = null;

            // Get the maximum connections to the destination.
            int maximumConnections = OutboundRuleManager.GetMaxConnectionsToDestination(ipAddress, mxRecord);

            lock (this.SyncRoot)
            {
                // Get the currently active connections count.
                int currentConnections = InUseConnections.Count;

                lock (_ConnectionAttemptsInProgressLock)
                {
                    // If the current connections count + current connection is less than
                    // the maximum connections then we can create a new connection otherwise
                    // we are maxed out so return null.
                    if (maximumConnections <= (currentConnections + _ConnectionAttemptsInProgress))
                    {
                        return(new CreateNewConnectionAsyncResult(new MaxConnectionsException()));
                    }


                    // Limit the amount of connection attempts or experiance massive delays 30s+ for client.connect()
                    if (_ConnectionAttemptsInProgress >= SmtpClientQueue.MAX_SIMULTANEOUS_CLIENT_CONNECT_ATTEMPTS)
                    {
                        //Logging.Debug("Cannot attempt to create new connection.");
                        return(new CreateNewConnectionAsyncResult(new MaxConnectionsException()));
                    }

                    //Logging.Debug("Attempting to create new connection.");
                    _ConnectionAttemptsInProgress++;
                }
            }

            // Do the actual creating and connecting of the client outside of the lock
            // so we don't block other threads.

            try
            {
                // Create the new client and make the connection
                smtpClient = new SmtpOutboundClient(ipAddress);
                await smtpClient.ConnectAsync(mxRecord);

                smtpClient.IsActive = true;
                this.InUseConnections.Add(smtpClient);
            }
            catch (Exception ex)
            {
                // If something went wrong clear the client so we don't return something odd.
                if (smtpClient != null)
                {
                    smtpClient.Close();
                    smtpClient.Dispose();
                    smtpClient = null;
                }
                if (ex is SocketException)
                {
                    return(new CreateNewConnectionAsyncResult(ex));
                }

                if (ex is AggregateException && ex.InnerException is System.IO.IOException)
                {
                    return(new CreateNewConnectionAsyncResult(ex.InnerException));
                }
            }
            finally
            {
                // Reduce the current attempts as were done.
                _ConnectionAttemptsInProgress--;
                if (smtpClient != null)
                {
                    smtpClient.IsActive = false;
                }
            }

            // Return connected client or null.
            return(new CreateNewConnectionAsyncResult(smtpClient));
        }
Exemplo n.º 20
0
        /// <summary>
        /// Gets the MxPatternID that matches the MX Record, Outbound IP Address combo.
        /// </summary>
        /// <param name="record"></param>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        private static int GetMxPatternID(MXRecord record, VirtualMTA ipAddress)
        {
            if (_matchedPatterns == null)
            {
                _matchedPatterns = new ConcurrentDictionary <string, MatchedMxPatternCollection>();
            }

            MatchedMxPatternCollection matchedPatterns = null;

            if (!_matchedPatterns.TryGetValue(record.Host, out matchedPatterns))
            {
                matchedPatterns = new MatchedMxPatternCollection();
                _matchedPatterns.AddOrUpdate(record.Host, matchedPatterns, (string s, MatchedMxPatternCollection p) => matchedPatterns);
            }

            MatchedMxPattern matchedPattern = matchedPatterns.GetMatchedMxPattern(ipAddress);

            if (matchedPattern != null &&
                matchedPattern.MatchedUtc.AddMinutes(MtaParameters.MTA_CACHE_MINUTES) > DateTime.UtcNow)
            {
                // Found a valid cached pattern ID so return it.
                return(matchedPattern.MxPatternID);
            }

            // Loop through all of the patterns
            for (int i = 0; i < _MXPatterns.Count; i++)
            {
                // The current pattern we're working with.
                OutboundMxPattern pattern = _MXPatterns[i];

                // If the pattern applies only to a specified IP address then
                // only check for a match if getting rules for that IP.
                if (pattern.LimitedToOutboundIpAddressID.HasValue &&
                    pattern.LimitedToOutboundIpAddressID.Value != ipAddress.ID)
                {
                    continue;
                }

                if (pattern.Type == OutboundMxPatternType.CommaDelimited)
                {
                    // Pattern is a comma delimited list, so split the values
                    string[] strings = pattern.Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                    // Loop though the values in the split string array.
                    for (int c = 0; c < strings.Length; c++)
                    {
                        try
                        {
                            // If they are a match return the rules.
                            if (strings[c].Equals(record.Host, StringComparison.OrdinalIgnoreCase))
                            {
                                if (pattern.LimitedToOutboundIpAddressID.HasValue)
                                {
                                    matchedPatterns.Add(pattern.ID, ipAddress);
                                }
                                else
                                {
                                    matchedPatterns.Add(pattern.ID, null);
                                }

                                return(pattern.ID);
                            }
                        }
                        catch (Exception) { }
                    }

                    continue;
                }
                else if (pattern.Type == OutboundMxPatternType.Regex)
                {
                    // Pattern is Regex so just need to do an IsMatch
                    if (Regex.IsMatch(record.Host, pattern.Value, RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
                    {
                        // Found pattern match.
                        if (pattern.LimitedToOutboundIpAddressID.HasValue)
                        {
                            matchedPatterns.Add(pattern.ID, ipAddress);
                        }
                        else
                        {
                            matchedPatterns.Add(pattern.ID, null);
                        }

                        return(pattern.ID);
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    // Don't know what to do with this pattern so move on to the next.
                    Logging.Error("Unknown OutboundMxPatternType : " + pattern.Type.ToString());
                    continue;
                }
            }

            // Should have been found by default at least, but hasn't.
            Logging.Fatal("No MX Pattern Rules! Default Deleted?");
            MantaCoreEvents.InvokeMantaCoreStopping();
            Environment.Exit(0);
            return(-1);
        }
Exemplo n.º 21
0
        public override int Compare(DnsRecord x, DnsRecord y)
        {
            if (x == y)
            {
                return(0);
            }
            if (x == null)
            {
                return(-1);
            }
            if (y == null)
            {
                return(1);
            }

            int res = 0;

            if ((res = x.Type.ToString().CompareTo(y.Type.ToString())) == 0 &&
                (res = x.Owner.CompareTo(y.Owner)) == 0)
            {
                switch (x.Type)
                {
                case DnsRecordType.NS:
                    res = ((NSRecord)x).Domain.CompareTo(((NSRecord)y).Domain);
                    break;

                case DnsRecordType.CName:
                    res = ((CNameRecord)x).Canonical.CompareTo(((CNameRecord)y).Canonical);
                    break;

                case DnsRecordType.DN:
                    res = ((DNRecord)x).Target.CompareTo(((DNRecord)y).Target);
                    break;

                case DnsRecordType.Ptr:
                    res = ((PtrRecord)x).Domain.CompareTo(((PtrRecord)y).Domain);
                    break;

                case DnsRecordType.HInfo:
                    HInfoRecord xHInfo = (HInfoRecord)x;
                    HInfoRecord yHInfo = (HInfoRecord)y;

                    if ((res = xHInfo.Cpu.CompareTo(yHInfo.Cpu)) == 0)
                    {
                        res = xHInfo.Os.CompareTo(yHInfo.Os);
                    }
                    break;

                case DnsRecordType.MInfo:
                    MInfoRecord xMInfo = (MInfoRecord)x;
                    MInfoRecord yMInfo = (MInfoRecord)y;

                    if ((res = xMInfo.RMbox.CompareTo(yMInfo.RMbox)) == 0)
                    {
                        res = xMInfo.EMbox.CompareTo(yMInfo.EMbox);
                    }
                    break;

                case DnsRecordType.MX:
                    MXRecord xMx = (MXRecord)x;
                    MXRecord yMx = (MXRecord)y;

                    if ((res = xMx.CompareTo(yMx)) == 0)
                    {
                        res = xMx.Exchange.CompareTo(yMx.Exchange);
                    }
                    break;

                case DnsRecordType.MB:
                    res = ((MBRecord)x).Mailbox.CompareTo(((MBRecord)y).Mailbox);
                    break;

                case DnsRecordType.MG:
                    res = ((MGRecord)x).Mailbox.CompareTo(((MGRecord)y).Mailbox);
                    break;

                case DnsRecordType.MR:
                    res = ((MRRecord)x).NewMailbox.CompareTo(((MRRecord)y).NewMailbox);
                    break;

                case DnsRecordType.Txt:
                    res = ((TxtRecord)x).Text.CompareTo(((TxtRecord)y).Text);
                    break;

                case DnsRecordType.Spf:
                    res = ((SpfRecord)x).Specification.CompareTo(((SpfRecord)y).Specification);
                    break;

                case DnsRecordType.Srv:
                    SrvRecord xSrv = (SrvRecord)x;
                    SrvRecord ySrv = (SrvRecord)y;

                    if ((res = xSrv.CompareTo(ySrv)) == 0)
                    {
                        res = xSrv.Target.CompareTo(ySrv.Target);
                    }
                    break;

                default:
                    res = 0;
                    break;
                }
            }

            return(res);
        }
Exemplo n.º 22
0
        public static int GetMaxMessagesDestinationHour(VirtualMTA vmta, MXRecord mx)
        {
            int tmp;

            return(GetMaxMessagesDestinationHour(vmta, mx, out tmp));
        }
Exemplo n.º 23
0
        public void CreateDnsResourceRecords(string domain)
        {
            DnsBuffer buff = new DnsBuffer();

            byte[]        bytes;
            AddressRecord arec = new AddressRecord(domain
                                                   , "127.0.0.1")
            {
                TTL = 1000
            };

            arec.Serialize(buff);

            string path = Path.Combine(DNSRECORDSEPATH, string.Format("aname.{0}.bin", domain));

            Console.WriteLine("Creating {0}", path);

            using (FileStream s = new FileStream(path, FileMode.OpenOrCreate))
            {
                s.Write(buff.Buffer
                        , 0
                        , buff.Buffer.Length);
                s.Close();
            }


            //----------------------------------------------------------------------------------------------------
            //---read the stream from the bytes
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                Console.WriteLine("checking [{0}]", path);
                bytes = new BinaryReader(fs).ReadBytes((int)new FileInfo(path).Length);
                DnsBufferReader rdr = new DnsBufferReader(bytes, 0, bytes.Length);
                arec = (AddressRecord)DnsResourceRecord.Deserialize(ref rdr);
            }
            Console.WriteLine(arec.IPAddress);
            Console.WriteLine(arec.TTL);
            Console.WriteLine(arec.Name);
            //----------------------------------------------------------------------------------------------------------------
            SOARecord soa = new SOARecord(domain
                                          , domain + ".dom"
                                          , "somebody"
                                          , 1
                                          , 2
                                          , 3
                                          , 4
                                          , 5)
            {
                TTL = 2000
            };

            buff = new DnsBuffer();
            soa.Serialize(buff);

            path = Path.Combine(DNSRECORDSEPATH, string.Format("soa.{0}.bin", domain));
            Console.WriteLine("Creating {0}", path);

            using (FileStream s = new FileStream(path, FileMode.OpenOrCreate))
            {
                s.Write(buff.Buffer
                        , 0
                        , buff.Buffer.Length);
                s.Close();
            }

            //----------------------------------------------------------------------------------------------------
            //---read the stream from the bytes
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                Console.WriteLine("checking [{0}]", path);
                bytes = new BinaryReader(fs).ReadBytes((int)new FileInfo(path).Length);
                DnsBufferReader rdr = new DnsBufferReader(bytes, 0, bytes.Length);
                soa = (SOARecord)DnsResourceRecord.Deserialize(ref rdr);
            }
            Console.WriteLine(soa.ResponsibleName);
            Console.WriteLine(soa.SerialNumber);
            Console.WriteLine(soa.Retry);
            Console.WriteLine(soa.Refresh);
            Console.WriteLine(soa.Expire);
            Console.WriteLine(soa.Minimum);
            Console.WriteLine(soa.TTL);
            Console.WriteLine(soa.Name);
            //----------------------------------------------------------------------------------------------------------------
            MXRecord mx = new MXRecord(domain
                                       , string.Format("mx.{0}", domain)
                                       , 1)
            {
                TTL = 2000
            };

            buff = new DnsBuffer();
            mx.Serialize(buff);

            path = Path.Combine(DNSRECORDSEPATH, string.Format("mx.{0}.bin", domain));
            Console.WriteLine("Creating {0}", path);

            using (FileStream s = new FileStream(path, FileMode.OpenOrCreate))
            {
                s.Write(buff.Buffer
                        , 0
                        , buff.Buffer.Length);
                s.Close();
            }

            //----------------------------------------------------------------------------------------------------
            //---read the stream from the bytes
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                Console.WriteLine("checking [{0}]", path);
                bytes = new BinaryReader(fs).ReadBytes((int)new FileInfo(path).Length);
                DnsBufferReader rdr = new DnsBufferReader(bytes, 0, bytes.Length);
                mx = (MXRecord)DnsResourceRecord.Deserialize(ref rdr);
            }
            Console.WriteLine(mx.Exchange);
            Console.WriteLine(mx.Name);
            Console.WriteLine(mx.Preference);

            //----------------------------------------------------------------------------------------------------------------
            //---create the cert on the fly
            CertRecord cert = new CertRecord(new DnsX509Cert(CreateNamedKeyCertificate(new CertData(domain
                                                                                                    , domain
                                                                                                    , string.Format("CN={0}", domain)
                                                                                                    , ""))))
            {
                TTL = 2000
            };

            buff = new DnsBuffer();
            cert.Serialize(buff);

            path = Path.Combine(DNSRECORDSEPATH, string.Format("cert.{0}.bin", domain));
            Console.WriteLine("Creating {0}", path);

            using (FileStream s = new FileStream(path, FileMode.OpenOrCreate))
            {
                s.Write(buff.Buffer
                        , 0
                        , buff.Buffer.Length);
                s.Close();
            }

            //----------------------------------------------------------------------------------------------------
            //---read the stream from the bytes
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                Console.WriteLine("checking [{0}]", path);
                bytes = new BinaryReader(fs).ReadBytes((int)new FileInfo(path).Length);
                DnsBufferReader rdr = new DnsBufferReader(bytes, 0, bytes.Length);
                cert = (CertRecord)DnsResourceRecord.Deserialize(ref rdr);
            }
            Console.WriteLine(cert.Name);
            Console.WriteLine(cert.Cert.Certificate.NotBefore);
            Console.WriteLine(cert.Cert.Certificate.NotAfter);
        }
Exemplo n.º 24
0
        /// <summary>
        /// This method handles failure of delivery.
        /// Logs failure
        /// Deletes queued data
        /// </summary>
        /// <param name="failMsg"></param>
        public static async Task <bool> HandleDeliveryFailAsync(MtaQueuedMessage msg, string failMsg, VirtualMTA ipAddress, MXRecord mxRecord)
        {
            await MtaTransaction.LogTransactionAsync(msg, TransactionStatus.Failed, failMsg, ipAddress, mxRecord);

            try
            {
                // Send fails to Manta.Core.Events
                for (int i = 0; i < msg.RcptTo.Length; i++)
                {
                    EmailProcessingDetails processingInfo = null;
                    EventsManager.Instance.ProcessSmtpResponseMessage(failMsg, msg.RcptTo[i], msg.InternalSendID, out processingInfo);
                }
            }
            catch (Exception)
            {
            }

            msg.IsHandled = true;

            return(true);
        }
Exemplo n.º 25
0
        /// <summary>
        /// This method handle successful delivery.
        /// Logs success
        /// Deletes queued data
        /// </summary>
        public static async Task <bool> HandleDeliverySuccessAsync(MtaQueuedMessage msg, VirtualMTA ipAddress, MXRecord mxRecord, string response)
        {
            await MtaTransaction.LogTransactionAsync(msg, TransactionStatus.Success, response, ipAddress, mxRecord);

            msg.IsHandled = true;
            return(true);
        }
Exemplo n.º 26
0
 private string GetPoolKey(VirtualMTA vmta, MXRecord mxRecord)
 {
     return(vmta.ID.ToString() + "-" + mxRecord.Host.ToLower());
 }
Exemplo n.º 27
0
        /// <summary>
        /// This method handles message throttle.
        ///	Logs throttle
        /// Sets the next rety date time
        /// </summary>
        internal static async Task <bool> HandleDeliveryThrottleAsync(MtaQueuedMessage msg, VirtualMTA ipAddress, MXRecord mxRecord)
        {
            // Log deferral
            await MtaTransaction.LogTransactionAsync(msg, TransactionStatus.Throttled, string.Empty, ipAddress, mxRecord);

            // Set next retry time and release the lock.
            msg.AttemptSendAfterUtc = DateTime.UtcNow.AddMinutes(1);
            msg.RabbitMqPriority    = RabbitMqPriority.Low;
            await Requeue(msg);

            return(true);
        }
Exemplo n.º 28
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ipAddress"></param>
 /// <param name="mxRecord"></param>
 /// <returns></returns>
 public static async Task <bool> HandleFailedToConnectAsync(MtaQueuedMessage msg, VirtualMTA ipAddress, MXRecord mxRecord)
 {
     // If there was no MX record in DNS, so using A, we should fail and not retry.
     if (mxRecord.MxRecordSrc == MxRecordSrc.A)
     {
         return(await HandleDeliveryFailAsync(msg, "550 Failed to connect", ipAddress, mxRecord));
     }
     else
     {
         return(await HandleDeliveryDeferralAsync(msg, "Failed to connect", ipAddress, mxRecord, false, 15));
     }
 }
Exemplo n.º 29
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="vmta"></param>
        /// <param name="mxRecord"></param>
        /// <param name="rawMsg"></param>
        /// <returns></returns>
        private async Task <MantaOutboundClientSendResult> SendAsync(MailAddress mailFrom, MailAddress rcptTo, VirtualMTA vmta, MXRecord mxRecord, string msg)
        {
            var key = GetPoolKey(vmta, mxRecord);

            if (!ClientPools.ContainsKey(key))
            {
                AddClientPool(vmta, mxRecord);
            }

            var pool = ClientPools[key];

            return(await pool.SendAsync(mailFrom, rcptTo, msg));
        }
Exemplo n.º 30
0
        /// <summary>
        /// This method handles message deferal.
        ///	Logs deferral
        ///	Fails the message if timed out
        /// or
        /// Sets the next rety date time
        /// </summary>
        /// <param name="defMsg">The deferal message from the SMTP server.</param>
        /// <param name="ipAddress">IP Address that send was attempted from.</param>
        /// <param name="mxRecord">MX Record of the server tried to send too.</param>
        /// <param name="isServiceUnavailable">If false will backoff the retry, if true will use the MtaParameters.MtaRetryInterval,
        /// this is needed to reduce the tail when sending as a message could get multiple try again laters and soon be 1h+ before next retry.</param>
        public static async Task <bool> HandleDeliveryDeferralAsync(MtaQueuedMessage msg, string defMsg, VirtualMTA ipAddress, MXRecord mxRecord, bool isServiceUnavailable = false, int?overrideTimeminutes = null)
        {
            // Log the deferral.
            await MtaTransaction.LogTransactionAsync(msg, TransactionStatus.Deferred, defMsg, ipAddress, mxRecord);

            // This holds the maximum interval between send retries. Should be put in the database.
            int maxInterval = 3 * 60;

            // Increase the defered count as the queued messages has been deferred.
            msg.DeferredCount++;

            // Hold the minutes to wait until next retry.
            double nextRetryInterval = MtaParameters.MtaRetryInterval;

            if (overrideTimeminutes.HasValue)
            {
                nextRetryInterval = overrideTimeminutes.Value;
            }
            else
            {
                if (!isServiceUnavailable)
                {
                    // Increase the deferred wait interval by doubling for each retry.
                    for (int i = 1; i < msg.DeferredCount; i++)
                    {
                        nextRetryInterval = nextRetryInterval * 2;
                    }

                    // If we have gone over the max interval then set to the max interval value.
                    if (nextRetryInterval > maxInterval)
                    {
                        nextRetryInterval = maxInterval;
                    }
                }
                else
                {
                    nextRetryInterval = 1;                     // For service unavalible use 1 minute between retries.
                }
            }

            // Set next retry time and release the lock.
            msg.AttemptSendAfterUtc = DateTime.UtcNow.AddMinutes(nextRetryInterval);
            await Requeue(msg);

            return(true);
        }