/// <summary> /// Executes specified actions. /// </summary> /// <param name="dvActions">Dataview what contains actions to be executed.</param> /// <param name="server">Reference to owner virtual server.</param> /// <param name="message">Recieved message.</param> /// <param name="sender">MAIL FROM: command value.</param> /// <param name="to">RCPT TO: commands values.</param> public GlobalMessageRuleActionResult DoActions(DataView dvActions, VirtualServer server, Stream message, string sender, string[] to) { // TODO: get rid of MemoryStream, move to Stream // bool messageChanged = false; bool deleteMessage = false; string storeFolder = null; string errorText = null; // Loop actions foreach (DataRowView drV in dvActions) { GlobalMessageRuleAction_enum action = (GlobalMessageRuleAction_enum)drV["ActionType"]; byte[] actionData = (byte[])drV["ActionData"]; // Reset stream position message.Position = 0; #region AutoResponse /* Description: Sends specified autoresponse message to sender. * Action data structure: * <ActionData> * <From></From> * <Message></Message> * </ActionData> */ if (action == GlobalMessageRuleAction_enum.AutoResponse) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); string smtp_from = table.GetValue("From"); string responseMsg = table.GetValue("Message"); // See if we have header field X-LS-MailServer-AutoResponse, never answer to auto response. MIME_h_Collection header = new MIME_h_Collection(new MIME_h_Provider()); header.Parse(new SmartStream(message, false)); if (header.Contains("X-LS-MailServer-AutoResponse")) { // Just skip } else { Mail_Message autoresponseMessage = Mail_Message.ParseFromByte(System.Text.Encoding.Default.GetBytes(responseMsg)); // Add header field 'X-LS-MailServer-AutoResponse:' autoresponseMessage.Header.Add(new MIME_h_Unstructured("X-LS-MailServer-AutoResponse", "")); // Update message date autoresponseMessage.Date = DateTime.Now; // Set To: if not explicity set if (autoresponseMessage.To == null || autoresponseMessage.To.Count == 0) { if (autoresponseMessage.To == null) { Mail_t_AddressList t = new Mail_t_AddressList(); t.Add(new Mail_t_Mailbox(null, sender)); autoresponseMessage.To = t; } else { autoresponseMessage.To.Add(new Mail_t_Mailbox(null, sender)); } } // Update Subject: variables, if any if (autoresponseMessage.Subject != null) { if (header.Contains("Subject")) { autoresponseMessage.Subject = autoresponseMessage.Subject.Replace("#SUBJECT", header.GetFirst("Subject").ValueToString().Trim()); } } // Sender missing, we can't send auto response. if (string.IsNullOrEmpty(sender)) { continue; } server.ProcessAndStoreMessage(smtp_from, new string[] { sender }, new MemoryStream(autoresponseMessage.ToByte(new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8)), null); } } #endregion #region Delete Message /* Description: Deletes message. * Action data structure: * <ActionData> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.DeleteMessage) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); deleteMessage = true; } #endregion #region ExecuteProgram /* Description: Executes specified program. * Action data structure: * <ActionData> * <Program></Program> * <Arguments></Arguments> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.ExecuteProgram) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); System.Diagnostics.ProcessStartInfo pInfo = new System.Diagnostics.ProcessStartInfo(); pInfo.FileName = table.GetValue("Program"); pInfo.Arguments = table.GetValue("Arguments"); pInfo.CreateNoWindow = true; System.Diagnostics.Process.Start(pInfo); } #endregion #region ForwardToEmail /* Description: Forwards email to specified email. * Action data structure: * <ActionData> * <Email></Email> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.ForwardToEmail) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); // See If message has X-LS-MailServer-ForwardedTo: and equals to "Email". // If so, then we have cross reference forward, don't forward that message MIME_h_Collection header = new MIME_h_Collection(new MIME_h_Provider()); header.Parse(new SmartStream(message, false)); bool forwardedAlready = false; if (header.Contains("X-LS-MailServer-ForwardedTo")) { foreach (MIME_h headerField in header["X-LS-MailServer-ForwardedTo"]) { if (headerField.ValueToString().Trim() == table.GetValue("Email")) { forwardedAlready = true; break; } } } // Reset stream position message.Position = 0; if (forwardedAlready) { // Just skip } else { // Add header field 'X-LS-MailServer-ForwardedTo:' MemoryStream msFwMessage = new MemoryStream(); byte[] fwField = System.Text.Encoding.Default.GetBytes("X-LS-MailServer-ForwardedTo: " + table.GetValue("Email") + "\r\n"); msFwMessage.Write(fwField, 0, fwField.Length); SCore.StreamCopy(message, msFwMessage); server.ProcessAndStoreMessage(sender, new string[] { table.GetValue("Email") }, msFwMessage, null); } } #endregion #region ForwardToHost /* Description: Forwards email to specified host. * All RCPT TO: recipients are preserved. * Action data structure: * <ActionData> * <Host></Host> * <Port></Port> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.ForwardToHost) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); foreach (string t in to) { message.Position = 0; server.RelayServer.StoreRelayMessage( Guid.NewGuid().ToString(), null, message, HostEndPoint.Parse(table.GetValue("Host") + ":" + table.GetValue("Port")), sender, t, null, SMTP_DSN_Notify.NotSpecified, SMTP_DSN_Ret.NotSpecified ); } message.Position = 0; } #endregion #region StoreToDiskFolder /* Description: Stores message to specified disk folder. * Action data structure: * <ActionData> * <Folder></Folder> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.StoreToDiskFolder) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); string folder = table.GetValue("Folder"); if (!folder.EndsWith("\\")) { folder += "\\"; } if (Directory.Exists(folder)) { using (FileStream fs = File.Create(folder + DateTime.Now.ToString("ddMMyyyyHHmmss") + "_" + Guid.NewGuid().ToString().Replace('-', '_').Substring(0, 8) + ".eml")){ SCore.StreamCopy(message, fs); } } else { // TODO: log error somewhere } } #endregion #region StoreToIMAPFolder /* Description: Stores message to specified IMAP folder. * Action data structure: * <ActionData> * <Folder></Folder> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.StoreToIMAPFolder) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); storeFolder = table.GetValue("Folder"); } #endregion #region AddHeaderField /* Description: Add specified header field to message main header. * Action data structure: * <ActionData> * <HeaderFieldName></HeaderFieldName> * <HeaderFieldValue></HeaderFieldValue> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.AddHeaderField) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); Mail_Message mime = Mail_Message.ParseFromStream(message); mime.Header.Add(new MIME_h_Unstructured(table.GetValue("HeaderFieldName"), table.GetValue("HeaderFieldValue"))); message.SetLength(0); mime.ToStream(message, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8); // messageChanged = true; } #endregion #region RemoveHeaderField /* Description: Removes specified header field from message mian header. * Action data structure: * <ActionData> * <HeaderFieldName></HeaderFieldName> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.RemoveHeaderField) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); Mail_Message mime = Mail_Message.ParseFromStream(message); mime.Header.RemoveAll(table.GetValue("HeaderFieldName")); message.SetLength(0); mime.ToStream(message, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8); // messageChanged = true; } #endregion #region SendErrorToClient /* Description: Sends error to currently connected client. NOTE: Error text may contain ASCII printable chars only and maximum length is 500. * Action data structure: * <ActionData> * <ErrorText></ErrorText> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.SendErrorToClient) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); errorText = table.GetValue("ErrorText"); } #endregion #region StoreToFTPFolder /* Description: Stores message to specified FTP server folder. * Action data structure: * <ActionData> * <Server></Server> * <Port></Server> * <User></User> * <Password></Password> * <Folder></Folder> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.StoreToFTPFolder) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); _MessageRuleAction_FTP_AsyncSend ftpSend = new _MessageRuleAction_FTP_AsyncSend( table.GetValue("Server"), Convert.ToInt32(table.GetValue("Port")), table.GetValue("User"), table.GetValue("Password"), table.GetValue("Folder"), message, DateTime.Now.ToString("ddMMyyyyHHmmss") + "_" + Guid.NewGuid().ToString().Replace('-', '_').Substring(0, 8) + ".eml" ); } #endregion #region PostToNNTPNewsGroup /* Description: Posts message to specified NNTP newsgroup. * Action data structure: * <ActionData> * <Server></Server> * <Port></Server> * <User></User> * <Password></Password> * <Newsgroup></Newsgroup> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.PostToNNTPNewsGroup) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); // Add header field "Newsgroups: newsgroup", NNTP server demands it. Mail_Message mime = Mail_Message.ParseFromStream(message); if (!mime.Header.Contains("Newsgroups:")) { mime.Header.Add(new MIME_h_Unstructured("Newsgroups:", table.GetValue("Newsgroup"))); } _MessageRuleAction_NNTP_Async nntp = new _MessageRuleAction_NNTP_Async( table.GetValue("Server"), Convert.ToInt32(table.GetValue("Port")), table.GetValue("Newsgroup"), new MemoryStream(mime.ToByte(new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8)) ); } #endregion #region PostToHTTP /* Description: Posts message to specified page via HTTP. * Action data structure: * <ActionData> * <URL></URL> * <FileName></FileName> * </ActionData> */ else if (action == GlobalMessageRuleAction_enum.PostToHTTP) { XmlTable table = new XmlTable("ActionData"); table.Parse(actionData); _MessageRuleAction_HTTP_Async http = new _MessageRuleAction_HTTP_Async( table.GetValue("URL"), message ); } #endregion } return(new GlobalMessageRuleActionResult(deleteMessage, storeFolder, errorText)); }
public GlobalMessageRuleActionResult DoActions(DataView dvActions, VirtualServer server, Stream message, string sender, string[] to) { bool deleteMessage = false; string storeFolder = null; string errorText = null; foreach (DataRowView dataRowView in dvActions) { GlobalMessageRuleActionType globalMessageRuleAction_enum = (GlobalMessageRuleActionType)dataRowView["ActionType"]; byte[] data = (byte[])dataRowView["ActionData"]; message.Position = 0L; if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)1) { XmlTable xmlTable = new XmlTable("ActionData"); xmlTable.Parse(data); string value = xmlTable.GetValue("From"); string value2 = xmlTable.GetValue("Message"); MIME_h_Collection mIME_h_Collection = new MIME_h_Collection(new MIME_h_Provider()); mIME_h_Collection.Parse(new SmartStream(message, false)); if (!mIME_h_Collection.Contains("X-LS-MailServer-AutoResponse")) { Mail_Message mail_Message = Mail_Message.ParseFromByte(Encoding.UTF8.GetBytes(value2)); mail_Message.Header.Add(new MIME_h_Unstructured("X-LS-MailServer-AutoResponse", "")); mail_Message.Date = DateTime.Now; if (mail_Message.To == null || mail_Message.To.Count == 0) { if (mail_Message.To == null) { mail_Message.To = new Mail_t_AddressList { new Mail_t_Mailbox(null, sender) }; } else { mail_Message.To.Add(new Mail_t_Mailbox(null, sender)); } } if (mail_Message.Subject != null && mIME_h_Collection.Contains("Subject")) { mail_Message.Subject = mail_Message.Subject.Replace("#SUBJECT", mIME_h_Collection.GetFirst("Subject").ValueToString().Trim()); } if (!string.IsNullOrEmpty(sender)) { server.ProcessAndStoreMessage(value, new string[] { sender }, new MemoryStream(mail_Message.ToByte(new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8)), null); } } } else if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.DeleteMessage) { XmlTable xmlTable2 = new XmlTable("ActionData"); xmlTable2.Parse(data); deleteMessage = true; } else if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.ExecuteProgram) { XmlTable xmlTable3 = new XmlTable("ActionData"); xmlTable3.Parse(data); Process.Start(new ProcessStartInfo { FileName = xmlTable3.GetValue("Program"), Arguments = xmlTable3.GetValue("Arguments"), CreateNoWindow = true }); } else if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.ForwardToEmail) { XmlTable xmlTable4 = new XmlTable("ActionData"); xmlTable4.Parse(data); MIME_h_Collection mIME_h_Collection2 = new MIME_h_Collection(new MIME_h_Provider()); mIME_h_Collection2.Parse(new SmartStream(message, false)); bool flag = false; if (mIME_h_Collection2.Contains("X-LS-MailServer-ForwardedTo")) { MIME_h[] array = mIME_h_Collection2["X-LS-MailServer-ForwardedTo"]; for (int i = 0; i < array.Length; i++) { MIME_h mIME_h = array[i]; if (mIME_h.ValueToString().Trim() == xmlTable4.GetValue("Email")) { flag = true; break; } } } message.Position = 0L; if (!flag) { MemoryStream memoryStream = new MemoryStream(); byte[] bytes = Encoding.UTF8.GetBytes("X-LS-MailServer-ForwardedTo: " + xmlTable4.GetValue("Email") + "\r\n"); memoryStream.Write(bytes, 0, bytes.Length); SCore.StreamCopy(message, memoryStream); server.ProcessAndStoreMessage(sender, new string[] { xmlTable4.GetValue("Email") }, memoryStream, null); } } else if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.ForwardToHost) { XmlTable xmlTable5 = new XmlTable("ActionData"); xmlTable5.Parse(data); for (int j = 0; j < to.Length; j++) { string to2 = to[j]; message.Position = 0L; server.RelayServer.StoreRelayMessage(Guid.NewGuid().ToString(), null, message, HostEndPoint.Parse(xmlTable5.GetValue("Host") + ":" + xmlTable5.GetValue("Port")), sender, to2, null, SMTP_DSN_Notify.NotSpecified, SMTP_DSN_Ret.NotSpecified); } message.Position = 0L; } else { if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.StoreToDiskFolder) { XmlTable xmlTable6 = new XmlTable("ActionData"); xmlTable6.Parse(data); string text = xmlTable6.GetValue("Folder"); if (!text.EndsWith("\\")) { text += "\\"; } if (!Directory.Exists(text)) { continue; } using (FileStream fileStream = File.Create(string.Concat(new string[] { text, DateTime.Now.ToString("ddMMyyyyHHmmss"), "_", Guid.NewGuid().ToString().Replace('-', '_').Substring(0, 8), ".eml" }))) { SCore.StreamCopy(message, fileStream); continue; } } if (globalMessageRuleAction_enum == GlobalMessageRuleActionType.StoreToIMAPFolder) { XmlTable xmlTable7 = new XmlTable("ActionData"); xmlTable7.Parse(data); storeFolder = xmlTable7.GetValue("Folder"); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)8) { XmlTable xmlTable8 = new XmlTable("ActionData"); xmlTable8.Parse(data); Mail_Message mail_Message2 = Mail_Message.ParseFromStream(message); mail_Message2.Header.Add(new MIME_h_Unstructured(xmlTable8.GetValue("HeaderFieldName"), xmlTable8.GetValue("HeaderFieldValue"))); message.SetLength(0L); mail_Message2.ToStream(message, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)9) { XmlTable xmlTable9 = new XmlTable("ActionData"); xmlTable9.Parse(data); Mail_Message mail_Message3 = Mail_Message.ParseFromStream(message); mail_Message3.Header.RemoveAll(xmlTable9.GetValue("HeaderFieldName")); message.SetLength(0L); mail_Message3.ToStream(message, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)10) { XmlTable xmlTable10 = new XmlTable("ActionData"); xmlTable10.Parse(data); errorText = xmlTable10.GetValue("ErrorText"); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)11) { XmlTable xmlTable11 = new XmlTable("ActionData"); xmlTable11.Parse(data); new _MessageRuleAction_FTP_AsyncSend(xmlTable11.GetValue("Server"), Convert.ToInt32(xmlTable11.GetValue("Port")), xmlTable11.GetValue("User"), xmlTable11.GetValue("Password"), xmlTable11.GetValue("Folder"), message, DateTime.Now.ToString("ddMMyyyyHHmmss") + "_" + Guid.NewGuid().ToString().Replace('-', '_').Substring(0, 8) + ".eml"); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)12) { XmlTable xmlTable12 = new XmlTable("ActionData"); xmlTable12.Parse(data); Mail_Message mail_Message4 = Mail_Message.ParseFromStream(message); if (!mail_Message4.Header.Contains("Newsgroups:")) { mail_Message4.Header.Add(new MIME_h_Unstructured("Newsgroups:", xmlTable12.GetValue("Newsgroup"))); } new _MessageRuleAction_NNTP_Async(xmlTable12.GetValue("Server"), Convert.ToInt32(xmlTable12.GetValue("Port")), xmlTable12.GetValue("Newsgroup"), new MemoryStream(mail_Message4.ToByte(new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8))); } else if (globalMessageRuleAction_enum == (GlobalMessageRuleActionType)13) { XmlTable xmlTable13 = new XmlTable("ActionData"); xmlTable13.Parse(data); new _MessageRuleAction_HTTP_Async(xmlTable13.GetValue("URL"), message); } } } return(new GlobalMessageRuleActionResult(deleteMessage, storeFolder, errorText)); }