Skip to content

Commit d92978a

Browse files
author
Timothy Dodd
committed
Refactor: Remove SQLite database dependency
This commit removes the `MailDb` class and all associated database operations, eliminating the dependency on ServiceStack.OrmLite and SQLite. The `SettingsHelper` class was also removed, and configuration management was streamlined to directly use the application's base directory. Key changes: - Removed `MailDb` and `SettingsHelper` classes. - Eliminated `ServiceStack.OrmLite.Sqlite.Data` package reference. - Simplified `Program.cs` by restructuring configuration setup and adding `PrintRules` for improved rule logging. - Updated `Rule` and `EmailSettings` classes to remove database-related properties. - Refactored `BatchRuleProcessor` and `RuleMatcher` to simplify rule value handling. - Removed database operations from `EmailMonitoringService`. - Updated `appsettings.json` to remove `StoreMovedMessages` setting. These changes simplify the application's architecture by removing the database layer, focusing on in-memory processing of email rules, and improving maintainability.
1 parent 882678d commit d92978a

8 files changed

Lines changed: 66 additions & 141 deletions

File tree

src/MailZort/MailDb.cs

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/MailZort/MailZort.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" />
3535
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.3" />
3636
<PackageReference Include="Microsoft.NET.Build.Containers" Version="10.0.103" />
37-
<PackageReference Include="ServiceStack.OrmLite.Sqlite.Data" Version="10.0.6" />
3837
<PackageReference Include="System.Text.Json" Version="10.0.3" />
3938
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
4039
</ItemGroup>

src/MailZort/Program.cs

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,31 @@
1-
// See https://aka.ms/new-console-template for more information
2-
3-
41
using MailKit;
5-
using MailZort;
62
using MailZort.Services;
7-
using ServiceStack;
83

94
internal class Program
105
{
116
static async Task Main(string[] args)
127
{
13-
SettingsHelper settingHelper = new();
14-
IConfigurationBuilder builder = new ConfigurationBuilder()
15-
.SetBasePath(settingHelper.SettingPath)
16-
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
17-
.AddEnvironmentVariables();
18-
19-
builder = builder.AddUserSecrets<Program>();
20-
21-
IConfiguration configuration = builder.Build();
22-
238
var host = Host.CreateDefaultBuilder(args)
249
.ConfigureAppConfiguration((context, config) =>
2510
{
26-
// Use the configuration we already built
27-
config.AddConfiguration(configuration);
11+
config.Sources.Clear();
12+
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
13+
config.AddJsonFile("appsettings.json", optional: false);
14+
config.AddEnvironmentVariables();
15+
config.AddUserSecrets<Program>();
2816
})
2917
.ConfigureServices((context, services) =>
3018
{
31-
var rules = context.Configuration.GetSection("Rules")?.Get<IEnumerable<Rule>>()?.Where(x => x.IsEnabled).ToList();
19+
var rules = context.Configuration.GetSection("Rules").Get<List<Rule>>()
20+
?.Where(x => x.IsEnabled).ToList();
21+
22+
PrintRules(rules);
3223

33-
// Freeze rule values into arrays to prevent concurrent enumeration issues during parallel processing
3424
if (rules != null && rules.Any())
3525
{
36-
foreach (var rule in rules)
37-
{
38-
if (rule.Values != null)
39-
rule.FrozenValues = rule.Values.ToArray();
40-
}
4126
services.AddSingleton(rules);
4227
}
43-
// Bind email configuration from appsettings.json
28+
4429
var emailConfig = new EmailSettings();
4530
context.Configuration.GetSection("EmailSettings").Bind(emailConfig);
4631

@@ -52,13 +37,9 @@ static async Task Main(string[] args)
5237
}
5338

5439
services.AddSingleton(emailConfig);
55-
services.AddSingleton<MailDb>();
5640
services.AddSingleton<IBatchRuleProcessor, BatchRuleProcessor>();
5741
services.AddSingleton<IEmailMover, EmailMover>();
58-
5942
services.AddSingleton<RuleMatcher>();
60-
services.AddSingleton(x => settingHelper);
61-
// Register the background service
6243
services.AddHostedService<EmailMonitoringService>();
6344
})
6445
.ConfigureLogging(logging =>
@@ -74,6 +55,45 @@ static async Task Main(string[] args)
7455

7556
await host.RunAsync();
7657
}
58+
59+
private static void PrintRules(List<Rule>? rules)
60+
{
61+
Console.WriteLine();
62+
Console.WriteLine("=== Rules Configuration ===");
63+
64+
if (rules == null || !rules.Any())
65+
{
66+
Console.WriteLine(" WARNING: No rules loaded!");
67+
Console.WriteLine("===========================");
68+
Console.WriteLine();
69+
return;
70+
}
71+
72+
Console.WriteLine($" Total rules: {rules.Count}");
73+
Console.WriteLine();
74+
75+
for (int i = 0; i < rules.Count; i++)
76+
{
77+
var rule = rules[i];
78+
var action = rule.Action == RuleAction.MarkImportant ? "Flag" : $"Move -> {rule.MoveTo}";
79+
var values = rule.Values != null ? string.Join(", ", rule.Values) : "none";
80+
var filters = new List<string>();
81+
if (rule.DaysOld > 0) filters.Add($"DaysOld>={rule.DaysOld}");
82+
if (rule.RequireUnread == true) filters.Add("UnreadOnly");
83+
if (rule.RequireNotImportant == true) filters.Add("NotImportant");
84+
85+
Console.WriteLine($" [{i + 1}] {rule.Name}");
86+
Console.WriteLine($" {rule.Folder} -> {action}");
87+
Console.WriteLine($" Match: {rule.ExpressionType} in {rule.LookIn}");
88+
Console.WriteLine($" Values: [{values}]");
89+
if (filters.Any())
90+
Console.WriteLine($" Filters: {string.Join(", ", filters)}");
91+
Console.WriteLine();
92+
}
93+
94+
Console.WriteLine("===========================");
95+
Console.WriteLine();
96+
}
7797
}
7898

