POP3_Server.cs
上传用户:horngjaan
上传日期:2009-12-12
资源大小:2882k
文件大小:12k
源码类别:

Email服务器

开发平台:

C#

  1. using System;
  2. using System.IO;
  3. using System.ComponentModel;
  4. using System.Collections;
  5. using System.Diagnostics;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Threading;
  9. using System.Windows.Forms;
  10. using LumiSoft.MailServer;
  11. namespace LumiSoft.MailServer.POP3
  12. {
  13. #region Event delegates
  14. /// <summary>
  15. /// Represents the method that will handle the GetMessgesList event for POP3_Server.
  16. /// </summary>
  17. /// <param name="sender">The source of the event. </param>
  18. /// <param name="e">A GetMessagesInfo_EventArgs that contains the event data.</param>
  19. public delegate void GetMessagesInfoHandler(object sender,GetMessagesInfo_EventArgs e);
  20. /// <summary>
  21. /// Represents the method that will handle the GetMailEvent event for POP3_Server.
  22. /// </summary>
  23. /// <param name="sender">The source of the event. </param>
  24. /// <param name="e">A GetMessage_EventArgs that contains the event data.</param>
  25. public delegate void GetMessageHandler(object sender,GetMessage_EventArgs e);
  26. /// <summary>
  27. /// Represents the method that will handle the DeleteMessageEvent event for POP3_Server.
  28. /// </summary>
  29. /// <param name="sender">The source of the event. </param>
  30. /// <param name="e">A DeleteMessage_EventArgs that contains the event data.</param>
  31. public delegate void DeleteMessageHandler(object sender,DeleteMessage_EventArgs e);
  32. /// <summary>
  33. /// Represents the method that will handle the GetTopLines event for POP3_Server.
  34. /// </summary>
  35. /// <param name="sender">The source of the event. </param>
  36. /// <param name="e">A GetTopLines_Eventargs that contains the event data.</param>
  37. public delegate void GetTopLinesHandler(object sender,GetTopLines_Eventargs e);
  38. #endregion
  39. /// <summary>
  40. /// POP3 server component.
  41. /// </summary>
  42. public class POP3_Server : System.ComponentModel.Component
  43. {
  44. /// <summary>
  45. /// Required designer variable.
  46. /// </summary>
  47. private System.ComponentModel.Container components = null;
  48. private TcpListener POP3_Listener  = null;
  49. private Hashtable   m_SessionTable = null;
  50. private string m_IPAddress          = "ALL";  // Holds IP Address, which to listen incoming calls.
  51. private int    m_port               = 110;    // Holds port number, which to listen incoming calls.
  52. private int    m_MaxThreads         = 10;     // Holds maximum allowed Worker Threads (Users).
  53. private bool   m_enabled            = false;  // If true listens incoming calls.
  54. private bool   m_LogCmds            = false;  // If true, writes POP3 commands to log file.
  55. private int    m_SessionIdleTimeOut = 80000;  // Holds session idle timeout.
  56. private int    m_CommandIdleTimeOut = 60000;  // Holds command ilde timeout.
  57. private int    m_MaxBadCommands     = 8;       // Holds maximum bad commands allowed to session.
  58.         
  59. #region Event declarations
  60. /// <summary>
  61. /// Occurs when new computer connected to POP3 server.
  62. /// </summary>
  63. public event ValidateIPHandler ValidateIPAddress = null;
  64. /// <summary>
  65. /// Occurs when connected user tryes to authenticate.
  66. /// </summary>
  67. public event AuthUserEventHandler AuthUser = null;
  68. /// <summary>
  69. /// Occurs when server needs to know logged in user's maibox messages.
  70. /// </summary>
  71. public event GetMessagesInfoHandler GetMessgesList = null;
  72. /// <summary>
  73. /// Occurs when user requests specified message.
  74. /// </summary>
  75. public event GetMessageHandler GetMailEvent = null;
  76. /// <summary>
  77. /// Occurs when user requests delete message.
  78. /// </summary>
  79. public event DeleteMessageHandler DeleteMessageEvent = null;
  80. /// <summary>
  81. /// Occurs when user requests specified message TOP lines.
  82. /// </summary>
  83. public event GetTopLinesHandler GetTopLines = null;
  84. /// <summary>
  85. /// Occurs when server has system error(Unknown error).
  86. /// </summary>
  87. public event ErrorEventHandler SysError = null;
  88. /// <summary>
  89. /// Occurs when POP3 session has finished and session log is available.
  90. /// </summary>
  91. public event LogEventHandler SessionLog = null;
  92. #endregion
  93. #region Constructors
  94. /// <summary>
  95. /// 
  96. /// </summary>
  97. /// <param name="container"></param>
  98. public POP3_Server(System.ComponentModel.IContainer container)
  99. {
  100. // Required for Windows.Forms Class Composition Designer support
  101. container.Add(this);
  102. InitializeComponent();
  103. //
  104. // TODO: Add any constructor code after InitializeComponent call
  105. //
  106. }
  107. /// <summary>
  108. /// 
  109. /// </summary>
  110. public POP3_Server()
  111. {
  112. // Required for Windows.Forms Class Composition Designer support
  113. InitializeComponent();
  114. //
  115. // TODO: Add any constructor code after InitializeComponent call
  116. //
  117. }
  118. #endregion
  119. #region function Dispose
  120. /// <summary>
  121. /// Clean up any resources being used and STOPs POP3 server.
  122. /// </summary>
  123. public new void Dispose()
  124. {
  125. base.Dispose();
  126. Stop();
  127. }
  128. #endregion
  129. #region Component Designer generated code
  130. /// <summary>
  131. /// Required method for Designer support - do not modify
  132. /// the contents of this method with the code editor.
  133. /// </summary>
  134. private void InitializeComponent()
  135. {
  136. components = new System.ComponentModel.Container();
  137. }
  138. #endregion
  139. #region function Start
  140. /// <summary>
  141. /// Starts POP3 Server.
  142. /// </summary>
  143. private void Start()
  144. {
  145. try
  146. {
  147. if(!m_enabled && !this.DesignMode){
  148. m_SessionTable = new Hashtable();
  149. Thread startPOP3Server = new Thread(new ThreadStart(Run));
  150. startPOP3Server.Start();
  151. }
  152. }
  153. catch(Exception x)
  154. {
  155. OnSysError(x,new System.Diagnostics.StackTrace());
  156. }
  157. }
  158. #endregion
  159. #region function Stop
  160. /// <summary>
  161. /// Stops POP3 Server.
  162. /// </summary>
  163. private void Stop()
  164. {
  165. try
  166. {
  167. if(POP3_Listener != null){
  168. POP3_Listener.Stop();
  169. }
  170. }
  171. catch(Exception x)
  172. {
  173. OnSysError(x,new System.Diagnostics.StackTrace());
  174. }
  175. }
  176. #endregion
  177. #region function Run
  178. /// <summary>
  179. /// Starts server message loop.
  180. /// </summary>
  181. private void Run()
  182. {
  183. try
  184. {
  185. // check which ip's to listen (all or assigned)
  186. if(m_IPAddress == "(All Unassigned)"){
  187. POP3_Listener = new TcpListener(m_port);
  188. }
  189. else{
  190. POP3_Listener = new TcpListener(IPAddress.Parse(m_IPAddress),m_port);
  191. }
  192. // Start listening
  193. POP3_Listener.Start();
  194. while(true)
  195. {
  196. // Check if maximum allowed thread count isn't exceeded
  197. if(m_SessionTable.Count < m_MaxThreads){
  198. // Thread is sleeping, until a client connects
  199. Socket clientSocket = POP3_Listener.AcceptSocket();
  200. string sessionID = clientSocket.GetHashCode().ToString();
  201. //****
  202. _LogWriter logWriter       = new _LogWriter(this.SessionLog);
  203. POP3_Session session       = new POP3_Session(clientSocket,this,sessionID,logWriter);
  204. session.DeleteMessageEvent = this.DeleteMessageEvent;
  205. session.GetMailEvent       = this.GetMailEvent;
  206. session.GetMessgesList     = this.GetMessgesList;
  207. session.GetTopLines        = this.GetTopLines;
  208. session.ValidateIPAddress  = this.ValidateIPAddress;
  209. session.AuthUser           = this.AuthUser;
  210. ThreadStart tStart = new ThreadStart(session.StartProcessing);
  211. Thread clientThread = new Thread(tStart);
  212. // Add session to session list
  213. AddSession(sessionID,session,logWriter);
  214. // Start proccessing
  215. clientThread.Start();
  216. }
  217. else{
  218. Thread.Sleep(300);
  219. }
  220. }
  221. }
  222. catch(ThreadInterruptedException e)
  223. {
  224. Thread.CurrentThread.Abort();
  225. }
  226. catch(Exception x)
  227. {
  228. if(x.Message != "A blocking operation was interrupted by a call to WSACancelBlockingCall"){
  229. OnSysError(x,new System.Diagnostics.StackTrace());
  230. }
  231. }
  232. }
  233. #endregion
  234. #region Session handling stuff
  235. #region function AddSession
  236. /// <summary>
  237. /// Adds session.
  238. /// </summary>
  239. /// <param name="sessionID">Session ID.</param>
  240. /// <param name="session">Session object.</param>
  241. /// <param name="logWriter">Log writer.</param>
  242. internal void AddSession(string sessionID,POP3_Session session,_LogWriter logWriter)
  243. {
  244. m_SessionTable.Add(sessionID,session);
  245. if(m_LogCmds){
  246. logWriter.AddEntry("//----- Sys: 'Session:'" + sessionID + " added" + DateTime.Now);
  247. }
  248. }
  249. #endregion
  250. #region function RemoveSession
  251. /// <summary>
  252. /// Removes session.
  253. /// </summary>
  254. /// <param name="sessionID">Session ID.</param>
  255. /// <param name="logWriter">Log writer.</param>
  256. internal void RemoveSession(string sessionID,_LogWriter logWriter)
  257. {
  258. lock(this){
  259. if(!m_SessionTable.Contains(sessionID)){
  260. OnSysError(new Exception("Session '" + sessionID + "' doesn't exist."),new System.Diagnostics.StackTrace());
  261. return;
  262. }
  263. m_SessionTable.Remove(sessionID);
  264. }
  265. if(m_LogCmds){
  266. logWriter.AddEntry("//----- Sys: 'Session:'" + sessionID + " removed" + DateTime.Now);
  267. }
  268. }
  269. #endregion
  270. #region function IsUserLoggedIn
  271. /// <summary>
  272. /// Checks if user is logged in.
  273. /// </summary>
  274. /// <param name="userName">User name.</param>
  275. /// <returns></returns>
  276. internal bool IsUserLoggedIn(string userName)
  277. {
  278. lock(this){
  279. foreach(POP3_Session sess in m_SessionTable.Values){
  280. if(sess.UserName == userName){
  281. return true;
  282. }
  283. }
  284. }
  285.             return false;
  286. }
  287. #endregion
  288. #endregion
  289. #region Properties implementation
  290. /// <summary>
  291. /// Gets or sets whick IP address to listen.
  292. /// </summary>
  293. [
  294. Description("IP Address to Listen POP3 requests"),
  295. DefaultValue("ALL"),
  296. ]
  297. public string IpAddress 
  298. {
  299. get{ return m_IPAddress; }
  300. set{ m_IPAddress = value; }
  301. }
  302. /// <summary>
  303. /// Gets or sets which port to listen.
  304. /// </summary>
  305. [
  306. Description("Port to use for POP3"),
  307. DefaultValue(110),
  308. ]
  309. public int Port 
  310. {
  311. get{ return m_port; }
  312. set{ m_port = value; }
  313. }
  314. /// <summary>
  315. /// Gets or sets maximum session threads.
  316. /// </summary>
  317. [
  318. Description("Maximum Allowed threads"),
  319. DefaultValue(10),
  320. ]
  321. public int Threads 
  322. {
  323. get{ return m_MaxThreads; }
  324. set{ m_MaxThreads = value; }
  325. }
  326. /// <summary>
  327. /// Runs or stops server.
  328. /// </summary>
  329. [
  330. Description("Use this property to run and stop POP3 Server"),
  331. DefaultValue(false),
  332. ]
  333. public bool Enabled 
  334. {
  335. get{ return m_enabled; }
  336. set{
  337. if(value){
  338. Start();
  339. }
  340. else{
  341. Stop();
  342. }
  343. m_enabled = value;
  344. }
  345. }
  346. /// <summary>
  347. /// Gets or sets if to log commands.
  348. /// </summary>
  349. public bool LogCommands
  350. {
  351. get{ return m_LogCmds; }
  352. set{ m_LogCmds = value; }
  353. }
  354. /// <summary>
  355. /// Session idle timeout.
  356. /// </summary>
  357. public int SessionIdleTimeOut 
  358. {
  359. get{ return m_SessionIdleTimeOut; }
  360. set{ m_SessionIdleTimeOut = value; }
  361. }
  362. /// <summary>
  363. /// Command idle timeout.
  364. /// </summary>
  365. public int CommandIdleTimeOut 
  366. {
  367. get{ return m_CommandIdleTimeOut; }
  368. set{ m_CommandIdleTimeOut = value; }
  369. }
  370. /// <summary>
  371. /// Gets or sets maximum bad commands allowed to session.
  372. /// </summary>
  373. public int MaxBadCommands
  374. {
  375. get{ return m_MaxBadCommands; }
  376. set{ m_MaxBadCommands = value; }
  377. }
  378. #endregion
  379. #region Events Implementation
  380. /// <summary>
  381. /// Raises SysError event.
  382. /// </summary>
  383. /// <param name="x"></param>
  384. /// <param name="stackTrace"></param>
  385. internal void OnSysError(Exception x,StackTrace stackTrace)
  386. {
  387. if(this.SysError != null){
  388. this.SysError(this,new Error_EventArgs(x,stackTrace));
  389. }
  390. }
  391. #endregion
  392. }
  393. }