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

Email服务器

开发平台:

C#

  1. using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.ComponentModel;
  6. using System.ComponentModel.Design;
  7. using System.Collections;
  8. using System.Text;
  9. namespace LumiSoft.MailServer
  10. {
  11. #region public enum ReadReplyCode
  12. /// <summary>
  13. /// Reply reading return codes.
  14. /// </summary>
  15. public enum ReadReplyCode
  16. {
  17. /// <summary>
  18. /// Read completed successfully.
  19. /// </summary>
  20. Ok             = 0,
  21. /// <summary>
  22. /// Read timed out.
  23. /// </summary>
  24. TimeOut        = 1,
  25. /// <summary>
  26. /// Maximum allowed lenght exceeded.
  27. /// </summary>
  28. LenghtExceeded = 2,
  29. /// <summary>
  30. /// UnKnown error, eception raised.
  31. /// </summary>
  32. UnKnownError   = 3,
  33. }
  34. #endregion
  35. #region enum AuthType
  36. /// <summary>
  37. /// Authentication type.
  38. /// </summary>
  39. public enum AuthType
  40. {
  41. /// <summary>
  42. /// 
  43. /// </summary>
  44. Plain = 0,
  45. /// <summary>
  46. /// Not implemented.
  47. /// </summary>
  48. LOGIN = 2,
  49. /// <summary>
  50. /// 
  51. /// </summary>
  52. APOP  = 1,
  53. }
  54. #endregion
  55. /// <summary>
  56. /// Contains utility functions.
  57. /// </summary>
  58. public class Core
  59. {
  60. // public Core()
  61. // {
  62. // }
  63. #region function ParseIP_from_EndPoint
  64. /// <summary>
  65. /// 
  66. /// </summary>
  67. /// <param name="endpoint"></param>
  68. /// <returns></returns>
  69. public static string ParseIP_from_EndPoint(string endpoint)
  70. {
  71. string retVal = endpoint;
  72. int index = endpoint.IndexOf(":");
  73. if(index > 1){
  74. retVal = endpoint.Substring(0,index);
  75. }
  76. return retVal;
  77. }
  78. #endregion
  79. #region function ReadReplyFromSocket
  80. /// <summary>
  81. /// Reads reply from socket.
  82. /// </summary>
  83. /// <param name="socket"></param>
  84. /// <param name="replyData">Data that has been readen from socket.</param>
  85. /// <param name="addData">Data that has will be written at the beginning of read data. This param may be null.</param>
  86. /// <param name="maxLenght">Maximum lenght of data which may read.</param>
  87. /// <param name="cmdIdleTimeOut">Command idle time out in milliseconds.</param>
  88. /// <param name="terminator">Terminator string which terminates reading. eg 'rn'.</param>
  89. /// <param name="removeFromEnd">Removes following string from reply.NOTE: removes only if ReadReplyCode is Ok.</param>
  90. /// <param name="retIfLenExceeded">If true, returns function if maximum length is exceeded.If false, chuck data.</param>
  91. /// <returns>Return reply code.</returns>
  92. public static ReadReplyCode ReadReplyFromSocket(Socket socket,out MemoryStream replyData,byte[] addData,int maxLenght,int cmdIdleTimeOut,string terminator,string removeFromEnd,bool retIfLenExceeded)
  93. {
  94. ReadReplyCode replyCode = ReadReplyCode.Ok;
  95. replyData = null;
  96. try
  97. {
  98. // Create memory stream, where to store data.
  99. MemoryStream strm = new MemoryStream();
  100. // Write additional data to the beginning of stream, if any specified.
  101. if(addData != null){
  102. strm.Write(addData,0,addData.Length);
  103. }
  104. int lastDataTime = Environment.TickCount;
  105. while(true){
  106. if(socket.Available > 0){
  107. // If maximum lenght is exceeded and there is enough data for terminator, clear stream.
  108. // NOTE: we may not clear stream if there isn't enough data for terminator, beacuse
  109. //       some part of terminator may be in stream.
  110. if(replyCode == ReadReplyCode.LenghtExceeded && socket.Available >= terminator.Length){
  111. strm.SetLength(0);
  112. }
  113. //--- Read data from socket and write to stream --//
  114. byte[] buf_Return = new byte[socket.Available];
  115. int received = socket.Receive(buf_Return);
  116. strm.Seek(0,SeekOrigin.End);
  117. strm.Write(buf_Return,0,received);
  118. //------------------------------------------------//
  119. //---- Check if maximum length is exceeded ------------------------------//
  120. if(replyCode != ReadReplyCode.LenghtExceeded && strm.Length > maxLenght){
  121. replyCode = ReadReplyCode.LenghtExceeded;
  122. if(retIfLenExceeded){
  123. break;
  124. }
  125. }
  126. //-----------------------------------------------------------------------//
  127. //----- Check for terminator ---------------------------------------//
  128. if(strm.Length >= terminator.Length){
  129. byte[] bufComp = new byte[terminator.Length];
  130. strm.Position = strm.Length - terminator.Length;
  131. strm.Read(bufComp,0,bufComp.Length);
  132. string strCompare = System.Text.Encoding.ASCII.GetString(bufComp);
  133.                
  134. // check for terminator.
  135. if(socket.Available == 0 && strCompare.IndexOf(terminator) > -1){
  136. break;
  137. }
  138. }
  139. //--------------------------------------------------------------------//
  140. // reset last data time
  141. lastDataTime = Environment.TickCount;
  142. }
  143. //---- Idle and time out stuff ----------------------------------------//
  144. if(socket.Available == 0){
  145. if(Environment.TickCount > lastDataTime + cmdIdleTimeOut){
  146. replyCode = ReadReplyCode.TimeOut;
  147. break;
  148. }
  149. System.Threading.Thread.Sleep(30);
  150. }
  151. //-----------------------------------------------------------//
  152. }
  153. // If reply is ok then remove chars if any specified by 'removeFromEnd'.
  154. // Remove specified char's from end.
  155. if(replyCode == ReadReplyCode.Ok && removeFromEnd.Length > 0){
  156. strm.SetLength(strm.Length - removeFromEnd.Length);
  157. }
  158. replyData = strm;
  159. }
  160. catch(Exception x)
  161. {
  162. replyCode = ReadReplyCode.UnKnownError;
  163. }
  164. return replyCode;
  165. }
  166. #endregion
  167. #region function ReadLineFromSocket
  168. /// <summary>
  169. /// Reads line from socket. Line terminator is {CRLF} and maxLenght = 1024.
  170. /// </summary>
  171. /// <param name="socket">Referance to socket.</param>
  172. /// <param name="reply">Data that has been readen from socket.</param>
  173. /// <param name="cmdTimeOut">Command idle time out in milliseconds.</param>
  174. /// <returns></returns>
  175. public static ReadReplyCode ReadLineFromSocket(Socket socket,out string reply,int cmdTimeOut)
  176. {
  177. ReadReplyCode replyCode = ReadReplyCode.Ok;
  178. reply = "";
  179. try
  180. {
  181. MemoryStream strm = null;
  182. replyCode = ReadReplyFromSocket(socket,out strm,null,1024,cmdTimeOut,"rn","rn",true);
  183. if(replyCode == ReadReplyCode.Ok){
  184. byte[] byte_reply = strm.ToArray();
  185. reply = System.Text.Encoding.ASCII.GetString(byte_reply);
  186. strm.Close();
  187. }
  188. }
  189. catch(Exception x)
  190. {
  191. replyCode = ReadReplyCode.UnKnownError;
  192. }
  193. return replyCode;
  194. }
  195. #endregion
  196. #region function ParseEmailFromPath
  197. /// <summary>
  198. /// Parses email address from forward-path or reverse-path.
  199. /// </summary>
  200. /// <param name="path"></param>
  201. /// <returns>Returns email address, or empty string if parse failed.</returns>
  202. public static string ParseEmailFromPath(string path)
  203. {
  204. //<path> ::= "<" [ <a-d-l> ":" ] <mailbox> ">"
  205. string email = "";
  206. try
  207. {
  208. // "Ivx iv" <abc@ls.ee> or <abc@ls.ee>
  209. if(path.IndexOf('<') != -1 && path.IndexOf('>') != -1){
  210. int index1 = path.IndexOf('<')+1;
  211. int index2 = path.IndexOf('>');
  212. email = path.Substring(index1,index2-index1);
  213. }
  214. // abc@ls.ee
  215. else{
  216. email = path;
  217. }
  218. email = email.Trim();
  219. }
  220. catch{
  221. }
  222.             
  223. return email;
  224. }
  225. #endregion
  226. #region function GetArgsText
  227. /// <summary>
  228. /// Gets argument part of command text.
  229. /// </summary>
  230. /// <param name="input">Input srting from where to remove value.</param>
  231. /// <param name="cmdTxtToRemove">Command text which to remove.</param>
  232. /// <returns></returns>
  233. public static string GetArgsText(string input,string cmdTxtToRemove)
  234. {
  235. string buff = input.Trim();
  236. if(buff.Length >= cmdTxtToRemove.Length){
  237. buff = buff.Substring(cmdTxtToRemove.Length);
  238. }
  239. buff = buff.Trim();
  240. return buff;
  241. }
  242. #endregion
  243. #region fucntion GetParams
  244. /// <summary>
  245. /// Parses parameters.
  246. /// </summary>
  247. /// <param name="argsText">Arguments text.</param>
  248. /// <param name="paramNames">Known parameter list.</param>
  249. /// <returns>Returns array of parameters.</returns>
  250. public static string[] GetParams(string argsText,string[] paramNames)
  251. {
  252. //--- Remove continues spaces ---------//
  253. // eg, aaa=  5 would be aaa=5
  254. while(true){
  255. if(argsText.IndexOf("  ") == -1){
  256. break;
  257. }
  258. argsText = argsText.Replace("  "," ");
  259. }
  260. //--------------------------------------//
  261. string argsTextUpper = argsText.ToUpper();
  262. //--- Try to remove spcaes between parameter name and value----------------------------------//
  263. // eg. FROM: aaa would be FROM:aaa
  264. foreach(string paramName in paramNames){
  265. int startPos = 0;
  266. // Argument text contains parameter
  267. while(argsTextUpper.IndexOf(paramName,startPos) > -1){
  268. int iEndOfParam = argsTextUpper.IndexOf(paramName,startPos) + paramName.Length - 1;
  269. startPos = iEndOfParam;
  270. // Check if next char is ' ' and param follows.
  271. if((argsText.Length > iEndOfParam+1) && argsText.Substring(iEndOfParam+1,1) == " "){
  272. argsText = argsText.Remove(iEndOfParam+1,1);
  273. argsTextUpper = argsTextUpper.Remove(iEndOfParam+1,1);
  274. }
  275. }
  276. }
  277. //--------------------------------------------------------------------------------------------//
  278. return argsText.Split(new char[]{' '});
  279. }
  280. #endregion
  281. #region function GetHostName
  282. /// <summary>
  283. /// 
  284. /// </summary>
  285. /// <param name="IP"></param>
  286. /// <returns></returns>
  287. public static string GetHostName(string IP)
  288. {
  289. try
  290. {
  291. return System.Net.Dns.GetHostByAddress(IP).HostName;
  292. }
  293. catch(Exception x)
  294. {
  295. return "UnkownHost";
  296. }
  297. }
  298. #endregion
  299. #region function GetDateTimeNow
  300. /// <summary>
  301. /// 
  302. /// </summary>
  303. /// <returns></returns>
  304. public static string GetDateTimeNow()
  305. {
  306. // System.Globalization.DateTimeFormatInfo dFormat = System.Globalization.CultureInfo.CreateSpecificCulture("en-US").DateTimeFormat;
  307. // return DateTime.Now.ToString(dFormat.RFC1123Pattern,dFormat);
  308. return DateTime.Now.ToUniversalTime().ToString("r");
  309. }
  310. #endregion
  311. #region function DoPeriodHandling
  312. /// <summary>
  313. /// Does period handling.
  314. /// </summary>
  315. /// <param name="data"></param>
  316. /// <param name="add_Remove"></param>
  317. /// <returns></returns>
  318. public static MemoryStream DoPeriodHandling(byte[] data,bool add_Remove)
  319. {
  320. using(MemoryStream strm = new MemoryStream(data)){
  321. return DoPeriodHandling(strm,add_Remove);
  322. }
  323. }
  324. /// <summary>
  325. /// Does period handling.
  326. /// </summary>
  327. /// <param name="strm">Input stream.</param>
  328. /// <param name="add_Remove">If true add periods, else removes periods.</param>
  329. /// <returns></returns>
  330. public static MemoryStream DoPeriodHandling(Stream strm,bool add_Remove)
  331. {
  332. MemoryStream mhStrm = new MemoryStream();
  333. strm.Position = 0;
  334. StreamReader reader = new StreamReader(strm);
  335. string line = reader.ReadLine();
  336. // Loop through all lines
  337. while(line != null){
  338. if(line.StartsWith(".")){
  339. /* Add period Rfc 281 4.5.2
  340.      -  Before sending a line of mail text, the SMTP client checks the
  341.  first character of the line.  If it is a period, one additional
  342.  period is inserted at the beginning of the line.
  343.     */
  344. if(add_Remove){
  345. line = "." + line;
  346. }
  347. /* Remove period Rfc 281 4.5.2
  348.  If the first character is a period , the first characteris deleted.
  349. */
  350. else if(line.Length > 1){
  351. line = line.Substring(1);
  352. }
  353. }
  354. byte[] data = System.Text.Encoding.ASCII.GetBytes(line + "rn");
  355. mhStrm.Write(data,0,data.Length);
  356. // Read next line
  357. line = reader.ReadLine();
  358. }
  359. reader.Close();
  360. mhStrm.Position = 0;
  361. return mhStrm;
  362. }
  363. #endregion
  364. #region function IsNumber
  365. /// <summary>
  366. /// Checks if specified string is number(long).
  367. /// </summary>
  368. /// <param name="str"></param>
  369. /// <returns></returns>
  370. public static bool IsNumber(string str)
  371. {
  372. try
  373. {
  374. Convert.ToInt64(str);
  375. return true;
  376. }
  377. catch{
  378. return false;
  379. }
  380. }
  381. #endregion
  382. }
  383. }