7999
public class Rule
@@ -88,11 +108,6 @@ public class Rule
88108
public int DaysOld { get; set; }
89109
public List<string>? Values { get; set; }
90110
/// <summary>
91-
/// Thread-safe frozen copy of Values, set at startup for use during parallel processing.
92-
/// </summary>
93-
[System.Text.Json.Serialization.JsonIgnore]
94-
public string[]? FrozenValues { get; set; }
95-
/// <summary>
96111
/// If true, rule only matches unread emails. If false or null, read status is ignored.
97112
/// </summary>
98113
public bool? RequireUnread { get; set; }
@@ -110,8 +125,7 @@ public class EmailSettings
110125
public string? Password { get; set; }
111126
public int Port { get; set; }
112127
public bool UseSsl { get; set; }
113-
public bool StoreMovedMessages { get; set; } = false;
114-
public int BatchProcessingIntervalSeconds { get; set; } = 60; // Default to 60 seconds
128+
public int BatchProcessingIntervalSeconds { get; set; } = 60;
115129
public bool InboxCleanupEnabled { get; set; } = true;
116130
public int InboxCleanupDaysOld { get; set; } = 30;
117131
public string ImportantFolder { get; set; } = "Important";
@@ -174,6 +188,18 @@ public enum RuleAction
174188
MarkImportant
175189
}
176190

