Skip to content
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
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Rnwood.Smtp4dev/bin/Debug/net8.0/Rnwood.Smtp4dev.dll",
"cwd": "${workspaceFolder}/Rnwood.Smtp4dev",
"args": ["--recreatedb", "--urls", "http://localhost:5000"],
"args": ["--recreatedb", "--urls", "http://localhost:5000", "--basepath=/smtp4dev"],
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": "build Rnwood.Smtp4dev",
Expand All @@ -30,7 +30,7 @@
"name": "Chrome (Client Debug)",
"type": "chrome",
"request": "launch",
"url": "http://localhost:5000",
"url": "http://localhost:5000/smtp4dev",
"webRoot": "${workspaceFolder}/Rnwood.Smtp4dev/ClientApp/src",
"sourceMapPathOverrides": {
"../../ClientApp/src/*": "${webRoot}/*",
Expand Down
1 change: 0 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/Rnwood.Smtp4dev",
"/property:GenerateFullPaths=true"
],
"problemMatcher": "$msCompile",
Expand Down
6 changes: 4 additions & 2 deletions Rnwood.Smtp4dev.Tests/E2E/E2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ public class E2ETestOptions
{
public bool InMemoryDB { get; set; }
public string BasePath { get; set; }
public IDictionary<string,string> EnvironmentVariables { get; set; } = new Dictionary<string,string>();

public string TestPath { get; set; }
public IDictionary<string, string> EnvironmentVariables { get; set; } = new Dictionary<string, string>();
}

public class E2ETestContext
Expand Down Expand Up @@ -156,7 +158,7 @@ protected void RunE2ETest(Action<E2ETestContext> test, E2ETestOptions options =
if (newLine.StartsWith("Now listening on: http://"))
{
int portNumber = int.Parse(Regex.Replace(newLine, @".*http://[^\s]+:(\d+)", "$1"));
baseUrl = new Uri($"http://localhost:{portNumber}{options.BasePath ?? ""}");
baseUrl = new Uri($"http://localhost:{portNumber}{options.TestPath ?? options.BasePath ?? ""}");
}

if (newLine.StartsWith("SMTP Server is listening on port"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ public E2ETests_WebUI_CheckMessageIsReceivedAndDisplayed(ITestOutputHelper outpu
{
}

[Theory]
[InlineData("/", false)]
[InlineData("/", true)]
[InlineData("/smtp4dev", true)]
public void CheckMessageIsReceivedAndDisplayed(string basePath, bool inMemoryDb)
[Theory]
[InlineData("", "", false)]
[InlineData("", "/", true)]
[InlineData("/smtp4dev", "/smtp4dev", true)]
[InlineData("/smtp4dev", "/smtp4dev/", true)]
[InlineData("/smtp4dev", "", true)]
[InlineData("/smtp4dev", "/", true)]
public void CheckMessageIsReceivedAndDisplayed(string basePath, string testPath, bool inMemoryDb)
{
RunUITestAsync($"{nameof(CheckMessageIsReceivedAndDisplayed)}-{basePath}-{inMemoryDb}", async (page, baseUrl, smtpPortNumber) =>
{
Expand Down Expand Up @@ -59,13 +62,14 @@ public void CheckMessageIsReceivedAndDisplayed(string basePath, bool inMemoryDb)
var rows = await grid.GetRowsAsync();
return rows.FirstOrDefault();
});

Assert.NotNull(messageRow);
Assert.True(await messageRow.ContainsTextAsync(messageSubject));
}, new UITestOptions
{
InMemoryDB = inMemoryDb,
BasePath = basePath
BasePath = basePath,
TestPath = testPath
});
}
}
Expand Down
4 changes: 2 additions & 2 deletions Rnwood.Smtp4dev/ClientApp/src/components/home/home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<div style="flex: 0 0 content">
<a href="https://github.com/rnwood/smtp4dev/" target="_blank">

<UseDark v-slot="{ isDark, toggleDark }">
<img height="35" :src="isDark ? '/logo-dark.png' : '/logo.png'" class="logo" alt="smtp4dev" />
<UseDark v-slot="{ isDark }">
<img height="35" :src="isDark ? './logo-dark.png' : './logo.png'" class="logo" alt="smtp4dev" />
</UseDark>
</a>
</div>
Expand Down
42 changes: 29 additions & 13 deletions Rnwood.Smtp4dev/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private static void ValidateDatabaseVersionCompatibility(Smtp4devDbContext conte

// Get all migrations that have been applied to the database
var appliedMigrations = context.Database.GetAppliedMigrations().ToList();

// Get all migrations available in the current application
var availableMigrations = context.Database.GetMigrations().ToList();

Expand Down Expand Up @@ -92,7 +92,7 @@ public void ConfigureServices(IServiceCollection services)
//Remove the JSON content type from the actions where it is not supported.
NSwag.OpenApiOperationDescription sendOp = d.Operations.FirstOrDefault(o => o.Path.EndsWith("/send") || o.Path.EndsWith("/reply"));
sendOp.Operation.RequestBody.Content.Remove("application/json");

};
});

Expand Down Expand Up @@ -131,10 +131,10 @@ public void ConfigureServices(IServiceCollection services)


using var context = new Smtp4devDbContext((DbContextOptions<Smtp4devDbContext>)opt.Options);

