From a62a0b3dffb0fd6c4b33dda1f556f0afa04059f3 Mon Sep 17 00:00:00 2001 From: Collin Alpert Date: Tue, 4 Apr 2023 09:35:12 +0200 Subject: [PATCH] Add date filter, fixes #5. --- MailSort.csproj | 2 +- MailSortRule.cs | 4 ++-- Program.cs | 31 +++++-------------------------- README.md | 5 +++-- 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/MailSort.csproj b/MailSort.csproj index 8dd18d0..8328c81 100644 --- a/MailSort.csproj +++ b/MailSort.csproj @@ -5,7 +5,7 @@ net6.0 enable Collin Alpert - 1.2.1 + 1.3.0 https://github.com/CollinAlpert/MailSort https://github.com/CollinAlpert/MailSort/blob/master/LICENSE Copyright © 2023 Collin Alpert diff --git a/MailSortRule.cs b/MailSortRule.cs index c577eb8..826d55e 100644 --- a/MailSortRule.cs +++ b/MailSortRule.cs @@ -34,7 +34,7 @@ public class MailSortRule public enum MatchingMethod { - Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase + Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase, GreaterThanOrEqual } public enum CombinationMethod @@ -44,5 +44,5 @@ public enum CombinationMethod public enum Haystack { - Subject, Body, Cc, Bcc, Sender, Recipients, RecipientsAndCc, RecipientsAndBcc, CcAndBcc, RecipientsAndCcAndBcc + Subject, Body, Cc, Bcc, Sender, Recipients, RecipientsAndCc, RecipientsAndBcc, CcAndBcc, RecipientsAndCcAndBcc, Date } \ No newline at end of file diff --git a/Program.cs b/Program.cs index 917c7f2..23a57b9 100644 --- a/Program.cs +++ b/Program.cs @@ -23,9 +23,10 @@ public class Program [MatchingMethod.Contains] = (haystack, needle) => haystack.Contains(needle), [MatchingMethod.Equals] = (haystack, needle) => haystack.Equals(needle), [MatchingMethod.ContainsIgnoreCase] = (haystack, needle) => haystack.Contains(needle, StringComparison.CurrentCultureIgnoreCase), - [MatchingMethod.EqualsIgnoreCase] = (haystack, needle) => haystack.Equals(needle, StringComparison.CurrentCultureIgnoreCase) + [MatchingMethod.EqualsIgnoreCase] = (haystack, needle) => haystack.Equals(needle, StringComparison.CurrentCultureIgnoreCase), + [MatchingMethod.GreaterThanOrEqual] = (haystack, needle) => DateOnly.TryParse(haystack, out var hayStackDate) && DateOnly.TryParse(needle, out var needleDate) && hayStackDate >= needleDate }; - + private static readonly IDictionary> HaystackMapping = new Dictionary> { [Haystack.Subject] = m => m.Subject, @@ -38,6 +39,7 @@ public class Program [Haystack.RecipientsAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.To), GetListHeader(m, message => message.Bcc)), [Haystack.CcAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.Cc), GetListHeader(m, message => message.Bcc)), [Haystack.RecipientsAndCcAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.To), GetListHeader(m, message => message.Cc), GetListHeader(m, message => message.Bcc)), + [Haystack.Date] = m => m.Date.ToString("yyyy-MM-dd") }; private static readonly IDictionary>, Expression>, Expression>>> CombinationMapping = new Dictionary>, Expression>, Expression>>> @@ -102,42 +104,19 @@ private static async Task RunAsync(MailSortConfig config) $"The folder '{tuple.Item2}' was not found. The following folders are available: {string.Join(", ", folders.Select(f => f.FullName))}"); } - await AddMessageToFolderAsync(destinationFolder, message, summary.Flags!.Value, summary.InternalDate!.Value); - - //Make sure inbox is still open. - await inbox.OpenAsync(FolderAccess.ReadWrite); - - await DeleteOriginalMessageAsync(inbox, summary.UniqueId); + await inbox.MoveToAsync(summary.UniqueId, destinationFolder); } await inbox.CloseAsync(true); await imapClient.DisconnectAsync(true); } - private static Task DeleteOriginalMessageAsync(IMailFolder inbox, UniqueId uniqueId) - { - var storeRequest = new StoreFlagsRequest(StoreAction.Add, MessageFlags.Deleted) - { - Silent = true - }; - - return inbox.StoreAsync(uniqueId, storeRequest); - } - private static async Task LoginAsync(IImapClient client, MailSortConfig config) { await client.ConnectAsync(config.Host, config.NoSsl ? ImapPort : EncryptedImapPort, !config.NoSsl); await client.AuthenticateAsync(config.Username, config.Password); } - private static async Task AddMessageToFolderAsync(IMailFolder destinationFolder, MimeMessage message, MessageFlags flags, DateTimeOffset internalDate) - { - await destinationFolder.OpenAsync(FolderAccess.ReadWrite); - var appendRequest = new AppendRequest(message, flags, internalDate); - await destinationFolder.AppendAsync(appendRequest); - await destinationFolder.CloseAsync(); - } - private static Queue GetCombinedRules(MailSortRule rule, Queue foundRules, IReadOnlyList allRules) { if (string.IsNullOrWhiteSpace(rule.CombineWith)) diff --git a/README.md b/README.md index 24d0cc3..e9ee9f2 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,10 @@ The config file is a JSON file where you define your rules. Here's an example: Let's go through the fields.\ `id`: Can be any string and can also be omitted. Only useful when wanting to refer to the rule in another rule. -`haystack`: The part of the email to search through. Possible values: `subject`, `body`, `cc`, `bcc`, `sender`, `recipients`, `recipientsAndCc`, `recipientsAndBcc`, `ccAndBcc`, `recipientsAndCcAndBcc`. When using a haystack which combines two attributes (e.g. recipientsAndCc), they will be chained together using a comma and a following space and then checked against your `needle`. Thus you should probably only use these methods with the `contains` or `containsIgnoreCase` `matchingMethod`. +`haystack`: The part of the email to search through. Possible values: `subject`, `body`, `cc`, `bcc`, `sender`, `recipients`, `recipientsAndCc`, `recipientsAndBcc`, `ccAndBcc`, `recipientsAndCcAndBcc`, `date` (yyyy-MM-dd). When using a haystack which combines two attributes (e.g. recipientsAndCc), they will be chained together using a comma and a following space and then checked against your `needle`. Thus you should probably only use these methods with the `contains` or `containsIgnoreCase` `matchingMethod`.\ +Fields like `sender` are sometimes represented in the typical IMAP format ("Name" ), so you might want to use the `contains` `matchingMethod` with these emails. -`matchingMethod`: The type of check to perform. Should the subject exactly match something, or is it enough if it contains it? Possible values: `contains`, `equals`, `containsIgnoreCase`, `equalsIgnoreCase`. +`matchingMethod`: The type of check to perform. Should the subject exactly match something, or is it enough if it contains it? Possible values: `contains`, `equals`, `containsIgnoreCase`, `equalsIgnoreCase`, `greaterThanOrEqual`. `greaterThanOrEqual` can currently only be used in combination with the needle `date`. `needle`: The phrase to search for in the `haystack`.