Skip to content

Commit

Permalink
Add GitHub build logic (#220)
Browse files Browse the repository at this point in the history
* Add build script

* reactivate one unit test

* Update SmtpServerTests.cs

* Reactivate all unit tests

* Update SmtpServerTests.cs
  • Loading branch information
tinohager authored Aug 28, 2024
1 parent 9d253c4 commit cffd7df
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 90 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build and Publish

on:
workflow_dispatch: # Allow running the workflow manually from the GitHub UI
push:
paths:
- 'Src/**'
- '.github/workflows/**'
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v4
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
working-directory: ./Src
run: dotnet restore
- name: Build
working-directory: ./Src
run: dotnet build --configuration Release --no-restore
- name: Test
working-directory: ./Src
run: |
dotnet test --configuration Release --no-restore --no-build --verbosity normal
#- name: Create NuGet packages
# run: |
# dotnet pack --configuration Release --output $GITHUB_WORKSPACE/out Src/SmtpServer/SmtpServer.csproj
#- name: Push NuGet packages
# run: |
# dotnet nuget push $GITHUB_WORKSPACE/out/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.NUGET_TOKEN}} --skip-duplicate --no-symbols
4 changes: 2 additions & 2 deletions Examples/SampleApp/SampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand All @@ -15,7 +15,7 @@

<ItemGroup>
<PackageReference Include="MailKit" Version="3.4.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Examples/WorkerService/WorkerService.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<UserSecretsId>dotnet-WorkerService-1397719A-187C-45F4-8DB3-2427A449DD89</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Src/SmtpServer.Benchmarks/SmtpServer.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand All @@ -20,7 +20,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="MailKit" Version="3.4.1" />
</ItemGroup>

Expand Down
7 changes: 4 additions & 3 deletions Src/SmtpServer.Tests/MailClient.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Threading;
using MailKit.Net.Smtp;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using MimeKit.Text;
using System.Threading;

namespace SmtpServer.Tests
{
Expand Down Expand Up @@ -49,7 +49,8 @@ public static MimeMessage Message(
public static SmtpClientEx Client(string host = "localhost", int port = 9025, SecureSocketOptions options = SecureSocketOptions.Auto)
{
var client = new SmtpClientEx();

client.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

client.Connected += (sender, args) =>
{

Expand Down
8 changes: 4 additions & 4 deletions Src/SmtpServer.Tests/SmtpServer.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MailKit" Version="3.4.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
163 changes: 86 additions & 77 deletions Src/SmtpServer.Tests/SmtpServerTests.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
using System;
using MailKit;
using SmtpServer.Authentication;
using SmtpServer.ComponentModel;
using SmtpServer.Mail;
using SmtpServer.Net;
using SmtpServer.Protocol;
using SmtpServer.Storage;
using SmtpServer.Tests.Mocks;
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MailKit;
using SmtpServer.Mail;
using SmtpServer.Tests.Mocks;
using Xunit;
using SmtpServer.Authentication;
using SmtpServer.ComponentModel;
using SmtpServer.Net;
using SmtpServer.Protocol;
using SmtpServer.Storage;
using SmtpResponse = SmtpServer.Protocol.SmtpResponse;

namespace SmtpServer.Tests
Expand Down Expand Up @@ -51,6 +52,8 @@ public void CanReceiveMessage()
[InlineData("שלום שלום שלום", "windows-1255")]
public void CanReceiveUnicodeMimeMessage(string text, string charset)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

using (CreateServer())
{
// act
Expand Down Expand Up @@ -245,95 +248,80 @@ public void DoesNotSecureTheSessionWhenCertificateIsEmpty()
[Fact]
public void SecuresTheSessionWhenCertificateIsSupplied()
{
ServicePointManager.ServerCertificateValidationCallback = IgnoreCertificateValidationFailureForTestingOnly;
using var disposable = CreateServer(options => options.Certificate(CreateCertificate()));

using (var disposable = CreateServer(options => options.Certificate(CreateCertificate())))
{
var isSecure = false;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
var isSecure = false;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
{
args.Context.CommandExecuted += (_, commandArgs) =>
{
args.Context.CommandExecuted += (_, commandArgs) =>
{
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});

disposable.Server.SessionCreated += sessionCreatedHandler;

MailClient.Send();
disposable.Server.SessionCreated += sessionCreatedHandler;

disposable.Server.SessionCreated -= sessionCreatedHandler;

Assert.True(isSecure);
}
MailClient.Send();

ServicePointManager.ServerCertificateValidationCallback = null;
disposable.Server.SessionCreated -= sessionCreatedHandler;

Assert.True(isSecure);
}

[Fact]
public void SecuresTheSessionByDefault()
{
ServicePointManager.ServerCertificateValidationCallback = IgnoreCertificateValidationFailureForTestingOnly;
using var disposable = CreateServer(endpoint => endpoint.IsSecure(true).Certificate(CreateCertificate()));

using (var disposable = CreateServer(endpoint => endpoint.IsSecure(true).Certificate(CreateCertificate())))
{
var isSecure = false;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
var isSecure = false;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
{
args.Context.CommandExecuted += (_, commandArgs) =>
{
args.Context.CommandExecuted += (_, commandArgs) =>
{
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});

disposable.Server.SessionCreated += sessionCreatedHandler;

MailClient.NoOp(MailKit.Security.SecureSocketOptions.SslOnConnect);
disposable.Server.SessionCreated += sessionCreatedHandler;

disposable.Server.SessionCreated -= sessionCreatedHandler;

Assert.True(isSecure);
}
MailClient.NoOp(MailKit.Security.SecureSocketOptions.SslOnConnect);

ServicePointManager.ServerCertificateValidationCallback = null;
disposable.Server.SessionCreated -= sessionCreatedHandler;

Assert.True(isSecure);
}

[Fact]
public void ServerCanBeSecuredAndAuthenticated()
{
var userAuthenticator = new DelegatingUserAuthenticator((user, password) => true);

ServicePointManager.ServerCertificateValidationCallback = IgnoreCertificateValidationFailureForTestingOnly;

using (var disposable = CreateServer(
using var disposable = CreateServer(
endpoint => endpoint.AllowUnsecureAuthentication(true).Certificate(CreateCertificate()).SupportedSslProtocols(SslProtocols.Tls12),
services => services.Add(userAuthenticator)))
{
var isSecure = false;
ISessionContext sessionContext = null;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
{
sessionContext = args.Context;
sessionContext.CommandExecuted += (_, commandArgs) =>
{
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});
services => services.Add(userAuthenticator));

disposable.Server.SessionCreated += sessionCreatedHandler;
var isSecure = false;
ISessionContext sessionContext = null;
var sessionCreatedHandler = new EventHandler<SessionEventArgs>(
delegate (object sender, SessionEventArgs args)
{
sessionContext = args.Context;
sessionContext.CommandExecuted += (_, commandArgs) =>
{
isSecure = commandArgs.Context.Pipe.IsSecure;
};
});

MailClient.Send(user: "user", password: "password");
disposable.Server.SessionCreated += sessionCreatedHandler;

disposable.Server.SessionCreated -= sessionCreatedHandler;
MailClient.Send(user: "user", password: "password");

Assert.True(isSecure);
Assert.True(sessionContext.Authentication.IsAuthenticated);
}
disposable.Server.SessionCreated -= sessionCreatedHandler;

ServicePointManager.ServerCertificateValidationCallback = null;
Assert.True(isSecure);
Assert.True(sessionContext.Authentication.IsAuthenticated);
}

[Fact]
Expand All @@ -356,17 +344,38 @@ public void EndpointListenerWillRaiseEndPointEvents()
Assert.True(stopped);
}

public static bool IgnoreCertificateValidationFailureForTestingOnly(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
public static X509Certificate2 CreateSelfSignedCertificate(string subjectName)
{
return true;
var validityPeriodInYears = 1;

using RSA rsa = RSA.Create(2048); // 2048-Bit Key

var certificateRequest = new CertificateRequest(
$"CN={subjectName}", // Common Name (CN)
rsa,
HashAlgorithmName.SHA256, // Hash-Algorithmus
RSASignaturePadding.Pkcs1 // Padding Schema
);

certificateRequest.CertificateExtensions.Add(
new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false)
);

certificateRequest.CertificateExtensions.Add(
new X509BasicConstraintsExtension(true, false, 0, true)
);

DateTimeOffset notBefore = DateTimeOffset.UtcNow;
DateTimeOffset notAfter = notBefore.AddYears(validityPeriodInYears);

X509Certificate2 certificate = certificateRequest.CreateSelfSigned(notBefore, notAfter);

return new X509Certificate2(certificate.Export(X509ContentType.Pfx));
}

public static X509Certificate2 CreateCertificate()
{
var certificate = File.ReadAllBytes(@"C:\Users\caino\Dropbox\Documents\Cain\Programming\SmtpServer\SmtpServer.pfx");
var password = File.ReadAllText(@"C:\Users\caino\Dropbox\Documents\Cain\Programming\SmtpServer\SmtpServerPassword.txt");

return new X509Certificate2(certificate, password);
return CreateSelfSignedCertificate("localhost");
}

/// <summary>
Expand Down

0 comments on commit cffd7df

Please sign in to comment.