// Validate database version compatibility before attempting any operations
ValidateDatabaseVersionCompatibility(context);

if (string.IsNullOrEmpty(serverOptions.Database))
{
context.Database.Migrate();
Expand Down Expand Up @@ -178,7 +178,7 @@ public void ConfigureServices(IServiceCollection services)
{
Log.Logger.Information("Populating MIME metadata for {count} existing messages during startup", messagesWithoutMetadata.Count);
var mimeProcessingService = new MimeProcessingService();

int processed = 0;
int batchSize = 50; // Process in batches to avoid memory issues

Expand Down Expand Up @@ -335,14 +335,30 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

if (!string.IsNullOrEmpty(serverOptions.BasePath) && serverOptions.BasePath != "/")
{
RewriteOptions rewrites = new RewriteOptions();
rewrites.AddRedirect("^" + serverOptions.BasePath.TrimEnd('/') + "$", serverOptions.BasePath.TrimEnd('/') + "/");
;
rewrites.AddRedirect("^(/)?$", serverOptions.BasePath.TrimEnd('/') + "/");
;
app.UseRewriter(rewrites);

app.Map(serverOptions.BasePath, configure);
string basePathNoSlash = serverOptions.BasePath.TrimEnd('/');
string redirectTarget = basePathNoSlash + "/";

// Global middleware to redirect /smtp4dev to /smtp4dev/
app.Use(async (context, next) =>
{
if (context.Request.Path.Equals(basePathNoSlash, StringComparison.OrdinalIgnoreCase)
&& !context.Request.Path.Value.EndsWith("/"))
{
var queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : "";
context.Response.Redirect(redirectTarget + queryString, true);
return;
}
else if (context.Request.Path.Value.Equals("/")
|| context.Request.Path.Value == String.Empty)
{
var queryString = context.Request.QueryString.HasValue ? context.Request.QueryString.Value : "";
context.Response.Redirect(redirectTarget + queryString, true);
return;
}
await next();
});

app.Map(serverOptions.BasePath.TrimEnd('/'), configure);
}
else
{
Expand Down
12 changes: 5 additions & 7 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ stages:
condition: succeeded()
jobs:
- job: BuildMatrix
displayName: Build and test -
displayName: Build
timeoutInMinutes: 90
pool:
vmImage: $(vmImage)
Expand Down Expand Up @@ -1100,19 +1100,17 @@ stages:

File Name | Description
-- | --
[Winget package](https://winget.run/pkg/rnwood/smtp4dev/desktop)| Rnwood.Smtp4dev.Desktop Winget package (recommended easy option for Win10/11)
[Winget package](https://winget.run/pkg/rnwood/smtp4dev)| Rnwood.Smtp4dev Winget package Win10/11)
Winget package ```winget install -v "${tag}" -e Rnwood.Smtp4dev.Desktop``` | Rnwood.Smtp4dev.Desktop Winget package (recommended easy option for Win10/11)
Winget package ```winget install -v "${tag}" -e Rnwood.Smtp4dev``` | Rnwood.Smtp4dev Winget package Win10/11)
[.NET tool - ```dotnet tool install -g Rnwood.Smtp4dev --version "$(tag)"```](https://www.nuget.org/packages/Rnwood.Smtp4dev/$(tag)) | .NET tool (recommended option for Mac OS) - [How to use dotnet tool](https://github.com/rnwood/smtp4dev/blob/master/docs/Installation.md#how-to-run-smtp4dev-as-a-dotnet-global-tool)
[Rnwood.Smtp4dev-win-x64-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev-win-x64-$(tag).zip) | Windows x64 binary standalone - Server edition
[Rnwood.Smtp4dev.Desktop-win-x64-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev.Desktop-win-x64-$(tag).zip) | Windows x64 binary standalone - Desktop app edition.
[Rnwood.Smtp4dev-win-arm64-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev-win-arm64-$(tag).zip) | Windows ARM 62-bit binary standalone
[Rnwood.Smtp4dev-linux-x64-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev-linux-x64-$(tag).zip) | Linux x64 (Intel 64 bit) binary standalone
[Rnwood.Smtp4dev-linux-musl-x64-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev-linux-musl-x64-$(tag).zip) | Linux MUSL x64 binary standalone for Linux distros using MUSL libc
[Rnwood.Smtp4dev-noruntime-$(tag).zip](../../releases/download/$(tag)/Rnwood.Smtp4dev-noruntime-$(tag).zip) | Architecture independent version. Should run on any platform where the .NET 8.0 (or greater) runtime is installed
[Docker images for Windows and Linux](https://hub.docker.com/layers/rnwood/smtp4dev/$(tag)) - [How to use Docker image](https://github.com/rnwood/smtp4dev/blob/master/docs/Installation.md#how-to-run-smtp4dev-in-docker)
[.NET tool Rnwood.Smtp4dev $(tag)](https://www.nuget.org/packages/Rnwood.Smtp4dev/$(tag)) | .NET tool (recommended option for Mac OS) - [How to use dotnet tool](https://github.com/rnwood/smtp4dev/blob/master/docs/Installation.md#how-to-run-smtp4dev-as-a-dotnet-global-tool)




${{ if eq(variables['isreleasebuild'], true) }}:
action: edit
isPreRelease: false
Expand Down
Loading