SMTPMessage.cs
上传用户:wdhx888
上传日期:2017-06-08
资源大小:112k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using EricDaugherty.CSES.Common;
  5. using System.Text.RegularExpressions;
  6. namespace EricDaugherty.CSES.SmtpServer
  7. {
  8. /// <summary>
  9. /// Stores an incoming SMTP Message.
  10. /// </summary>
  11. public class SMTPMessage: object
  12. {
  13. #region Constants
  14. private static readonly string DOUBLE_NEWLINE = Environment.NewLine + Environment.NewLine;
  15. #endregion
  16. #region Variables
  17. private EmailAddress senderAddress;
  18. private ArrayList recipientAddresses;
  19. private StringBuilder data;
  20. private Hashtable headerFields = null;
  21. #endregion
  22. #region Constructors
  23. /// <summary>
  24. /// Creates a new message.
  25. /// </summary>
  26. public SMTPMessage()
  27. {
  28. recipientAddresses = new ArrayList();
  29. data = new StringBuilder();
  30. }
  31. #endregion
  32. #region Properies
  33. /// <summary>
  34. /// A hash table of all the Headers in the email message.  They keys
  35. /// are the header names, and the values are the assoicated values, including
  36. /// any sub key/value pairs is the header.
  37. /// </summary>
  38. public Hashtable Headers
  39. {
  40.   get
  41.   {
  42.     if( headerFields == null )
  43.     {
  44.       headerFields = ParseHeaders( data.ToString() );
  45.     }
  46. return headerFields;
  47.   }
  48. }
  49. /// <summary>
  50. /// The email address of the person
  51. /// that sent this email.
  52. /// </summary>
  53. public EmailAddress FromAddress
  54. {
  55. get
  56. {
  57. return senderAddress;
  58. }
  59. set
  60. {
  61. senderAddress = value;
  62. }
  63. }
  64. /// <summary>
  65. /// The addresses that this message will be
  66. /// delivered to.
  67. /// </summary>
  68. public EmailAddress[] ToAddresses
  69. {
  70. get
  71. {
  72. return (EmailAddress[]) recipientAddresses.ToArray( typeof( EmailAddress ) );
  73. }
  74. }
  75. /// <summary>Addes an address to the recipient list.</summary>
  76. public void AddToAddress( EmailAddress address )
  77. {
  78. recipientAddresses.Add( address );
  79. }
  80. /// <summary>Message data.</summary>
  81. public string Data
  82. {
  83. get
  84. {
  85. return data.ToString();
  86. }
  87. }
  88. /// <summary>Append data to message data.</summary>
  89. public void AddData( String data )
  90. {
  91. this.data.Append( data );
  92. }
  93. /// <summary>
  94. /// Parses the message body and creates an Attachment object
  95. /// for each attachment in the message.
  96. /// </summary>
  97. public SMTPMessagePart[] MessageParts
  98. {
  99.   get
  100.   {
  101.     return parseMessageParts();
  102.   }
  103. }
  104. #endregion
  105.   #region Private Methods
  106. /// <summary>
  107. /// Parses an entire message or message part and returns the header entries
  108. /// as a hashtable.
  109. /// </summary>
  110. /// <param name="partData">The raw message or message part data.</param>
  111. /// <returns>A hashtable of the header keys and values.</returns>
  112. internal static Hashtable ParseHeaders( string partData )
  113. {
  114. Hashtable headerFields = new Hashtable();
  115. string[] parts = Regex.Split( partData, DOUBLE_NEWLINE );
  116. string headerString = parts[0] + DOUBLE_NEWLINE;
  117. MatchCollection headerKeyCollectionMatch = Regex.Matches( headerString, @"^(?<key>S*):", RegexOptions.Multiline );
  118. string headerKey = null;
  119. foreach( Match headerKeyMatch in headerKeyCollectionMatch )
  120. {
  121.   headerKey = headerKeyMatch.Result( "${key}" );
  122.         Match valueMatch = Regex.Match( headerString, headerKey + @":(?<value>.*?)rn[Sr]", RegexOptions.Singleline );
  123. if( valueMatch.Success )
  124. {
  125. string headerValue = valueMatch.Result( "${value}" ).Trim();
  126. headerValue = Regex.Replace( headerValue, "rn", "" );
  127. headerValue = Regex.Replace( headerValue, @"s+", " " );
  128.   // TODO: Duplicate headers (like Received) will be overwritten by the 'last' value.
  129. headerFields[ headerKey] = headerValue;
  130. }
  131. }
  132. return headerFields;
  133. }
  134.   private SMTPMessagePart[] parseMessageParts()
  135.   {
  136. string message = data.ToString();
  137. string contentType = (string) Headers["Content-Type"];
  138. // Check to see if it is a Multipart Messages
  139. if( contentType != null && Regex.Match( contentType, "multipart/mixed", RegexOptions.IgnoreCase ).Success )
  140. {
  141. // Message parts are seperated by boundries.  Parse out what the boundry is so we can easily
  142. // parse the parts out of the message.
  143. Match boundryMatch = Regex.Match( contentType, "boundary="(?<boundry>\S+)"", RegexOptions.IgnoreCase );
  144. if( boundryMatch.Success )
  145. {
  146. string boundry = boundryMatch.Result( "${boundry}" );
  147. ArrayList messageParts = new ArrayList();
  148. //TODO Improve this Regex.
  149. MatchCollection matches = Regex.Matches( message, "--" + boundry + ".*rn" );
  150. int lastIndex = -1;
  151. int currentIndex = -1;
  152. int matchLength = -1;
  153. string messagePartText = null;
  154. foreach( Match match in matches )
  155. {
  156. currentIndex = match.Index;
  157. matchLength = match.Length;
  158. if( lastIndex != -1 )
  159. {
  160. messagePartText = message.Substring( lastIndex, currentIndex - lastIndex );
  161. messageParts.Add( new SMTPMessagePart( messagePartText ) );
  162. }
  163. lastIndex = currentIndex + matchLength;
  164. }
  165. return (SMTPMessagePart[]) messageParts.ToArray( typeof( SMTPMessagePart ) );
  166. }
  167. }
  168.     return new SMTPMessagePart[0];
  169.   }
  170.   #endregion
  171. }
  172. }