/// <summary> /// Raises event ValidateIP event. /// </summary> /// <param name="session">Reference to current smtp session.</param> internal ValidateIP_EventArgs OnValidate_IpAddress(SMTP_Session session) { ValidateIP_EventArgs oArg = new ValidateIP_EventArgs(session.LocalEndPoint, session.RemoteEndPoint); if (this.ValidateIPAddress != null) { this.ValidateIPAddress(this, oArg); } session.Tag = oArg.SessionTag; return(oArg); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b> or <b>reply</b> is null reference.</exception> public SMTP_e_Started(SMTP_Session session, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pReply = reply; }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="to">RCPT TO: value.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>to</b> or <b>reply</b> is null reference.</exception> public SMTP_e_RcptTo(SMTP_Session session, SMTP_RcptTo to, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (to == null) { throw new ArgumentNullException("from"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pRcptTo = to; m_pReply = reply; }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="from">MAIL FROM: value.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>from</b> or <b>reply</b> is null reference.</exception> public SMTP_e_MailFrom(SMTP_Session session, SMTP_MailFrom from, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (from == null) { throw new ArgumentNullException("from"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pMailFrom = from; m_pReply = reply; }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="stream">Message stream.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>stream</b> or <b>reply</b> is null reference.</exception> public SMTP_e_MessageStored(SMTP_Session session, Stream stream, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (stream == null) { throw new ArgumentNullException("stream"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pStream = stream; m_pReply = reply; }
/// <summary> /// Initialize and start new session here. Session isn't added to session list automatically, /// session must add itself to server session list by calling AddSession(). /// </summary> /// <param name="socket">Connected client socket.</param> /// <param name="bindInfo">BindInfo what accepted socket.</param> protected override void InitNewSession(Socket socket, IPBindInfo bindInfo) { // Check maximum conncurent connections from 1 IP. if (m_MaxConnectionsPerIP > 0) { lock (this.Sessions){ int nSessions = 0; foreach (SocketServerSession s in this.Sessions) { IPEndPoint ipEndpoint = s.RemoteEndPoint; if (ipEndpoint != null) { if (ipEndpoint.Address.Equals(((IPEndPoint)socket.RemoteEndPoint).Address)) { nSessions++; } } // Maimum allowed exceeded if (nSessions >= m_MaxConnectionsPerIP) { socket.Send(System.Text.Encoding.ASCII.GetBytes("421 Maximum connections from your IP address is exceeded, try again later !\r\n")); socket.Shutdown(SocketShutdown.Both); socket.Close(); return; } } } } string sessionID = Guid.NewGuid().ToString(); SocketEx socketEx = new SocketEx(socket); if (LogCommands) { socketEx.Logger = new SocketLogger(socket, this.SessionLog); socketEx.Logger.SessionID = sessionID; } SMTP_Session session = new SMTP_Session(sessionID, socketEx, bindInfo, this); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="domain">Ehlo/Helo domain name.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>domain</b> or <b>reply</b> is null reference.</exception> /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception> public SMTP_e_Ehlo(SMTP_Session session, string domain, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (domain == null) { throw new ArgumentNullException("domain"); } if (domain == string.Empty) { throw new ArgumentException("Argument 'domain' value must be sepcified.", "domain"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_Domain = domain; m_pReply = reply; }
public bool Filter(string from, IMailServerManagementApi api, SMTP_Session session, out string errorText) { errorText = null; bool result = true; if (session.IsAuthenticated || this.IsPrivateIP(session.RemoteEndPoint.Address)) { return(true); } try { DataSet dataSet = new DataSet(); dataSet.Tables.Add("General"); dataSet.Tables["General"].Columns.Add("CheckHelo"); dataSet.Tables["General"].Columns.Add("LogRejections"); dataSet.Tables.Add("BlackListSettings"); dataSet.Tables["BlackListSettings"].Columns.Add("ErrorText"); dataSet.Tables.Add("BlackList"); dataSet.Tables["BlackList"].Columns.Add("IP"); dataSet.Tables.Add("Servers"); dataSet.Tables["Servers"].Columns.Add("Cost"); dataSet.Tables["Servers"].Columns.Add("Server"); dataSet.Tables["Servers"].Columns.Add("DefaultRejectionText"); dataSet.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DnsBlackList.xml"); bool flag = false; if (dataSet.Tables["General"].Rows.Count == 1) { if (Convert.ToBoolean(dataSet.Tables["General"].Rows[0]["CheckHelo"])) { DnsServerResponse dnsServerResponse = Dns_Client.Static.Query(session.EhloHost, DNS_QType.A); if (dnsServerResponse.ConnectionOk && dnsServerResponse.ResponseCode != DNS_RCode.SERVER_FAILURE) { bool flag2 = false; DNS_rr_A[] aRecords = dnsServerResponse.GetARecords(); for (int i = 0; i < aRecords.Length; i++) { DNS_rr_A dNS_rr_A = aRecords[i]; if (session.RemoteEndPoint.Address.Equals(dNS_rr_A.IP)) { flag2 = true; break; } } if (!flag2) { errorText = "Not valid DNS EHLO/HELO name for your IP '" + session.EhloHost + "' !"; bool result2 = false; return(result2); } } } flag = ConvertEx.ToBoolean(dataSet.Tables["General"].Rows[0]["LogRejections"]); } foreach (DataRow dataRow in dataSet.Tables["BlackList"].Rows) { if (this.IsAstericMatch(dataRow["IP"].ToString(), session.RemoteEndPoint.Address.ToString())) { errorText = dataSet.Tables["BlackListSettings"].Rows[0]["ErrorText"].ToString(); bool result2 = false; return(result2); } } foreach (DataRow dataRow2 in dataSet.Tables["Servers"].Rows) { DnsServerResponse dnsServerResponse2 = Dns_Client.Static.Query(this.ReverseIP(session.RemoteEndPoint.Address) + "." + dataRow2["Server"].ToString(), DNS_QType.ANY); DNS_rr_A[] aRecords2 = dnsServerResponse2.GetARecords(); if (aRecords2.Length > 0) { if (flag) { this.WriteFilterLog(string.Concat(new string[] { "Sender:", from, " IP:", session.RemoteEndPoint.Address.ToString(), " blocked\r\n" })); } errorText = dataRow2["DefaultRejectionText"].ToString(); if (dnsServerResponse2.GetTXTRecords().Length > 0) { errorText = dnsServerResponse2.GetTXTRecords()[0].Text; } if (errorText == "") { errorText = "You are in '" + dataRow2["Server"].ToString() + "' rejection list !"; } bool result2 = false; return(result2); } } } catch { } return(result); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Reference to smtp session.</param> /// <param name="mailFrom">Sender email address.</param> public ValidateSender_EventArgs(SMTP_Session session, string mailFrom) { m_pSession = session; m_MailFrom = mailFrom; }
/// <summary> /// Checks if specified message matches to specified criteria. /// </summary> /// <param name="syntaxCheckOnly">Specifies if syntax check is only done. If true no matching is done.</param> /// <param name="r">Match expression reader what contains match expression.</param> /// <param name="mailFrom">SMTP MAIL FROM: command email value.</param> /// <param name="rcptTo">SMTP RCPT TO: command email values.</param> /// <param name="smtpSession">SMTP current session.</param> /// <param name="mime">Message to match.</param> /// <param name="messageSize">Message size in bytes.</param> /// <returns>Returns true if message matches to specified criteria.</returns> private bool Match(bool syntaxCheckOnly, LumiSoft.Net.StringReader r, string mailFrom, string[] rcptTo, SMTP_Session smtpSession, Mail_Message mime, int messageSize) { /* Possible keywords order * At first there can be NOT,parethesized or matcher * After NOT, parethesized or matcher * After matcher, AND or OR * After OR, NOT,parethesized or matcher * After AND, NOT,parethesized or matcher * After parethesized, NOT or matcher */ PossibleClauseItem possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.NOT | PossibleClauseItem.Matcher; bool lastMatchValue = false; // Empty string passed r.ReadToFirstChar(); if (r.Available == 0) { throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !"); } // Parse while there are expressions or get error while (r.Available > 0) { r.ReadToFirstChar(); // Syntax check must consider that there is alwas match !!! if (syntaxCheckOnly) { lastMatchValue = true; } #region () Groupped matchers // () Groupped matchers if (r.StartsWith("(")) { lastMatchValue = Match(syntaxCheckOnly, new LumiSoft.Net.StringReader(r.ReadParenthesized()), mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT; } #endregion #region AND clause // AND clause else if (r.StartsWith("and", false)) { // See if AND allowed if ((possibleClauseItems & PossibleClauseItem.AND) == 0) { throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !"); } // Last match value is false, no need to check next conditions if (!lastMatchValue) { return(false); } // Remove AND r.ReadWord(); r.ReadToFirstChar(); lastMatchValue = Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT; } #endregion #region OR clause // OR clause else if (r.StartsWith("or", false)) { // See if OR allowed if ((possibleClauseItems & PossibleClauseItem.OR) == 0) { throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !"); } // Remove OR r.ReadWord(); r.ReadToFirstChar(); // Last match value is false, then we need to check next condition. // Otherwise OR is matched already, just eat next matcher. if (lastMatchValue) { // Skip next clause Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); } else { lastMatchValue = Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); } possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher | PossibleClauseItem.NOT; } #endregion #region NOT clause // NOT clause else if (r.StartsWith("not", false)) { // See if NOT allowed if ((possibleClauseItems & PossibleClauseItem.NOT) == 0) { throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected !"); } // Remove NOT r.ReadWord(); r.ReadToFirstChar(); // Just reverse match result value lastMatchValue = !Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItems = PossibleClauseItem.Parenthesizes | PossibleClauseItem.Matcher; } #endregion else { // See if matcher allowed if ((possibleClauseItems & PossibleClauseItem.Matcher) == 0) { throw new Exception("Invalid syntax: '" + ClauseItemsToString(possibleClauseItems) + "' expected ! \r\n\r\n Near: '" + r.OriginalString.Substring(0, r.Position) + "'"); } // 1) matchsource // 2) keyword // Read match source string word = r.ReadWord(); if (word == null) { throw new Exception("Invalid syntax: matcher is missing !"); } word = word.ToLower(); string[] matchSourceValues = new string[] {}; #region smtp.mail_from // SMTP command MAIL FROM: value. // smtp.mail_from if (word == "smtp.mail_from") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { mailFrom }; } } #endregion #region smtp.rcpt_to // SMTP command RCPT TO: values. // smtp.mail_to else if (word == "smtp.rcpt_to") { if (!syntaxCheckOnly) { matchSourceValues = rcptTo; } } #endregion #region smtp.ehlo // SMTP command EHLO/HELO: value. // smtp.ehlo else if (word == "smtp.ehlo") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { smtpSession.EhloHost }; } } #endregion #region smtp.authenticated // Specifies if SMTP session is authenticated. // smtp.authenticated else if (word == "smtp.authenticated") { if (!syntaxCheckOnly) { if (smtpSession != null) { matchSourceValues = new string[] { smtpSession.IsAuthenticated.ToString() }; } } } #endregion #region smtp.user // SMTP authenticated user name. Empy string "" if not authenticated. // smtp.user else if (word == "smtp.user") { if (!syntaxCheckOnly) { if (smtpSession != null && smtpSession.AuthenticatedUserIdentity != null) { matchSourceValues = new string[] { smtpSession.AuthenticatedUserIdentity.Name }; } } } #endregion #region smtp.remote_ip // SMTP session connected client IP address. // smtp.remote_ip else if (word == "smtp.remote_ip") { if (!syntaxCheckOnly) { if (smtpSession != null) { matchSourceValues = new string[] { smtpSession.RemoteEndPoint.Address.ToString() }; } } } #endregion #region message.size // Message size in bytes. // message.size else if (word == "message.size") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { messageSize.ToString() }; } } #endregion #region message.header <SP> "HeaderFieldName:" // Message main header header field. If multiple header fields, then all are checked. // message.header <SP> "HeaderFieldName:" else if (word == "message.header") { string headerFieldName = r.ReadWord(); if (headerFieldName == null) { throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}"); } if (!syntaxCheckOnly) { if (mime.Header.Contains(headerFieldName)) { MIME_h[] fields = mime.Header[headerFieldName]; matchSourceValues = new string[fields.Length]; for (int i = 0; i < matchSourceValues.Length; i++) { matchSourceValues[i] = fields[i].ValueToString(); } } } } #endregion #region message.all_headers <SP> "HeaderFieldName:" // Any mime entity header header field. If multiple header fields, then all are checked. // message.all_headers <SP> "HeaderFieldName:" else if (word == "message.all_headers") { string headerFieldName = r.ReadWord(); if (headerFieldName == null) { throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}"); } if (!syntaxCheckOnly) { List <string> values = new List <string>(); foreach (MIME_Entity entity in mime.AllEntities) { if (entity.Header.Contains(headerFieldName)) { MIME_h[] fields = entity.Header[headerFieldName]; for (int i = 0; i < fields.Length; i++) { values.Add(fields[i].ValueToString()); } } } matchSourceValues = values.ToArray(); } } #endregion #region message.body_text // Message body text. // message.body_text else if (word == "message.body_text") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { mime.BodyText }; } } #endregion #region message.body_html // Message body html. // message.body_html else if (word == "message.body_html") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { mime.BodyHtmlText }; } } #endregion #region message.content_md5 // Message any mime entity decoded data MD5 hash. // message.content_md5 else if (word == "message.content_md5") { if (!syntaxCheckOnly) { List <string> values = new List <string>(); foreach (MIME_Entity entity in mime.AllEntities) { try{ if (entity.Body is MIME_b_SinglepartBase) { byte[] data = ((MIME_b_SinglepartBase)entity.Body).Data; if (data != null) { System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); values.Add(System.Text.Encoding.Default.GetString(md5.ComputeHash(data))); } } } catch { // Message data parsing failed, just skip that entity md5 } } matchSourceValues = values.ToArray(); } } #endregion #region sys.date_time // System current date time. Format: yyyy.MM.dd HH:mm:ss. // sys.date_time else if (word == "sys.date_time") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") }; } } #endregion #region sys.date // System current date. Format: yyyy.MM.dd. // sys.date else if (word == "sys.date") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { DateTime.Today.ToString("dd.MM.yyyy") }; } } #endregion #region sys.time // System current time. Format: HH:mm:ss. // sys.time else if (word == "sys.time") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { DateTime.Now.ToString("HH:mm:ss") }; } } #endregion #region sys.day_of_week // Day of week. Days: sunday,monday,tuesday,wednesday,thursday,friday,saturday. // sys.day_of_week else if (word == "sys.day_of_week") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { DateTime.Today.DayOfWeek.ToString() }; } } #endregion /* * // Day of month. Format: 1 - 31. If no so much days in month, then replaced with month max days. * // sys.day_of_month * else if(word == "sys.day_of_month"){ * } */ #region sys.day_of_year // Month of year. Format: 1 - 12. // sys.day_of_year else if (word == "sys.day_of_year") { if (!syntaxCheckOnly) { matchSourceValues = new string[] { DateTime.Today.ToString("M") }; } } #endregion #region Unknown // Unknown else { throw new Exception("Unknown match source '" + word + "' !"); } #endregion /* If we reach so far, then we have valid match sorce and compare value. * Just do compare. */ // Reset lastMatch result lastMatchValue = false; // Read matcher word = r.ReadWord(true, new char[] { ' ' }, true); if (word == null) { throw new Exception("Invalid syntax: operator is missing ! \r\n\r\n Near: '" + r.OriginalString.Substring(0, r.Position) + "'"); } word = word.ToLower(); #region * <SP> "astericPattern" // * <SP> "astericPattern" if (word == "*") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (SCore.IsAstericMatch(val, matchSourceValue.ToLower())) { lastMatchValue = true; break; } } } } #endregion #region !* <SP> "astericPattern" // !* <SP> "astericPattern" else if (word == "!*") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (SCore.IsAstericMatch(val, matchSourceValue.ToLower())) { lastMatchValue = false; break; } } } } #endregion #region == <SP> "value" // == <SP> "value" else if (word == "==") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (val == matchSourceValue.ToLower()) { lastMatchValue = true; break; } } } } #endregion #region != <SP> "value" // != <SP> "value" else if (word == "!=") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found, then already value equals foreach (string matchSourceValue in matchSourceValues) { if (val == matchSourceValue.ToLower()) { lastMatchValue = false; break; } lastMatchValue = true; } } } #endregion #region >= <SP> "value" // >= <SP> "value" else if (word == ">=") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (matchSourceValue.ToLower().CompareTo(val) >= 0) { lastMatchValue = true; break; } } } } #endregion #region <= <SP> "value" // <= <SP> "value" else if (word == "<=") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (matchSourceValue.ToLower().CompareTo(val) <= 0) { lastMatchValue = true; break; } } } } #endregion #region > <SP> "value" // > <SP> "value" else if (word == ">") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (matchSourceValue.ToLower().CompareTo(val) > 0) { lastMatchValue = true; break; } } } } #endregion #region < <SP> "value" // < <SP> "value" else if (word == "<") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (matchSourceValue.ToLower().CompareTo(val) < 0) { lastMatchValue = true; break; } } } } #endregion #region regex <SP> "value" // Regex <SP> "value" else if (word == "regex") { string val = r.ReadWord(); if (val == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } val = val.ToLower(); if (!syntaxCheckOnly) { // We check matchSourceValues when first is found foreach (string matchSourceValue in matchSourceValues) { if (Regex.IsMatch(val, matchSourceValue.ToLower())) { lastMatchValue = true; break; } } } } #endregion #region Unknown // Unknown else { throw new Exception("Unknown keword '" + word + "' !"); } #endregion possibleClauseItems = PossibleClauseItem.AND | PossibleClauseItem.OR; } } return(lastMatchValue); }
/// <summary> /// Checks if specified message matches to specified criteria. /// </summary> /// <param name="matchExpression">Match expression.</param> /// <param name="mailFrom">SMTP MAIL FROM: command email value.</param> /// <param name="rcptTo">SMTP RCPT TO: command email values.</param> /// <param name="smtpSession">SMTP current session.</param> /// <param name="mime">Message to match.</param> /// <param name="messageSize">Message size in bytes.</param> /// <returns>Returns true if message matches to specified criteria.</returns> public bool Match(string matchExpression, string mailFrom, string[] rcptTo, SMTP_Session smtpSession, Mail_Message mime, int messageSize) { LumiSoft.Net.StringReader r = new LumiSoft.Net.StringReader(matchExpression); return(Match(false, r, mailFrom, rcptTo, smtpSession, mime, messageSize)); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Reference to smtp session.</param> /// <param name="eAddress">Email address of recipient.</param> /// <param name="messageSize">Message size.</param> public ValidateMailboxSize_EventArgs(SMTP_Session session, string eAddress, long messageSize) { m_pSession = session; m_eAddress = eAddress; m_MsgSize = messageSize; }
/// <summary> /// Filters message. /// </summary> /// <param name="messageStream">Message stream which to filter.</param> /// <param name="filteredStream">Filtered stream.</param> /// <param name="sender">Senders email address.</param> /// <param name="recipients">Recipients email addresses.</param> /// <param name="api">Access to server API.</param> /// <param name="session">Reference to SMTP session.</param> /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 500 chars maximum.</param> public FilterResult Filter(Stream messageStream, out Stream filteredStream, string sender, string[] recipients, IMailServerApi api, SMTP_Session session, out string errorText) { errorText = null; filteredStream = null; try{ // Store message to tmp file string file = API_Utlis.PathFix(Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml"); using (FileStream fs = File.Create(file)){ byte[] data = new byte[messageStream.Length]; messageStream.Read(data, 0, data.Length); fs.Write(data, 0, data.Length); } // Execute virus program to scan tmp message // #FileName - place holder is replaced with file DataSet ds = new DataSet(); ds.Tables.Add("Settings"); ds.Tables["Settings"].Columns.Add("Program"); ds.Tables["Settings"].Columns.Add("Arguments"); ds.Tables["Settings"].Columns.Add("VirusExitCode"); ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsVirusFilter_db.xml"); string virusSoft = ds.Tables["Settings"].Rows[0]["Program"].ToString(); string virusSoftArgs = ds.Tables["Settings"].Rows[0]["Arguments"].ToString().Replace("#FileName", file); int virusExitCode = ConvertEx.ToInt32(ds.Tables["Settings"].Rows[0]["Program"], 1); int exitCode = 0; System.Diagnostics.ProcessStartInfo sInf = new System.Diagnostics.ProcessStartInfo(virusSoft, virusSoftArgs); sInf.CreateNoWindow = true; sInf.UseShellExecute = false; System.Diagnostics.Process p = System.Diagnostics.Process.Start(sInf); if (p != null) { p.WaitForExit(60000); exitCode = p.ExitCode; } if (File.Exists(file)) { // Return scanned message and delete tmp file using (FileStream fs = File.OpenRead(file)){ byte[] data = new byte[fs.Length]; fs.Read(data, 0, data.Length); filteredStream = new MemoryStream(data); } File.Delete(file); } // Virus scanner deleted messaeg, probably contains virus else { virusExitCode = exitCode; } // Do exit code mapping if (virusExitCode == exitCode) { errorText = "Message is blocked, contains virus !"; return(FilterResult.Error); } } catch (Exception x) { string dummy = x.Message; // Virus scanning failed, allow message through filteredStream = messageStream; } return(FilterResult.Store); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Reference to smtp session.</param> /// <param name="msgStream">Message stream.</param> public NewMail_EventArgs(SMTP_Session session, MemoryStream msgStream) { m_pSession = session; m_MsgStream = msgStream; }
public FilterResult Filter(Stream messageStream, out Stream filteredStream, string sender, string[] recipients, IMailServerManagementApi api, SMTP_Session session, out string errorText) { errorText = null; filteredStream = null; string text = PathHelper.PathFix(Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml"); try { using (FileStream fileStream = File.Create(text)) { byte[] array = new byte[messageStream.Length]; messageStream.Read(array, 0, array.Length); fileStream.Write(array, 0, array.Length); } DataSet dataSet = new DataSet(); dataSet.Tables.Add("Settings"); dataSet.Tables["Settings"].Columns.Add("Program"); dataSet.Tables["Settings"].Columns.Add("Arguments"); dataSet.Tables["Settings"].Columns.Add("VirusExitCode"); dataSet.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\VirusScan.xml"); string fileName = dataSet.Tables["Settings"].Rows[0]["Program"].ToString(); string arguments = dataSet.Tables["Settings"].Rows[0]["Arguments"].ToString().Replace("#FileName", text); int num = ConvertEx.ToInt32(dataSet.Tables["Settings"].Rows[0]["Program"], 1); int num2 = 0; Process process = Process.Start(new ProcessStartInfo(fileName, arguments) { CreateNoWindow = true, UseShellExecute = false }); if (process != null) { process.WaitForExit(60000); num2 = process.ExitCode; } if (File.Exists(text)) { using (FileStream fileStream2 = File.OpenRead(text)) { byte[] array2 = new byte[fileStream2.Length]; fileStream2.Read(array2, 0, array2.Length); filteredStream = new MemoryStream(array2); } File.Delete(text); } else { num = num2; } if (num == num2) { errorText = "Message is blocked, contains virus !"; return(FilterResult.Error); } } catch (Exception ex) { string arg_243_0 = ex.Message; filteredStream = messageStream; } finally { if (File.Exists(text)) { File.Delete(text); } } return(FilterResult.Store); }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Reference to smtp session.</param> /// <param name="mailTo">Recipient email address.</param> /// <param name="authenticated">Specifies if connected user is authenticated.</param> public ValidateRecipient_EventArgs(SMTP_Session session, string mailTo, bool authenticated) { m_pSession = session; m_MailTo = mailTo; m_Authenticated = authenticated; }
/// <summary> /// Default constructor. /// </summary> /// <param name="session">Reference to calling SMTP sesssion.</param> public GetMessageStoreStream_eArgs(SMTP_Session session) { m_pSession = session; m_pStoreStream = new MemoryStream(); }
private bool Match(bool syntaxCheckOnly, System.NetworkToolkit.StringReader r, string mailFrom, string[] rcptTo, SMTP_Session smtpSession, Mail_Message mime, int messageSize) { GlobalMessageRuleProcessor.PossibleClauseItem possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 56; bool flag = false; r.ReadToFirstChar(); if (r.Available == 0L) { throw new Exception("Invalid syntax: '" + this.ClauseItemsToString(possibleClauseItem) + "' expected !"); } while (r.Available > 0L) { r.ReadToFirstChar(); if (syntaxCheckOnly) { flag = true; } if (r.StartsWith("(")) { flag = this.Match(syntaxCheckOnly, new System.NetworkToolkit.StringReader(r.ReadParenthesized()), mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 56; } else if (r.StartsWith("and", false)) { if ((possibleClauseItem & GlobalMessageRuleProcessor.PossibleClauseItem.AND) == (GlobalMessageRuleProcessor.PossibleClauseItem) 0) { throw new Exception("Invalid syntax: '" + this.ClauseItemsToString(possibleClauseItem) + "' expected !"); } if (!flag) { return(false); } r.ReadWord(); r.ReadToFirstChar(); flag = this.Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 56; } else if (r.StartsWith("or", false)) { if ((possibleClauseItem & GlobalMessageRuleProcessor.PossibleClauseItem.OR) == (GlobalMessageRuleProcessor.PossibleClauseItem) 0) { throw new Exception("Invalid syntax: '" + this.ClauseItemsToString(possibleClauseItem) + "' expected !"); } r.ReadWord(); r.ReadToFirstChar(); if (flag) { this.Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); } else { flag = this.Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); } possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 56; } else if (r.StartsWith("not", false)) { if ((possibleClauseItem & GlobalMessageRuleProcessor.PossibleClauseItem.NOT) == (GlobalMessageRuleProcessor.PossibleClauseItem) 0) { throw new Exception("Invalid syntax: '" + this.ClauseItemsToString(possibleClauseItem) + "' expected !"); } r.ReadWord(); r.ReadToFirstChar(); flag = !this.Match(syntaxCheckOnly, r, mailFrom, rcptTo, smtpSession, mime, messageSize); possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 48; } else { if ((possibleClauseItem & GlobalMessageRuleProcessor.PossibleClauseItem.Matcher) == (GlobalMessageRuleProcessor.PossibleClauseItem) 0) { throw new Exception(string.Concat(new string[] { "Invalid syntax: '", this.ClauseItemsToString(possibleClauseItem), "' expected ! \r\n\r\n Near: '", r.OriginalString.Substring(0, r.Position), "'" })); } string text = r.ReadWord(); if (text == null) { throw new Exception("Invalid syntax: matcher is missing !"); } text = text.ToLower(); string[] array = new string[0]; if (text == "smtp.mail_from") { if (!syntaxCheckOnly) { array = new string[] { mailFrom }; } } else if (text == "smtp.rcpt_to") { if (!syntaxCheckOnly) { array = rcptTo; } } else if (text == "smtp.ehlo") { if (!syntaxCheckOnly) { array = new string[] { smtpSession.EhloHost }; } } else if (text == "smtp.authenticated") { if (!syntaxCheckOnly && smtpSession != null) { array = new string[] { smtpSession.IsAuthenticated.ToString() }; } } else if (text == "smtp.user") { if (!syntaxCheckOnly && smtpSession != null && smtpSession.AuthenticatedUserIdentity != null) { array = new string[] { smtpSession.AuthenticatedUserIdentity.Name }; } } else if (text == "smtp.remote_ip") { if (!syntaxCheckOnly && smtpSession != null) { array = new string[] { smtpSession.RemoteEndPoint.Address.ToString() }; } } else if (text == "message.size") { if (!syntaxCheckOnly) { array = new string[] { messageSize.ToString() }; } } else if (text == "message.header") { string text2 = r.ReadWord(); if (text2 == null) { throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}"); } if (!syntaxCheckOnly && mime.Header.Contains(text2)) { MIME_h[] array2 = mime.Header[text2]; array = new string[array2.Length]; for (int i = 0; i < array.Length; i++) { array[i] = array2[i].ValueToString(); } } } else if (text == "message.all_headers") { string text3 = r.ReadWord(); if (text3 == null) { throw new Exception("Match source MainHeaderField HeaderFieldName is missing ! Syntax:{MainHeaderField <SP> \"HeaderFieldName:\"}"); } if (!syntaxCheckOnly) { List <string> list = new List <string>(); MIME_Entity[] allEntities = mime.AllEntities; for (int j = 0; j < allEntities.Length; j++) { MIME_Entity mIME_Entity = allEntities[j]; if (mIME_Entity.Header.Contains(text3)) { MIME_h[] array3 = mIME_Entity.Header[text3]; for (int k = 0; k < array3.Length; k++) { list.Add(array3[k].ValueToString()); } } } array = list.ToArray(); } } else if (text == "message.body_text") { if (!syntaxCheckOnly) { array = new string[] { mime.BodyText }; } } else if (text == "message.body_html") { if (!syntaxCheckOnly) { array = new string[] { mime.BodyHtmlText }; } } else if (text == "message.content_md5") { if (!syntaxCheckOnly) { List <string> list2 = new List <string>(); MIME_Entity[] allEntities2 = mime.AllEntities; for (int l = 0; l < allEntities2.Length; l++) { MIME_Entity mIME_Entity2 = allEntities2[l]; try { if (mIME_Entity2.Body is MIME_b_SinglepartBase) { byte[] data = ((MIME_b_SinglepartBase)mIME_Entity2.Body).Data; if (data != null) { MD5CryptoServiceProvider mD5CryptoServiceProvider = new MD5CryptoServiceProvider(); list2.Add(Encoding.UTF8.GetString(mD5CryptoServiceProvider.ComputeHash(data))); } } } catch { } } array = list2.ToArray(); } } else if (text == "sys.date_time") { if (!syntaxCheckOnly) { array = new string[] { DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") }; } } else if (text == "sys.date") { if (!syntaxCheckOnly) { array = new string[] { DateTime.Today.ToString("dd.MM.yyyy") }; } } else if (text == "sys.time") { if (!syntaxCheckOnly) { array = new string[] { DateTime.Now.ToString("HH:mm:ss") }; } } else if (text == "sys.day_of_week") { if (!syntaxCheckOnly) { array = new string[] { DateTime.Today.DayOfWeek.ToString() }; } } else { if (!(text == "sys.day_of_year")) { throw new Exception("Unknown match source '" + text + "' !"); } if (!syntaxCheckOnly) { array = new string[] { DateTime.Today.ToString("M") }; } } flag = false; text = r.ReadWord(true, new char[] { ' ' }, true); if (text == null) { throw new Exception("Invalid syntax: operator is missing ! \r\n\r\n Near: '" + r.OriginalString.Substring(0, r.Position) + "'"); } text = text.ToLower(); if (text == "*") { string text4 = r.ReadWord(); if (text4 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text4 = text4.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int m = 0; m < array4.Length; m++) { string text5 = array4[m]; if (SCore.IsAstericMatch(text4, text5.ToLower())) { flag = true; break; } } } } else if (text == "!*") { string text6 = r.ReadWord(); if (text6 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text6 = text6.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text7 = array4[j]; if (SCore.IsAstericMatch(text6, text7.ToLower())) { flag = false; break; } } } } else if (text == "==") { string text8 = r.ReadWord(); if (text8 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text8 = text8.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text9 = array4[j]; if (text8 == text9.ToLower()) { flag = true; break; } } } } else if (text == "!=") { string text10 = r.ReadWord(); if (text10 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text10 = text10.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text11 = array4[j]; if (text10 == text11.ToLower()) { flag = false; break; } flag = true; } } } else if (text == ">=") { string text12 = r.ReadWord(); if (text12 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text12 = text12.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text13 = array4[j]; if (text13.ToLower().CompareTo(text12) >= 0) { flag = true; break; } } } } else if (text == "<=") { string text14 = r.ReadWord(); if (text14 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text14 = text14.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text15 = array4[j]; if (text15.ToLower().CompareTo(text14) <= 0) { flag = true; break; } } } } else if (text == ">") { string text16 = r.ReadWord(); if (text16 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text16 = text16.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text17 = array4[j]; if (text17.ToLower().CompareTo(text16) > 0) { flag = true; break; } } } } else if (text == "<") { string text18 = r.ReadWord(); if (text18 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text18 = text18.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text19 = array4[j]; if (text19.ToLower().CompareTo(text18) < 0) { flag = true; break; } } } } else { if (!(text == "regex")) { throw new Exception("Unknown keword '" + text + "' !"); } string text20 = r.ReadWord(); if (text20 == null) { throw new Exception("Invalid syntax: <SP> \"value\" is missing !"); } text20 = text20.ToLower(); if (!syntaxCheckOnly) { string[] array4 = array; for (int j = 0; j < array4.Length; j++) { string text21 = array4[j]; if (Regex.IsMatch(text20, text21.ToLower())) { flag = true; break; } } } } possibleClauseItem = (GlobalMessageRuleProcessor.PossibleClauseItem) 6; } } return(flag); }
public bool Match(string matchExpression, string mailFrom, string[] rcptTo, SMTP_Session smtpSession, Mail_Message mime, int messageSize) { System.NetworkToolkit.StringReader r = new System.NetworkToolkit.StringReader(matchExpression); return(this.Match(false, r, mailFrom, rcptTo, smtpSession, mime, messageSize)); }
/// <summary> /// /// </summary> /// <param name="socket"></param> protected override void InitNewSession(Socket socket) { SocketLogger logger = new SocketLogger(socket, this.SessionLog); SMTP_Session session = new SMTP_Session(socket, this, logger); }
/// <summary> /// /// </summary> /// <param name="socket"></param> protected override void InitNewSession(Socket socket) { _LogWriter logWriter = new _LogWriter(this.SessionLog); SMTP_Session session = new SMTP_Session(socket, this, logWriter); }
/// <summary> /// Filters sender. /// </summary> /// <param name="from">Sender.</param> /// <param name="api">Reference to server API.</param> /// <param name="session">Reference to SMTP session.</param> /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param> /// <returns>Returns true if sender is ok or false if rejected.</returns> public bool Filter(string from, IMailServerApi api, SMTP_Session session, out string errorText) { errorText = null; bool ok = true; // Don't check authenticated users or LAN IP if (session.IsAuthenticated || IsPrivateIP(session.RemoteEndPoint.Address)) { return(true); } try{ //--- Load data ----------------------- DataSet ds = new DataSet(); ds.Tables.Add("General"); ds.Tables["General"].Columns.Add("CheckHelo"); ds.Tables["General"].Columns.Add("LogRejections"); ds.Tables.Add("BlackListSettings"); ds.Tables["BlackListSettings"].Columns.Add("ErrorText"); ds.Tables.Add("BlackList"); ds.Tables["BlackList"].Columns.Add("IP"); ds.Tables.Add("Servers"); ds.Tables["Servers"].Columns.Add("Cost"); ds.Tables["Servers"].Columns.Add("Server"); ds.Tables["Servers"].Columns.Add("DefaultRejectionText"); ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsDNSBL_Filter_db.xml"); bool logRejections = false; #region General if (ds.Tables["General"].Rows.Count == 1) { if (Convert.ToBoolean(ds.Tables["General"].Rows[0]["CheckHelo"])) { DnsServerResponse response = Dns_Client.Static.Query(session.EhloHost, DNS_QType.A); // If dns server connection errors, don't block. if (response.ConnectionOk && response.ResponseCode != DNS_RCode.SERVER_FAILURE) { bool found = false; foreach (DNS_rr_A a in response.GetARecords()) { if (session.RemoteEndPoint.Address.Equals(a.IP)) { found = true; break; } } if (!found) { errorText = "Not valid DNS EHLO/HELO name for your IP '" + session.EhloHost + "' !"; return(false); } } } logRejections = ConvertEx.ToBoolean(ds.Tables["General"].Rows[0]["LogRejections"]); } #endregion #region Balck List foreach (DataRow dr in ds.Tables["BlackList"].Rows) { if (IsAstericMatch(dr["IP"].ToString(), session.RemoteEndPoint.Address.ToString())) { errorText = ds.Tables["BlackListSettings"].Rows[0]["ErrorText"].ToString(); return(false); } } #endregion #region DNSBL foreach (DataRow dr in ds.Tables["Servers"].Rows) { DnsServerResponse dnsResponse = Dns_Client.Static.Query(ReverseIP(session.RemoteEndPoint.Address) + "." + dr["Server"].ToString(), DNS_QType.ANY); DNS_rr_A[] recs = dnsResponse.GetARecords(); if (recs.Length > 0) { if (logRejections) { WriteFilterLog("Sender:" + from + " IP:" + session.RemoteEndPoint.Address.ToString() + " blocked\r\n"); } errorText = dr["DefaultRejectionText"].ToString(); // Server provided return text, use it if (dnsResponse.GetTXTRecords().Length > 0) { errorText = dnsResponse.GetTXTRecords()[0].Text; } if (errorText == "") { errorText = "You are in '" + dr["Server"].ToString() + "' rejection list !"; } return(false); } } #endregion } catch { } return(ok); }