Skip to content
Browse files

Deal with comments, unit tests

- Deal with comments + unit tests.
- Version 3.6.0.0
  • Loading branch information...
1 parent a865dce commit 874de537106804fed9cd752b9945c666af6221e2 @smiley22 committed
View
25 MailMessage.cs
@@ -12,9 +12,30 @@ namespace S22.Imap {
/// Adds extension methods to the MailMessage class of the .NET Framework.
/// </summary>
/// <remarks>
- /// These are only used internally and are not visible outside of the S22.Imap assembly.
+ /// Most of the methods are only used internally and are not visible outside of the
+ /// S22.Imap assembly.
/// </remarks>
- internal static class MailMessageExtension {
+ public static class MailMessageExtension {
+ /// <summary>
+ /// Returns the date and time the mail message was composed.
+ /// </summary>
+ /// <param name="message">The MailMessage instance to return the date and time for.</param>
+ /// <returns>The date and time the mail message was composed, or null if the mail message
+ /// does not contain any date information.</returns>
+ public static DateTime? Date(this MailMessage message) {
+ string date = message.Headers["Date"];
+ if (String.IsNullOrEmpty(date))
+ return null;
+ // Dates are sometimes suffixed with comments indicating the timezone, for example:
+ // Tue, 29 Mar 2005 15:11:45 -0800 (PST).
+ date = Regex.Replace(date, @"\([^\)]+\)", String.Empty);
+ try {
+ return DateTime.Parse(date);
+ } catch (FormatException) {
+ return null;
+ }
+ }
+
/// <summary>
/// Constructs a textual representation of a mail message from the specified MailMessage
/// instance compliant with the RFC822 and MIME standards.
View
37 MessageBuilder.cs
@@ -84,6 +84,8 @@ internal static class MessageBuilder {
StringReader reader = new StringReader(header);
NameValueCollection coll = new NameValueCollection();
string line, fieldname = null, fieldvalue = null;
+ var exclude = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) {
+ "Subject", "Comments", "Content-disposition", "User-Agent" };
while ((line = reader.ReadLine()) != null) {
if (line == String.Empty)
continue;
@@ -99,12 +101,47 @@ internal static class MessageBuilder {
continue;
fieldname = line.Substring(0, delimiter).Trim();
fieldvalue = line.Substring(delimiter + 1).Trim();
+ // Strip comments from RFC822 and MIME fields unless they are unstructured fields.
+ if (!exclude.Contains(fieldname))
+ fieldvalue = StripComments(fieldvalue);
coll.Add(fieldname, fieldvalue);
}
return coll;
}
/// <summary>
+ /// Strips RFC822/MIME comments from the specified string.
+ /// </summary>
+ /// <param name="s">The string to strip comments from.</param>
+ /// <returns>A new string stripped of any comments.</returns>
+ internal static string StripComments(string s) {
+ if (String.IsNullOrEmpty(s))
+ return s;
+ bool inQuotes = false, escape = false;
+ char last = ' ';
+ int depth = 0;
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < s.Length; i++) {
+ char c = s[i];
+ if (c == '\\' && !escape) {
+ escape = true;
+ continue;
+ }
+ if (c == '"' && !escape)
+ inQuotes = !inQuotes;
+ last = c;
+ if (!inQuotes && !escape && c == '(')
+ depth++;
+ else if (!inQuotes && !escape && c == ')' && depth > 0)
+ depth--;
+ else if (depth <= 0)
+ builder.Append(c);
+ escape = false;
+ }
+ return builder.ToString().Trim();
+ }
+
+ /// <summary>
/// Parses a MIME header field which can contain multiple 'parameter = value'
/// pairs (such as Content-Type: text/html; charset=iso-8859-1).
/// </summary>
View
4 Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.5.0.3")]
-[assembly: AssemblyFileVersion("3.5.0.3")]
+[assembly: AssemblyVersion("3.6.0.0")]
+[assembly: AssemblyFileVersion("3.6.0.0")]
View
3 Readme.md
@@ -47,7 +47,8 @@ further details on using the classes and methods exposed by the S22.Imap namespa
+ Inherently thread-safe
+ Well documented with lots of example code
+ Robust MIME parser, tested with 100.000+ mails
-+ Supports various SASL authentication mechanisms (SCRAM-SHA-1, OAUTH2, NTLM among [others](https://github.com/smiley22/S22.Imap/blob/master/AuthMethod.cs))
++ Supports various authentication mechanisms (SCRAM-SHA-1, OAUTH2, NTLM among [others](https://github.com/smiley22/S22.Imap/blob/master/AuthMethod.cs))
++ Integrates well with existing System.Net.Mail infrastructure
+ Still supports .NET 3.5
+ Free to use in commercial and personal projects ([MIT license](https://github.com/smiley22/S22.Imap/blob/master/License.md))
View
22 Tests/MessageBuilderTest.cs
@@ -174,6 +174,28 @@ public class MessageBuilderTest {
}
/// <summary>
+ /// Ensures RFC822/MIME comments are processed properly.
+ /// </summary>
+ [TestMethod]
+ [TestCategory("BuildMessageFromMIME822")]
+ public void MessageWithMIMEComments() {
+ MailMessage m = MessageBuilder.FromMIME822(Properties.Resources.MailWithMIMEComments);
+
+ Assert.AreEqual<string>("1.0", m.Headers["Mime-version"]);
+ Assert.AreEqual<bool>(true, m.IsBodyHtml);
+ Assert.AreEqual<string>("utf-8", m.BodyEncoding.WebName);
+ Assert.AreEqual<string>("HUB02.mailcluster.uni-bonn.de",
+ m.Headers["X-MS-Exchange-Organization-AuthSource"]);
+ // Parentheses in the subject should be left alone.
+ Assert.AreEqual<string>("Business Development Meeting (Important)", m.Subject);
+ // Parentheses in double-quoted strings should also be left alone.
+ Assert.AreEqual<string>("Taylor (John) Evans", m.From.DisplayName);
+ Assert.AreEqual<string>("example_from@dc.edu", m.From.Address);
+ Assert.AreEqual<string>("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) " +
+ "Gecko/20020823 Netscape/7.0", m.Headers["User-Agent"]);
+ }
+
+ /// <summary>
/// Ensures address-lists with multiple addresses are properly parsed.
/// </summary>
[TestMethod]
View
19 Tests/Properties/Resources.Designer.cs
@@ -194,6 +194,25 @@ internal class Resources {
}
/// <summary>
+ /// Looks up a localized string similar to Return-Path: &lt;example_from@dc.edu&gt;
+ ///X-SpamCatcher-Score: 1 [X]
+ ///Received: from [136.167.40.119] (HELO dc.edu)
+ /// by fe3.dc.edu (CommuniGate Pro SMTP 4.1.8)
+ /// with ESMTP-TLS id 61258719 for example_to@mail.dc.edu; Mon, 23 Aug 2004 11:40:10 -0400
+ ///Message-ID: &lt;4129F3CA.2020509@dc.edu&gt;
+ ///Date: Mon, 23 Aug 2005 11:40:36 -0400
+ ///From: &quot;Taylor (John) Evans&quot; &lt;example_from@dc.edu&gt;
+ ///User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0
+ ///X-Accept-Language: en-us, en
+ ///MIME-Vers [rest of string was truncated]&quot;;.
+ /// </summary>
+ internal static string MailWithMIMEComments {
+ get {
+ return ResourceManager.GetString("MailWithMIMEComments", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to From: &quot;xxxxxxx&quot; &lt;xxxxxxx@ms19.hinet.net&gt;
///To: &quot;=?big5?B?pUS3UqTAqMm69A==?=&quot; &lt;xxxxxxx@ms19.hinet.net&gt;
///Subject: =?big5?B?tbmvuKr4qrqkQKvKq0g=?=
View
3 Tests/Properties/Resources.resx
@@ -204,4 +204,7 @@ Martin.</value>
<data name="MailWithRfc2231Headers2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\MailWithRfc2231Headers2.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
+ <data name="MailWithMIMEComments" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>..\Resources\MailWithMIMEComments.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
+ </data>
</root>
View
18 Tests/Resources/MailWithMIMEComments.txt
@@ -0,0 +1,18 @@
+Return-Path: <example_from@dc.edu>
+X-SpamCatcher-Score: 1 [X]
+Received: from [136.167.40.119] (HELO dc.edu)
+ by fe3.dc.edu (CommuniGate Pro SMTP 4.1.8)
+ with ESMTP-TLS id 61258719 for example_to@mail.dc.edu; Mon, 23 Aug 2004 11:40:10 -0400
+Message-ID: <4129F3CA.2020509@dc.edu>
+Date: Mon, 23 Aug 2005 11:40:36 -0400
+From: "Taylor (John) Evans" <example_from@dc.edu>
+User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0
+X-Accept-Language: en-us, en
+MIME-Version: 1.0 (generated by my-application 1.2)
+To: Jon Smith <example_to@mail.dc.edu>
+Subject: Business Development Meeting (Important)
+Content-Type: text/html (HTML EMAIL); charset=utf-(this is a (nested) comment)8; format=flowed
+Content-Transfer-Encoding: 7bit
+X-MS-Exchange-Organization-AuthSource: HUB02(public hub).mailcluster.uni-bonn.(another (co(m)me)nt)de
+
+This is a test.
View
3 Tests/Tests.csproj
@@ -108,6 +108,9 @@
<ItemGroup>
<None Include="Resources\MailWithRfc2231Headers2.txt" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\MailWithMIMEComments.txt" />
+ </ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>

0 comments on commit 874de53

Please sign in to comment.
Something went wrong with that request. Please try again.