/// <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); }
/// <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); } } }
/// <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 OutboundRuleCollection 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(new OutboundRuleCollection( from r in OutboundRuleManager._Rules where r.OutboundMxPatternID == patternID select r)); }
/// <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); }