/// <summary> /// Creates a MtaIPGroup object using the Data Record. /// </summary> /// <param name="record"></param> /// <returns></returns> private static VirtualMta.VirtualMtaGroup CreateAndFillVirtualMtaGroup(IDataRecord record) { VirtualMta.VirtualMtaGroup group = new VirtualMta.VirtualMtaGroup(); group.ID = record.GetInt32("ip_group_id"); group.Name = record.GetString("ip_group_name"); if (!record.IsDBNull("ip_group_description")) { group.Description = record.GetString("ip_group_description"); } return(group); }
/// <summary> /// Saves the virtual mta group to the database. /// </summary> /// <param name="grp">Group to save.</param> internal static void Save(VirtualMta.VirtualMtaGroup grp) { StringBuilder groupMembershipInserts = new StringBuilder(); foreach (VirtualMta.VirtualMTA vmta in grp.VirtualMtaCollection) { groupMembershipInserts.AppendFormat(@"{1}INSERT INTO man_ip_groupMembership(ip_group_id, ip_ipAddress_id) VALUES(@id,{0}){1}", vmta.ID, Environment.NewLine); } using (SqlConnection conn = MantaDB.GetSqlConnection()) { SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = @" BEGIN TRANSACTION IF EXISTS(SELECT 1 FROM man_ip_group WHERE ip_group_id = @id) UPDATE man_ip_group SET ip_group_name = @name, ip_group_description = @description WHERE ip_group_id = @id ELSE BEGIN INSERT INTO man_ip_group(ip_group_name, ip_group_description) VALUES(@name, @description) SELECT @id = @@IDENTITY END DELETE FROM man_ip_groupMembership WHERE ip_group_id = @id " + groupMembershipInserts.ToString() + @" COMMIT TRANSACTION"; cmd.Parameters.AddWithValue("@id", grp.ID); cmd.Parameters.AddWithValue("@name", grp.Name); cmd.Parameters.AddWithValue("@description", grp.Description); conn.Open(); cmd.ExecuteNonQuery(); } }
/// <summary> /// Queues the email for relaying. /// </summary> private async Task <SmtpServerTransactionAsyncResult> QueueForRelayingAsync() { // The email is for relaying. Guid messageID = Guid.NewGuid(); // Look for any MTA control headers. MessageHeaderCollection headers = MessageManager.GetMessageHeaders(Data); // Will not be null if the SendGroupID header was present. MessageHeader ipGroupHeader = headers.SingleOrDefault(m => m.Name.Equals(MessageHeaderNames.SendGroupID, StringComparison.OrdinalIgnoreCase)); // Parameter will hold the MtaIPGroup that will be used to relay this message. VirtualMta.VirtualMtaGroup mtaGroup = null; int ipGroupID = 0; if (ipGroupHeader != null) { if (int.TryParse(ipGroupHeader.Value, out ipGroupID)) { mtaGroup = VirtualMta.VirtualMtaManager.GetVirtualMtaGroup(ipGroupID); } } #region Look for a send id, if one doesn't exist create it. MessageHeader sendIdHeader = headers.SingleOrDefault(h => h.Name.Equals(MessageHeaderNames.SendID, StringComparison.OrdinalIgnoreCase)); int internalSendId = -1; if (sendIdHeader != null) { Sends.Send sndID = await Sends.SendManager.Instance.GetSendAsync(sendIdHeader.Value); if (sndID.SendStatus == SendStatus.Discard) { return(SmtpServerTransactionAsyncResult.FailedSendDiscarding); } internalSendId = sndID.InternalID; } else { Sends.Send sndID = await Sends.SendManager.Instance.GetDefaultInternalSendIdAsync(); if (sndID.SendStatus == SendStatus.Discard) { return(SmtpServerTransactionAsyncResult.FailedSendDiscarding); } internalSendId = sndID.InternalID; } #endregion #region Generate Return Path string returnPath = string.Empty; // Can only return path to messages with one rcpt to if (RcptTo.Count == 1) { // Need to check to see if the message contains a return path overide domain. MessageHeader returnPathDomainOverrideHeader = headers.SingleOrDefault(h => h.Name.Equals(MessageHeaderNames.ReturnPathDomain, StringComparison.OrdinalIgnoreCase)); if (returnPathDomainOverrideHeader != null && MtaParameters.LocalDomains.Count(d => d.Hostname.Equals(returnPathDomainOverrideHeader.Value, StringComparison.OrdinalIgnoreCase)) > 0) { // The message contained a local domain in the returnpathdomain // header so use it instead of the default. returnPath = ReturnPathManager.GenerateReturnPath(RcptTo[0], internalSendId, returnPathDomainOverrideHeader.Value); } else { // The message didn't specify a return path overide or it didn't // contain a localdomain so use the default. returnPath = ReturnPathManager.GenerateReturnPath(RcptTo[0], internalSendId); } // Insert the return path header. Data = MessageManager.AddHeader(Data, new MessageHeader("Return-Path", "<" + returnPath + ">")); } else { // multiple rcpt's so can't have unique return paths, use generic mail from. returnPath = MailFrom; } #endregion #region Generate a message ID header string msgIDHeaderVal = "<" + messageID.ToString("N") + MailFrom.Substring(MailFrom.LastIndexOf("@")) + ">"; // If there is already a message header, remove it and add our own. required for feedback loop processing. if (headers.Count(h => h.Name.Equals("Message-ID", StringComparison.OrdinalIgnoreCase)) > 0) { Data = MessageManager.RemoveHeader(Data, "Message-ID"); } // Add the new message-id header. Data = MessageManager.AddHeader(Data, new MessageHeader("Message-ID", msgIDHeaderVal)); #endregion // Remove any control headers. headers = new MessageHeaderCollection(headers.Where(h => h.Name.StartsWith(MessageHeaderNames.HeaderNamePrefix, StringComparison.OrdinalIgnoreCase))); foreach (MessageHeader header in headers) { Data = MessageManager.RemoveHeader(Data, header.Name); } // If the MTA group doesn't exist or it's not got any IPs, use the default. if (mtaGroup == null || mtaGroup.VirtualMtaCollection.Count == 0) { ipGroupID = VirtualMta.VirtualMtaManager.GetDefaultVirtualMtaGroup().ID; } // Attempt to Enqueue the Email for Relaying. if (!QueueManager.Instance.Enqueue(messageID, ipGroupID, internalSendId, returnPath, RcptTo.ToArray(), Data)) { return(SmtpServerTransactionAsyncResult.FailedToEnqueue); } return(SmtpServerTransactionAsyncResult.SuccessMessageQueued); }