Skip to content

Commit

Permalink
added version8 doco
Browse files Browse the repository at this point in the history
  • Loading branch information
cosullivan committed Nov 3, 2020
1 parent 7dfdce9 commit 1fcbd67
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Examples/WorkerService/ConsoleMessageStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public sealed class ConsoleMessageStore : MessageStore
public override async Task<SmtpResponse> SaveAsync(ISessionContext context, IMessageTransaction transaction, ReadOnlySequence<byte> buffer, CancellationToken cancellationToken)
{
await using var stream = new MemoryStream();

var position = buffer.GetPosition(0);
while (buffer.TryGet(ref position, out var memory))
{
Expand Down
2 changes: 1 addition & 1 deletion Examples/WorkerService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
{
var options = new SmtpServerOptionsBuilder()
.ServerName("SMTP Server")
.Port(9025)
.Port(25)
.Build();

return new SmtpServer.SmtpServer(options, provider.GetRequiredService<IServiceProvider>());
Expand Down
41 changes: 27 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ SmtpServer is a simple, but highly functional SMTP server implementation. Writte

SmtpServer is available via [NuGet](https://www.nuget.org/packages/SmtpServer/)

# Whats New?
See [here](https://github.com/cosullivan/SmtpServer/blob/master/Version8.md) for whats new in Version 8.

# What does it support?
SmtpServer currently supports the following ESMTP extensions:
* STARTTLS
Expand All @@ -24,7 +27,7 @@ var options = new SmtpServerOptionsBuilder()
.Port(25, 587)
.Build();

var smtpServer = new SmtpServer.SmtpServer(options);
var smtpServer = new SmtpServer.SmtpServer(options, ServiceProvider.Default);
await smtpServer.StartAsync(CancellationToken.None);
```

Expand All @@ -36,27 +39,37 @@ var options = new SmtpServerOptionsBuilder()
.Port(25, 587)
.Port(465, isSecure: true)
.Certificate(CreateX509Certificate2())
.MessageStore(new SampleMessageStore())
.MailboxFilter(new SampleMailboxFilter())
.UserAuthenticator(new SampleUserAuthenticator())
.Build();

var smtpServer = new SmtpServer.SmtpServer(options);
var serviceProvider = new ServiceProvider();
serviceProvider.Add(new SampleMessageStore());
serviceProvider.Add(new SampleMailboxFilter());
serviceProvider.Add(new SampleUserAuthenticator());

var smtpServer = new SmtpServer.SmtpServer(options, serviceProvider);
await smtpServer.StartAsync(CancellationToken.None);
```

```cs
public class SampleMessageStore : MessageStore
{
public override Task<SmtpResponse> SaveAsync(ISessionContext context, IMessageTransaction transaction, CancellationToken cancellationToken)
{
var textMessage = (ITextMessage)transaction.Message;

var message = MimeKit.MimeMessage.Load(textMessage.Content);
Console.WriteLine(message.TextBody);

return Task.FromResult(SmtpResponse.Ok);
}
public override async Task<SmtpResponse> SaveAsync(ISessionContext context, IMessageTransaction transaction, ReadOnlySequence<byte> buffer, CancellationToken cancellationToken)
{
await using var stream = new MemoryStream();

var position = buffer.GetPosition(0);
while (buffer.TryGet(ref position, out var memory))
{
await stream.WriteAsync(memory, cancellationToken);
}

stream.Position = 0;

var message = await MimeKit.MimeMessage.LoadAsync(stream, cancellationToken);
Console.WriteLine(message.TextBody);

return SmtpResponse.Ok;
}
}
```

Expand Down
4 changes: 1 addition & 3 deletions Src/SmtpServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.352
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{A965DCEA-280B-447A-B5C5-4089C444C2B7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmtpServer", "SmtpServer\SmtpServer.csproj", "{0A7CFC3D-305C-4018-9052-3A7A8B5DD104}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmtpServer.Benchmarks", "SmtpServer.Benchmarks\SmtpServer.Benchmarks.csproj", "{7AE1F3B4-2C00-4BAA-A13C-5EBD43EDE81A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmtpServer.Tests", "SmtpServer.Tests\SmtpServer.Tests.csproj", "{4957B054-F07E-402D-A3EC-7EBA0B3018B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkerService", "..\Examples\WorkerService\WorkerService.csproj", "{EE0C474F-8404-4FB6-865F-A034B5DB77FE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkerService", "..\Examples\WorkerService\WorkerService.csproj", "{EE0C474F-8404-4FB6-865F-A034B5DB77FE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{6BAD2430-FA6B-4929-8BD7-66663CA02207}"
EndProject
Expand Down
35 changes: 29 additions & 6 deletions Version8.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# What's new in Version 8
* Big refactor to Pipeline
* Utilising Span and Memory to dramatically reduce the allocations
Version 8 contains substantial refactoring to take advantage of [System.IO.Pipelines](https://www.nuget.org/packages/System.IO.Pipelines/) in an effort to improve throughput performance and reduce memory allocations.

In addition to this there are also changes to make service resolution easier via Dependency Injection through utilizing the [IServiceProvider](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider) interface.

## Performance
The *Send* test is the resul of having a basic SmtpServer configuration and sending a 143kb email that was take from the Enron Corpus.
The throuhput performance and memory allocation of version 7.2 and version 8 were benchmarked using [BenchmarkDotNet](https://www.nuget.org/packages/BenchmarkDotNet/). The benchmark consisted of a single *Send* test which is the result of having a basic SmtpServer configuration and sending a 143kb email that was take from the Enron Corpus dataset.

### Version 7.2

Expand All @@ -17,7 +18,29 @@ The *Send* test is the resul of having a basic SmtpServer configuration and send
|------- |---------:|----------:|----------:|--------:|------:|------:|----------:|
| Send | 2.204 ms | 0.0307 ms | 0.0287 ms | 11.7188 | - | - | 41.91 KB |

## Extensibility
ISmtpCommandFactory
- add Sample for overriding Greeting
## Breaking Changes
There are a number of breaking changes from v7.

### SmtpServerOptionsBuilder
The SmtpServerOptionsBuilder is now used to configure the SMTP Server options only and the extensibility services such as IMessageStore, IMailboxFilter, IUserAuthenticator, and IEndpointListener have now been removed from the SmtpServerOptionsBuilder.

### Extensibility Services

#### Service Configuration
The extensibility services such as IMessageStore, IMailboxFilter, IUserAuthenticator, and IEndpointListener are now resolved internally via an instance of [IServiceProvider](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider). This makes it easier to support Dependency Injection, however, there is a default implementation of the [IServiceProvider](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider) included that will just resolve the specific instances required for the SmtpServer. The [IServiceProvider](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider) instance is a constructor parameter on the SmtpServer instance.

#### Service Resolution
The IMessageStore, IMailboxFilter, and IUserAuthenticator instances were previously resolved by calling the appropriate CreateInstance method on the instance factory, for example, IMessageStoreFactory, IMailboxFilterFactory, and IUserAuthenticatorFactory.

#### IMessageStore
The IMessageStore interface has a breaking change to the SaveAsync method. The message contents is now included as a [ReadOnlySequence<byte>](https://docs.microsoft.com/en-us/dotnet/api/system.buffers.readonlysequence-1) buffer parameter on the method.

``` csharp
Task<SmtpResponse> SaveAsync(
ISessionContext context,
IMessageTransaction transaction,
ReadOnlySequence<byte> buffer,
CancellationToken cancellationToken);
```

This is the exact buffer that is read from the input stream so care must be taken when using it. It must not be referenced and used outside of the scope of this method.

0 comments on commit 1fcbd67

Please sign in to comment.