191+
public class Email
192+
{
193+
public int MessageIndex { get; set; }
194+
public string? Folder { get; set; }
195+
public string? MoveTo { get; set; }
196+
public string? SenderName { get; set; }
197+
public string? SenderEmailaddress { get; set; }
198+
public DateTimeOffset Date { get; set; }
199+
public string? Subject { get; set; }
200+
public string? Body { get; set; }
201+
}
202+
177203
public class EmailFlagOperation
178204
{
179205
public string SourceFolder { get; set; } = string.Empty;

src/MailZort/Services/BatchRuleProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public List<RuleTrigger> ProcessEmailBatch(List<EmailReceivedEventArgs> emails)
2525

2626
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
2727
var triggers = new List<RuleTrigger>();
28-
var enabledRules = _rules.Where(r => r.IsEnabled && (r.ExpressionType == ExpressionType.AllEmails || (r.FrozenValues ?? r.Values?.ToArray())?.Length > 0)).ToList();
28+
var enabledRules = _rules.Where(r => r.IsEnabled && (r.ExpressionType == ExpressionType.AllEmails || r.Values?.Any() == true)).ToList();
2929

3030
_logger.LogInformation("Processing batch of {EmailCount} emails against {RuleCount} rules",
3131
emails.Count, enabledRules.Count);

src/MailZort/Services/EmailMonitoringService.cs

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
using System.Collections.Concurrent;
2-
using System.Data;
32
using MailKit;
43
using MailKit.Net.Imap;
54
using MailKit.Search;
65
using MailKit.Security;
76
using MimeKit;
8-
using ServiceStack.OrmLite;
97

108
namespace MailZort.Services
119
{
@@ -14,7 +12,6 @@ public class EmailMonitoringService : BackgroundService
1412
{
1513
private readonly ILogger<EmailMonitoringService> _logger;
1614
private readonly EmailSettings _config;
17-
private readonly MailDb _mailDb;
1815
private ImapClient? _client;
1916
private CancellationTokenSource? _idleDoneSource;
2017
private volatile bool _newMessagesFlag = false;
@@ -33,13 +30,11 @@ public class EmailMonitoringService : BackgroundService
3330
public EmailMonitoringService(
3431
ILogger<EmailMonitoringService> logger,
3532
EmailSettings config,
36-
MailDb mailDb,
3733
IEmailMover emailMover,
3834
IBatchRuleProcessor batchRuleProcessor)
3935
{
4036
_logger = logger;
4137
_config = config;
42-
_mailDb = mailDb;
4338
_emailMover = emailMover;
4439
_batchRuleProcessor = batchRuleProcessor;
4540
}
@@ -563,12 +558,6 @@ private async Task ProcessSingleMoveOperationAsync(EmailMoveOperation moveOperat
563558
// Perform the move
564559
await sourceFolder.MoveToAsync(moveOperation.EmailIds, destinationFolder);
565560

566-
// Save to database if enabled
567-
if (_config.StoreMovedMessages)
568-
{
569-
SaveEmailsToDatabase(moveOperation.Emails);
570-
}
571-
572561
_logger.LogInformation("📁 Moved {Count} emails from {Source} to {Destination}",
573562
moveOperation.Emails.Count, moveOperation.SourceFolder, moveOperation.DestinationFolder);
574563
}
@@ -599,22 +588,6 @@ private IMailFolder GetDestinationFolder(string folderName)
599588
return _client!.GetFolder(folderName);
600589
}
601590

602-
private void SaveEmailsToDatabase(List<Email> emails)
603-
{
604-
using var dbConnection = _mailDb.GetConnection();
605-
foreach (var email in emails)
606-
{
607-
try
608-
{
609-
dbConnection.Insert(email);
610-
}
611-
catch (Exception ex)
612-
{
613-
_logger.LogError(ex, "Error saving email {MessageIndex} to database", email.MessageIndex);
614-
}
615-
}
616-
}
617-
618591
private void OnCountChanged(object? sender, EventArgs e)
619592
{
620593
var folder = (IMailFolder)sender!;

src/MailZort/Services/RuleMatcher.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ private bool ProcessMatch(Rule rule, EmailReceivedEventArgs email, string value,
5050

5151
if (passesAge && passesStatus)
5252
{
53-
var ruleValues = string.Join(", ", rule.FrozenValues ?? rule.Values?.ToArray() ?? Array.Empty<string>());
53+
var ruleValues = string.Join(", ", rule.Values ?? new List<string>());
5454
_logger.LogInformation("RULE MATCHED! Rule: {RuleId}, Value: '{Value}', Location: {Location}, Subject: '{Subject}', RuleValues: [{RuleValues}]",
5555
rule.Name, value, matchResult.MatchLocation, email.Subject, ruleValues);
5656
return true;
@@ -78,8 +78,7 @@ public bool CheckRuleMatch(Rule rule, EmailReceivedEventArgs email)
7878
return false;
7979
}
8080
}
81-
var valuesToCheck = rule.FrozenValues ?? rule.Values?.ToArray() ?? Array.Empty<string>();
82-
foreach (var value in valuesToCheck)
81+
foreach (var value in rule.Values!)
8382
{
8483
_logger.LogDebug("Testing value: '{Value}' with expression type: {ExpressionType}", value, rule.ExpressionType);
8584

src/MailZort/SettingsHelper.cs

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/MailZort/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"Trash": "Deleted Messages",
44
"StoreMovedMessages": false
55
},
6-
"rules": [
6+
"Rules": [
77
{
88
"Name": "Shipping",
99
"Folder": "Inbox",

0 commit comments

Comments
 (0)