Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed dependencies and synchronous IO operations #3

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions QuoteParser.Tests/EmailTestBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using MimeKit;
using MimeKit.Text;
using System;
using System.IO;
using Xunit;

Expand All @@ -18,17 +20,18 @@ protected EmailTestBase(string folder)

protected void Check(int emailNum, QuoteHeader expectedQuoteHeader)
{
using (var stream = GetResourceStream(emailNum))
{
var content = _parser.Value.Parse(stream);
Assert.Equal(expectedQuoteHeader, content.Header);
}
var content = _parser.Value.Parse(GetResourceTextBody(emailNum));
Assert.Equal(expectedQuoteHeader, content.Header);
}

protected Stream GetResourceStream(int emailNum)
protected string GetResourceTextBody(int emailNum)
{
var asm = typeof(ABTests).Assembly;
return asm.GetManifestResourceStream($"{asm.GetName().Name}.Resources.testEmls.{_folder}.{emailNum}.eml");
using (var stream = asm.GetManifestResourceStream($"{asm.GetName().Name}.Resources.testEmls.{_folder}.{emailNum}.eml")) {
return MimeMessage
.Load(stream)
.GetTextBody(TextFormat.Plain);
}
}

protected virtual QuoteParser CreateQuoteParser()
Expand Down
1 change: 1 addition & 0 deletions QuoteParser.Tests/QuoteParser.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="MimeKitLite" Version="2.3.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
Expand Down
25 changes: 10 additions & 15 deletions QuoteParser.Tests/RecTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using Xunit;

namespace QuoteParser.Tests
Expand Down Expand Up @@ -41,13 +42,10 @@ public void TestEmail270()
"In reply to:"
}
);

using (var stream = GetResourceStream(emailNum))
{
var content = Parser.Parse(stream);
Assert.Equal(expectedQuoteHeader, content.Header);
Assert.Equal(expectedInnerQuoteHeader, content.Quote?.Header);
}

var content = Parser.Parse(GetResourceTextBody(emailNum));
Assert.Equal(expectedQuoteHeader, content.Header);
Assert.Equal(expectedInnerQuoteHeader, content.Quote?.Header);
}

[Fact]
Expand Down Expand Up @@ -84,14 +82,11 @@ public void TestEmail6510()
"##- Please type your reply above this line -## "
}
);

using (var stream = GetResourceStream(emailNum))
{
var content = Parser.Parse(stream);
Assert.Equal(expectedQuoteHeader1, content.Header);
Assert.Equal(expectedQuoteHeader2, content.Quote?.Header);
Assert.Equal(expectedQuoteHeader3, content.Quote?.Quote?.Header);
}

var content = Parser.Parse(GetResourceTextBody(emailNum));
Assert.Equal(expectedQuoteHeader1, content.Header);
Assert.Equal(expectedQuoteHeader2, content.Quote?.Header);
Assert.Equal(expectedQuoteHeader3, content.Quote?.Quote?.Header);
}
}
}
24 changes: 0 additions & 24 deletions QuoteParser/Parse.cs

This file was deleted.

7 changes: 2 additions & 5 deletions QuoteParser/QuoteParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.IO;
using System.Linq;
using QuoteParser.Features;
using static QuoteParser.Parse;
using static QuoteParser.Features.QuoteMarkFeature;
using KeyPhrasesClass = QuoteParser.Features.KeyPhrases;

Expand Down Expand Up @@ -137,11 +136,9 @@ private QuoteParser(Builder builder)
);
}

public Content Parse(Stream emlFile)
public Content Parse(string text, bool hasInReplyToEmlHeader = true)
{
var msg = GetMimeMessage(emlFile);
string emailText = GetEmailText(msg);
return Parse(emailText.Lines(), ContainInReplyToHeader(msg));
return Parse(text.Split(new[] { "\n", "\r\n" }, StringSplitOptions.None), hasInReplyToEmlHeader);
}

