//------------------------------------------------------------------------------------------- private void server_QueueMail(SmtpClient smtpclient, string messagepath) { ThreadPool.QueueUserWorkItem(_ProcessOutgoingMail, messagepath); }
//-------------------------------------------------------------------------------------------- /// <summary> /// This is where 90% of the magic happens. Once the SmtpClient is issued a recipient's address this event is /// triggered and handles the address to return an address list which specifies how to route the incoming message. /// </summary> /// <param name="smtpclient">This is the client triggering the authorization event.</param> /// <param name="address">This is the address being verified.</param> /// <param name="AllowRelay">This states whether or not the client is allowed to relay. (i.e. if the address is not local, then /// an address should be added to the address list to route the message to the remote server.</param> /// <returns>This event should return an address list that contains routing instructions for the message.</returns> private ArrayList server_AuthorizeRCPT(SmtpClient smtpclient, Address mailaddress, bool AllowRelay) { string sql = ""; ArrayList al = new ArrayList(); ADODB.Recordset rs = null; if (!DBOpen()) { Address address = new Address(); address.SetAddress(mailaddress.address); DebugOut("Database connection error, e-mail rejected.", true); address.EndPoint = AddressEndPointStatus.Bad; address.Error = "There is a problem on our side, we can not accept your mail due to a database connection error."; al.Add(address); return al; } try { sql = String.Format(sqldomaincheck, mailaddress.domain); rs = Query(sql); if (rs.EOF && AllowRelay) { Address address = new Address(); address.SetAddress(mailaddress.address); address.Path = address.address; address.EndPoint = AddressEndPointStatus.Forward; al.Add(address); return al; } else if (rs.EOF && !AllowRelay) { Address address = new Address(); address.SetAddress(mailaddress.address); address.Error = "This server is rejecting your mail because it is not an authority for the end address to which you are trying to send to and/or you are not authenticated for relay."; address.EndPoint = AddressEndPointStatus.Bad; al.Add(address); return al; } while (!rs.EOF) { Address address = new Address(); address.SetAddress(mailaddress.address); switch (Int32.Parse(rs.get_Collect("status").ToString())) { #region Case BLOCKED case (int)Status.Blocked: //domain disabled address.EndPoint = AddressEndPointStatus.Bad; address.Error = "This server is not allowed to handle mail to this address and therefore can not accept your mail."; al.Add(address); return al; #endregion #region Case NORMAL case (int)Status.Normal: //normal operation address = null; // address.EndPoint = AddressEndPoint.Local; break; #endregion #region Case REMOTE case (int)AddressEndPointStatus.Remote: // forward mail to specified server address.EndPoint = AddressEndPointStatus.Remote; address.Server = rs.get_Collect("misc").ToString(); al.Add(address); return al; #endregion #region Case FORWARD case (int)AddressEndPointStatus.Forward: address.Path = rs.get_Collect("misc").ToString(); address.EndPoint = AddressEndPointStatus.Forward; al.Add(address); return al; #endregion #region Case DEFAULT default: address.Error = "Server is misconfigured for this domain and therefore can not accept any mail."; DebugOut("Domain status settings for " + address.domain + " are not set properly please check them again.", true); al.Add(address); return al; #endregion } rs.MoveNext(); } string disposableprefix = "<#IGNORE#>"; bool prefixfound = false; bool disposablefound = false; if (mailaddress.prefix.IndexOf("-") > 0 && mailaddress.prefix.Length > mailaddress.prefix.IndexOf("-")) disposableprefix = mailaddress.prefix.Substring(0, mailaddress.prefix.IndexOf("-")); sql = String.Format(sqladdressa, mailaddress.prefix, mailaddress.domain, disposableprefix); rs = Query(sql); if (rs.EOF) { Address address = new Address(); address.EndPoint = AddressEndPointStatus.Bad; address.Error = "The address belongs to this server but no mail box for it exists. (" + mailaddress.address + ")"; al.Add(address); return al; } while (!rs.EOF) { string prefix = rs.Fields["prefix"].Value.ToString().ToLower(); string astatus = rs.Fields["status"].Value.ToString(); int status = (int)rs.Fields["status"].Value; if (prefix == mailaddress.prefix.ToLower()) { prefixfound = true; } if (prefix == disposableprefix && status == 7) { disposablefound = true; } rs.MoveNext(); } rs.MoveFirst(); int rowcount = 0; while (!rs.EOF) { rowcount++; string prefix = rs.Fields["prefix"].Value.ToString(); string misc = rs.Fields["misc"].Value.ToString(); if ((prefixfound || disposablefound) && prefix == "*") { rs.MoveNext(); continue; } else if (prefixfound && prefix == disposableprefix) { rs.MoveNext(); continue; } ADODB.Recordset rsb = null; Address address = new Address(); address.SetAddress(mailaddress.address); sql = ""; switch (Int32.Parse(rs.get_Collect("status").ToString())) { case (int)Status.Blocked: if (!(misc == "ignore" && prefix == disposableprefix)) { address.EndPoint = AddressEndPointStatus.Blocked; address.Error = "This user's mail box has been disabled."; al.Add(address); } else { address = null; } break; case (int)Status.Normal: sql = String.Format(sqladdressb, rs.get_Collect("mailboxid").ToString()); rsb = Query(sql); address.EndPoint = AddressEndPointStatus.Local; address.quota = Decimal.Parse(rsb.Fields["quota"].Value.ToString()); address.Path = server.MailPath + rsb.Fields["postoffice"].Value.ToString() + "\\" + rsb.Fields["mailbox"].Value.ToString() + "\\"; al.Add(address); break; case (int)Status.Forward: string fmisc = rs.Fields["misc"].Value.ToString().Replace(" ", ""); address.EndPoint = AddressEndPointStatus.Forward; address.Path = fmisc; al.Add(address); break; case (int)Status.Execute: sql = String.Format(sqladdressb, rs.get_Collect("mailboxid").ToString()); rs = Query(sql); address.quota = Decimal.Parse(rs.get_Collect("quota").ToString()); address.EndPoint = AddressEndPointStatus.Plugin; address.Path = server.MailPath + rs.Fields["postoffice"].Value.ToString() + "\\" + rs.Fields["mailbox"].Value + "\\"; al.Add(address); break; case (int)AddressEndPointStatus.AutoRespond: break; case (int)AddressEndPointStatus.Disposable: //no action - just a pointer record break; case (int)Status.Remote: string rmisc = rs.Fields["misc"].Value.ToString().Trim(); address.EndPoint = AddressEndPointStatus.Remote; address.Path = rmisc; al.Add(address); break; case (int)Status.SMS: sql = String.Format(sqlsms, rs.Fields["smsserviceid"].Value.ToString()); rsb = Query(sql); if (!rsb.EOF) { switch (Int32.Parse(rsb.Fields["type"].Value.ToString())) { case 1: address.EndPoint = AddressEndPointStatus.SMS; address.Path = rs.Fields["misc"].Value.ToString() + "@" + rsb.Fields["misc"].Value.ToString(); al.Add(address); break; case 2: address.EndPoint = AddressEndPointStatus.Forward; address.Path = rs.Fields["misc"].Value.ToString() + "@" + rsb.Fields["misc"].Value.ToString(); al.Add(address); break; case 3: address.EndPoint = AddressEndPointStatus.Plugin; address.Path = rsb.Fields["misc"].Value.ToString(); al.Add(address); break; } } break; default: DebugOut("The status set for " + address.address + " is invalid. E-mail to this address was rejected, please fix it.", true); address.EndPoint = AddressEndPointStatus.Bad; address.Error = "The mailbox you are trying to reach does exist for this user however it is incorrectly configured and we are forced to reject your e-mail."; al.Add(address); break; } rs.MoveNext(); } if (rowcount == 0) { Address address = new Address(); address.SetAddress(mailaddress.address); address.Error = "This server is authoritive for the domain that you are trying to send an e-mail to, however the mailbox that you are trying to reach does not exist on this server!"; address.EndPoint = AddressEndPointStatus.Bad; al.Add(address); } return al; } catch (Exception e) { Address address = new Address(); address.SetAddress(mailaddress.address); DebugOut("User check against database failed for " + mailaddress.address + ".\r\n\r\n" + e.Message, true); address.Error = "This server can not accept your e-mail due to a local database error."; address.EndPoint = AddressEndPointStatus.Bad; al.Add(address); return al; } }
//------------------------------------------------------------------------------------------- private bool server_AuthorizeUserRelay(SmtpClient smtpclient, string user, string pass) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] raw = System.Text.ASCIIEncoding.ASCII.GetBytes(pass); byte[] hash = md5.ComputeHash(raw); pass = BitConverter.ToString(hash).Replace("-", "").ToUpper(); user = user.Replace("'", "\'"); pass = pass.Replace("'", "\'"); string sql = ""; if (user.IndexOf("@") > 0) { sql = String.Format(sqlchecka, user.Substring(user.IndexOf("@") + 1), user.Substring(0, user.IndexOf("@")), pass); } else { sql = String.Format(sqlcheckb, user, pass); } ADODB.Recordset rs = Query(sql); return !rs.EOF; }
//-------------------------------------------------------------------------------------------- private bool server_AuthorizeIPRelay(SmtpClient smtpclient, EndPoint endpoint) { string IPAddress = endpoint.ToString(); if (!DBOpen()) return false; ADODB.Recordset rs = null; IPAddress = IPAddress.Substring(0, IPAddress.IndexOf(":")); string sql = String.Format(sqlipaddresscheck, IPAddress, IPAddress.Substring(0, IPAddress.LastIndexOf(".") + 1) + "*"); rs = Query(sql); if (rs.EOF) return false; if (rs.Fields["status"].Value.ToString() == "1") return true; else return false; }
//-------------------------------------------------------------------------------------------- /// <summary> /// Currently I am not sure how this authorization should be implemented. If you have any ideas please /// let me know. /// </summary> private bool server_AuthorizeMAIL(SmtpClient smtpclient, string address) { return true; }
//------------------------------------------------------------------------------------------- public void QueueMailOut(SmtpClient smtpclient, string mailpath) { if (QueueMail != null) QueueMail(smtpclient, mailpath); }
//------------------------------------------------------------------------------------------- private void OnAccept(Object pSock) { try { SmtpClient smtpclient = new SmtpClient(this, (Socket)pSock); if (ClientConnected != null) { ClientConnected(smtpclient); } connections.Add(smtpclient); smtpclient.HandleConnection(); connections.Remove(smtpclient); pSock = null; smtpclient = null; } catch (Exception e) { DebugOut("Unknown error:\r\n\r\n" + e.Message, true); } }
//------------------------------------------------------------------------------------------- public void ProcessHandleMessageReceived(SmtpClient smtpclient, string mailpath) { if (HandleMessageReceived != null) HandleMessageReceived(smtpclient, mailpath); }
//------------------------------------------------------------------------------------------- public bool CheckUserRelay(SmtpClient smtpclient, string user, string pass) { if (AuthorizeUserRelay != null) return AuthorizeUserRelay(smtpclient, user, pass); else return false; }
//------------------------------------------------------------------------------------------- public ArrayList CheckRCPT(SmtpClient smtpclient, Address address, bool AllowRelay) { if (AuthorizeRCPT != null) return AuthorizeRCPT(smtpclient, address, AllowRelay); else return null; }
//------------------------------------------------------------------------------------------- public bool CheckMAIL(SmtpClient smtpclient, string address) { if (AuthorizeMAIL != null) return AuthorizeMAIL(smtpclient, address); else return false; }
//------------------------------------------------------------------------------------------- public bool CheckIPRelay(SmtpClient smtpclient, EndPoint endpoint) { if (AuthorizeIPRelay != null) return AuthorizeIPRelay(smtpclient, endpoint); else return false; }