Relay.cs
上传用户:horngjaan
上传日期:2009-12-12
资源大小:2882k
文件大小:13k
- using System;
- using System.IO;
- using System.Data;
- using System.Threading;
- using System.Collections;
- using LumiSoft.Net.SMTP.Client;
- using LumiSoft.Net.Mime;
- namespace LumiSoft.MailServer
- {
- /// <summary>
- /// Mail relayer.
- /// </summary>
- public class Relay
- {
- private static bool m_Delivering = false;
- private static bool m_DeliveringRetry = false;
- private static int m_MaxThreads = 10;
- private static int m_RelayInterval = 10;
- private static int m_RelayRetryInterval = 30;
- private static int m_RelayUndelWarning = 1;
- private static int m_RelayUndelivered = 1;
- private static string m_UndelWarningTemplate = "";
- private static string m_UndeliveredTemplate = "";
- private static string m_SmartHost = ""; // Smart host name eg. 'mail.neti.ee'.
- private static bool m_UseSmartHost = true; //
- private static string m_Dns1 = ""; // Primary dns server IP.
- private static string m_Dns2 = ""; // Secondary dns server IP.
- private static Hashtable m_RelayTable = null;
- private MailServer m_pServer = null;
-
- /// <summary>
- /// Default constructor.
- /// </summary>
- /// <param name="server"></param>
- public Relay(MailServer server)
- {
- m_pServer = server;
- if(m_RelayTable == null){
- m_RelayTable = new Hashtable();
- }
- }
- #region function Deliver
- /// <summary>
- /// Sends relay mails.
- /// </summary>
- public void Deliver()
- {
- if(!m_Delivering){
- m_Delivering = true;
- RelayMails();
- m_Delivering = false;
- }
- }
- #endregion
- #region function DeliverRetry
- /// <summary>
- /// Sends retry(mails which couldn't be sent at immedeately) relay mails.
- /// </summary>
- public void DeliverRetry()
- {
- if(!m_DeliveringRetry){
- m_DeliveringRetry = true;
- SendRetryMails();
- m_DeliveringRetry = false;
- }
- }
- #endregion
-
- #region function RelayMails
- /// <summary>
- /// Relays all messages from relay directory.
- /// </summary>
- private void RelayMails()
- {
- try
- {
- string path = MailStore.MailStorePath + "Relay\";
- // Check if Directory exists, if not Create
- if(!Directory.Exists(path)){
- Directory.CreateDirectory(path);
- }
- string[] files = Directory.GetFiles(path,"*.eml");
-
- foreach(string file in files){
- // If maximum relay threads are exceeded,
- // wait when some gets available.
- while(m_RelayTable.Count > m_MaxThreads){
- Thread.Sleep(200);
- }
- Thread tr = new Thread(new ThreadStart(this.RelayMessage));
- AddThread(tr,file);
- tr.Start();
- }
- }
- catch(Exception x)
- {
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- #endregion
- #region function RelayMessage
- private void RelayMessage()
- {
- try
- {
- if(!m_RelayTable.Contains(Thread.CurrentThread)){
- SCore.WriteLog(m_pServer.m_SartUpPath + "mailServiceError.log","RelayMails: params missing");
- return;
- }
- string messageFile = m_RelayTable[Thread.CurrentThread].ToString();
- bool sendOk = false;
- using(FileStream fs = File.Open(messageFile,FileMode.Open,FileAccess.ReadWrite)){
- // Get relay info
- RelayInfo relayInf = new RelayInfo(fs,1,1);
- string from = relayInf.From;
- if(from.Length == 0){
- from = relayInf.To;
- }
- SMTP_Client smtpClnt = new SMTP_Client();
- smtpClnt.UseSmartHost = UseSmartHost;
- smtpClnt.SmartHost = SmartHost;
- smtpClnt.DnsServers = new string[]{Dns1,Dns2};
- sendOk = smtpClnt.Send(new string[]{relayInf.To},from,fs);
- }
- if(sendOk){
- // Message sended successfuly, may delete it
- File.Delete(messageFile);
- }
- // send failed
- else{
- // Move message to Retry folder
- string msgFileName = Path.GetFileName(messageFile);
- File.Move(messageFile,MailStore.MailStorePath + "Retry\" + msgFileName);
- }
- }
- catch(Exception x){
- if(!(x is IOException)){
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- finally{
- RemoveThread(Thread.CurrentThread);
- }
- }
- #endregion
- #region function SendRetryMails
- /// <summary>
- /// Relay retry mails from retry directory.
- /// </summary>
- private void SendRetryMails()
- {
- try
- {
- string path = MailStore.MailStorePath + "Retry\";
- // Check if Directory exists, if not Create
- if(!Directory.Exists(path)){
- Directory.CreateDirectory(path);
- }
- string[] files = Directory.GetFiles(path,"*.eml");
-
- foreach(string file in files){
- // If maximum relay threads are exceeded,
- // wait when some gets available.
- while(m_RelayTable.Count > m_MaxThreads){
- Thread.Sleep(200);
- }
- Thread t = new Thread(new ThreadStart(this.SendRetryMail));
- AddThread(t,file);
- t.Start();
- }
- }
- catch(Exception x)
- {
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- #endregion
- #region function SendRetryMail
- private void SendRetryMail()
- {
- try
- {
- if(!m_RelayTable.Contains(Thread.CurrentThread)){
- SCore.WriteLog(m_pServer.m_SartUpPath + "mailServiceError.log","SendRetryMail: params missing");
- return;
- }
- string messageFile = m_RelayTable[Thread.CurrentThread].ToString();
- using(FileStream fs = File.Open(messageFile,FileMode.Open,FileAccess.ReadWrite)){
- // Get relay info
- RelayInfo relayInf = new RelayInfo(fs,RelayUndelivered,RelayUndelWarning);
- string from = relayInf.From;
- if(from.Length == 0){
- from = relayInf.To;
- }
- SMTP_Client smtpClnt = new SMTP_Client();
- smtpClnt.UseSmartHost = UseSmartHost;
- smtpClnt.SmartHost = SmartHost;
- smtpClnt.DnsServers = new string[]{Dns1,Dns2};
- if(smtpClnt.Send(new string[]{relayInf.To},from,fs)){
- fs.Close();
- // Message sended successfuly, may delete it
- File.Delete(messageFile);
- }
- // send failed
- else{
- string error = smtpClnt.Errors[0].ErrorText;
-
- // If destination recipient is invalid or Undelivered Date Exceeded, try to return message to sender
- if(smtpClnt.Errors[0].ErrorType == SMTP_ErrorType.InvalidEmailAddress || relayInf.IsUndeliveredDateExceeded){
- MakeUndeliveredNotify(relayInf,error,fs);
- fs.Close();
- // Undelivery note made, may delete message
- if(relayInf.From.Length > 0){
- File.Delete(messageFile);
- }
- // There isn't return address, can't send undelivery note
- else{
- // Check if Directory exists, if not Create
- if(!Directory.Exists(MailStore.MailStorePath + "Undelivered\")){
- Directory.CreateDirectory(MailStore.MailStorePath + "Undelivered\");
- }
- File.Move(messageFile,messageFile.Replace("Retry","Undelivered"));
- }
- }
- else if(relayInf.MustSendWarning){
- MakeUndeliveredWarning(relayInf,error,fs);
- byte[] mustSendWarningBit = System.Text.Encoding.ASCII.GetBytes("1");
- fs.Position = relayInf.WarningBitPos;
- fs.Write(mustSendWarningBit,0,mustSendWarningBit.Length);
- }
- }
- }
- }
- catch(Exception x){
- if(!(x is IOException)){
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- finally{
- RemoveThread(Thread.CurrentThread);
- }
- }
- #endregion
-
- #region function MakeUndeliveredNotify
- /// <summary>
- /// Creates undelivered notify for user and places it to relay folder.
- /// </summary>
- /// <param name="relayInfo">Relay info</param>
- /// <param name="error">SMTP returned error text.</param>
- /// <param name="file">Messsage file.</param>
- private void MakeUndeliveredNotify(RelayInfo relayInfo,string error,Stream file)
- {
- try
- {
- // If sender isn't specified, we can't send undelivery notify to sender.
- // Just skip undelivery notify sending.
- if(relayInfo.From.Length == 0){
- return;
- }
- //LumiSoft.MailServer.Core.WriteLog("e:\mail.log","MakeUndeliveredNotify To:" + relayInfo.From + " " + DateTime.Now.ToString() + "msg date:" + relayInfo.MessageDate.ToString());
- // Make new message
- MimeMessage mime = new MimeMessage();
- mime.From = "postmaster";
- mime.To = new string[]{relayInfo.From};
- mime.Subject = "Undelivered mail warning";
- mime.Attachments.Add(new Attachment("data.eml",file));
- string bodyTxt = Relay.UndeliveredTemplate;
- bodyTxt = bodyTxt.Replace("<#RECEPTIENT>",relayInfo.To);
- bodyTxt = bodyTxt.Replace("<#ERROR>",error);
- mime.Body = bodyTxt;
-
- byte[] data = System.Text.Encoding.Default.GetBytes(mime.Mime);
- MailStore.StoreMessage("",new MemoryStream(data),relayInfo.From,"",true);
- }
- catch(Exception x)
- {
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- #endregion
- #region function MakeUndeliveredWarning
- /// <summary>
- /// Creates undelivered warning for user and places it to relay folder.
- /// </summary>
- /// <param name="relayInfo">Relay info</param>
- /// <param name="error">SMTP returned error text.</param>
- /// <param name="file">Messsage file.</param>
- private void MakeUndeliveredWarning(RelayInfo relayInfo,string error,Stream file)
- {
- try
- {
- // If sender isn't specified, we can't send warning to sender.
- // Just skip warning sending.
- if(relayInfo.From.Length == 0){
- return;
- }
- // Make new message
- MimeMessage mime = new MimeMessage();
- mime.From = "postmaster";
- mime.To = new string[]{relayInfo.From};
- mime.Subject = "Undelivered mail warning";
- mime.Attachments.Add(new Attachment("data.eml",file));
- string bodyTxt = Relay.UndelWarningTemplate;
- bodyTxt = bodyTxt.Replace("<#RECEPTIENT>",relayInfo.To);
- bodyTxt = bodyTxt.Replace("<#ERROR>",error);
- bodyTxt = bodyTxt.Replace("<#UNDELIVERED_HOURS>",relayInfo.DeviveringForHours.ToString());
- mime.Body = bodyTxt;
-
- byte[] data = System.Text.Encoding.Default.GetBytes(mime.Mime);
- MailStore.StoreMessage("",new MemoryStream(data),relayInfo.From,"",true);
- }
- catch(Exception x)
- {
- Error.DumpError(x,new System.Diagnostics.StackTrace());
- }
- }
- #endregion
- #region function AddThread
- private void AddThread(Thread tr,string data)
- {
- lock(m_RelayTable){
- m_RelayTable.Add(tr,data);
- }
- }
- #endregion
- #region function RemoveThread
- private void RemoveThread(Thread t)
- {
- lock(m_RelayTable){
- if(!m_RelayTable.ContainsKey(t)){
- SCore.WriteLog(m_pServer.m_SartUpPath + "mailServiceError.log","RemoveThread: doesn't contain");
- }
- m_RelayTable.Remove(t);
- }
- }
- #endregion
-
- #region Properties Implementation
- /// <summary>
- /// Gets or sets maximum relay threads.
- /// </summary>
- public static int MaxRelayThreads
- {
- get{ return m_MaxThreads; }
- set{ m_MaxThreads = value; }
- }
- /// <summary>
- /// Gets or sets relay interval.
- /// </summary>
- public static int RelayInterval
- {
- get{ return m_RelayInterval; }
- set{ m_RelayInterval = value; }
- }
- /// <summary>
- /// Gets or sets relay retry(delayed relay) interval.
- /// </summary>
- public static int RelayRetryInterval
- {
- get{ return m_RelayRetryInterval; }
- set{ m_RelayRetryInterval = value; }
- }
- /// <summary>
- /// Gets or sets undelivered wanrning minutes.
- /// </summary>
- public static int RelayUndelWarning
- {
- get{ return m_RelayUndelWarning; }
- set{ m_RelayUndelWarning = value; }
- }
- /// <summary>
- /// Gets or sets undelivered wanrning reply template.
- /// </summary>
- public static string UndelWarningTemplate
- {
- get{ return m_UndelWarningTemplate; }
- set{ m_UndelWarningTemplate = value; }
- }
- /// <summary>
- /// Gets or sets undelivered hours.
- /// </summary>
- public static int RelayUndelivered
- {
- get{ return m_RelayUndelivered; }
- set{ m_RelayUndelivered = value; }
- }
- /// <summary>
- /// Gets or sets undelivered reply template.
- /// </summary>
- public static string UndeliveredTemplate
- {
- get{ return m_UndeliveredTemplate; }
- set{ m_UndeliveredTemplate = value; }
- }
- /// <summary>
- /// Gets or sets if to use smart host.
- /// </summary>
- public static bool UseSmartHost
- {
- get{ return m_UseSmartHost; }
- set{ m_UseSmartHost = value; }
- }
- /// <summary>
- /// Gets or sets smart host.
- /// </summary>
- public static string SmartHost
- {
- get{ return m_SmartHost; }
- set{ m_SmartHost = value; }
- }
- /// <summary>
- /// Gets or sets smart host.
- /// </summary>
- public static string Dns1
- {
- get{ return m_Dns1; }
- set{ m_Dns1 = value; }
- }
- /// <summary>
- /// Gets or sets smart host.
- /// </summary>
- public static string Dns2
- {
- get{ return m_Dns2; }
- set{ m_Dns2 = value; }
- }
- /// <summary>
- /// Gets if delivering messages.
- /// </summary>
- public static bool IsDelivering
- {
- get{ return m_Delivering; }
- }
- /// <summary>
- /// Gets if delivering retry messages.
- /// </summary>
- public static bool IsDeliveringRetry
- {
- get{ return m_DeliveringRetry; }
- }
- #endregion
-
- }
- }