public Content Parse(IEnumerable<string> lines, bool hasInReplyToEmlHeader = true)
Expand Down
6 changes: 1 addition & 5 deletions QuoteParser/QuoteParser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
<PackageIconUrl>https://raw.githubusercontent.com/feature23/QuoteParser.NET/master/logo.png</PackageIconUrl>
<RepositoryUrl></RepositoryUrl>
<PackageTags>quoteparser email-parser email parse parsing quote reply</PackageTags>
<Version>2.0.0</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2018.3.0" />
<PackageReference Include="MimeKitLite" Version="2.1.1" />
</ItemGroup>

</Project>
95 changes: 95 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,97 @@
# QuoteParser.NET [![Build Status](https://travis-ci.org/feature23/QuoteParser.NET.svg?branch=master)](https://travis-ci.org/feature23/QuoteParser.NET)
A .NET Standard port of JetBrains' [email-parser](https://github.com/JetBrains/email-parser) library.

## Usage Example
The `QuoteParser` class processes the plain text body content of an email message, separating the content of the latest reply from any previous quoted exchanges:

```csharp
// create an instance of the parser builder
var builder = new QuoteParser.QuoteParser.Builder();

// configure the builder using the fluent interface to override any defaults
builder = builder.MinimumQuoteBlockSize(10);

// build the parser
var parser = builder.Build();

// example reply email content that includes a quote of the original message
var emailContent =
@"this is the latest reply body text

On Tue, Oct 30, 2019, at 12:00 AM, Person A <[email protected]> wrote:

> this is the original message that was replied to";

// parse the email content
var content = parser.Parse(emailContent);

// write the content of the latest reply to the console
Console.Write(String.Join(Environment.NewLine, content.Body)); // this is the latest reply body text
```

### Processing raw MIME messages
If you are processing the full raw MIME message, you need to first extract the plain text body content using a MIME parser such as the one included with [MimeKit](http://www.mimekit.net/). The example below uses the `MimeMessage` class which is included with [MimeKitLite](https://www.nuget.org/packages/MimeKitLite/), [MimeKit](https://www.nuget.org/packages/MimeKit/) and [MailKit](https://www.nuget.org/packages/MailKit/).

```csharp
// same example as above only in raw MIME format
var rawEmailContent =
@"MIME-Version: 1.0
From: Person B <[email protected]>
To: Person A <[email protected]>
In-Reply-To: <[email protected]>
Content-Type: multipart/alternative; boundary=""random-boundary-id text""

--random-boundary-id text
Content-Type: text/plain

this is the latest reply body text

On Tue, Oct 30, 2019, at 12:00 AM, Person A <[email protected]> wrote:

> this is the original message that was replied to

--random-boundary-id text
Content-Type: text/html;
Content-Transfer-Encoding: quoted-printable

<p>this is the latest reply body text<p>

<p>On Tue, Oct 30, 2019, at 12:00 AM, Person A <[email protected]> wrote:</p>

<blockquote><p>this is the original message that was replied to<p></blockquote>

--random-boundary-id text--
";

// parse the message using MimeKit
var message = MimeMessage.Load(new MemoryStream(Encoding.UTF8.GetBytes(rawEmailContent)));

// get the plain text body
var emailContent = message.GetTextBody(TextFormat.Plain);

// check for reply headers
var hasInReplyToHeader = message.Headers.Contains("In-Reply-To") || message.Headers.Contains("References");

// parse the text body using QuoteParser
var content = new QuoteParser.QuoteParser
.Builder()
.Build()
.Parse(emailContent, hasInReplyToHeader);

// write the content of the latest reply to the console
Console.Write(String.Join(Environment.NewLine, content.Body)); // this is the latest reply body text
```

### QuoteParser.Builder Configuration

|Builder Method|Default Value|
|---|---|
|`HeaderLinesCount`|`3`|
|`MultiLineHeaderLinesCount`|`6`|
|`MinimumQuoteBlockSize`|`7`|
|`DeleteQuoteMarks`|`true`|
|`Recursive`|`false`|
|`KeyPhrases`|`InReplyToRegex, ReplyAboveRegex, OriginalMsgRegex`|

## Version 2.0.0 Breaking Changes
Removed MimeKitLite dependency in order to avoid duplicate type/namespace conflits for projects that already included (directly or indirectly) different versions of MimeKitLite, MimeKit or MailKit. See example above for processing raw MIME messages.