Skip to content

Commit a62a0b3

Browse files
committed
Add date filter, fixes #5.
1 parent 93535cc commit a62a0b3

4 files changed

Lines changed: 11 additions & 31 deletions

File tree

MailSort.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<TargetFramework>net6.0</TargetFramework>
66
<Nullable>enable</Nullable>
77
<Authors>Collin Alpert</Authors>
8-
<Version>1.2.1</Version>
8+
<Version>1.3.0</Version>
99
<RepositoryUrl>https://github.com/CollinAlpert/MailSort</RepositoryUrl>
1010
<PackageLicenseUrl>https://github.com/CollinAlpert/MailSort/blob/master/LICENSE</PackageLicenseUrl>
1111
<Copyright>Copyright © 2023 Collin Alpert</Copyright>

MailSortRule.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class MailSortRule
3434

3535
public enum MatchingMethod
3636
{
37-
Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase
37+
Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase, GreaterThanOrEqual
3838
}
3939

4040
public enum CombinationMethod
@@ -44,5 +44,5 @@ public enum CombinationMethod
4444

4545
public enum Haystack
4646
{
47-
Subject, Body, Cc, Bcc, Sender, Recipients, RecipientsAndCc, RecipientsAndBcc, CcAndBcc, RecipientsAndCcAndBcc
47+
Subject, Body, Cc, Bcc, Sender, Recipients, RecipientsAndCc, RecipientsAndBcc, CcAndBcc, RecipientsAndCcAndBcc, Date
4848
}

Program.cs

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ public class Program
2323
[MatchingMethod.Contains] = (haystack, needle) => haystack.Contains(needle),
2424
[MatchingMethod.Equals] = (haystack, needle) => haystack.Equals(needle),
2525
[MatchingMethod.ContainsIgnoreCase] = (haystack, needle) => haystack.Contains(needle, StringComparison.CurrentCultureIgnoreCase),
26-
[MatchingMethod.EqualsIgnoreCase] = (haystack, needle) => haystack.Equals(needle, StringComparison.CurrentCultureIgnoreCase)
26+
[MatchingMethod.EqualsIgnoreCase] = (haystack, needle) => haystack.Equals(needle, StringComparison.CurrentCultureIgnoreCase),
27+
[MatchingMethod.GreaterThanOrEqual] = (haystack, needle) => DateOnly.TryParse(haystack, out var hayStackDate) && DateOnly.TryParse(needle, out var needleDate) && hayStackDate >= needleDate
2728
};
28-
29+
2930
private static readonly IDictionary<Haystack, Func<MimeMessage, string>> HaystackMapping = new Dictionary<Haystack, Func<MimeMessage, string>>
3031
{
3132
[Haystack.Subject] = m => m.Subject,
@@ -38,6 +39,7 @@ public class Program
3839
[Haystack.RecipientsAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.To), GetListHeader(m, message => message.Bcc)),
3940
[Haystack.CcAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.Cc), GetListHeader(m, message => message.Bcc)),
4041
[Haystack.RecipientsAndCcAndBcc] = m => string.Join(", ", GetListHeader(m, message => message.To), GetListHeader(m, message => message.Cc), GetListHeader(m, message => message.Bcc)),
42+
[Haystack.Date] = m => m.Date.ToString("yyyy-MM-dd")
4143
};
4244

4345
private static readonly IDictionary<CombinationMethod, Func<Expression<Func<MimeMessage, bool>>, Expression<Func<MimeMessage, bool>>, Expression<Func<MimeMessage, bool>>>> CombinationMapping = new Dictionary<CombinationMethod, Func<Expression<Func<MimeMessage, bool>>, Expression<Func<MimeMessage, bool>>, Expression<Func<MimeMessage, bool>>>>
@@ -102,42 +104,19 @@ private static async Task RunAsync(MailSortConfig config)
102104
$"The folder '{tuple.Item2}' was not found. The following folders are available: {string.Join(", ", folders.Select(f => f.FullName))}");
103105
}
104106

105-
await AddMessageToFolderAsync(destinationFolder, message, summary.Flags!.Value, summary.InternalDate!.Value);
106-
107-
//Make sure inbox is still open.
108-
await inbox.OpenAsync(FolderAccess.ReadWrite);
109-
110-
await DeleteOriginalMessageAsync(inbox, summary.UniqueId);
107+
await inbox.MoveToAsync(summary.UniqueId, destinationFolder);
111108
}
112109

113110
await inbox.CloseAsync(true);
114111
await imapClient.DisconnectAsync(true);
115112
}
116113

117-
private static Task DeleteOriginalMessageAsync(IMailFolder inbox, UniqueId uniqueId)
118-
{
119-
var storeRequest = new StoreFlagsRequest(StoreAction.Add, MessageFlags.Deleted)
120-
{
121-
Silent = true
122-
};
123-
124-
return inbox.StoreAsync(uniqueId, storeRequest);
125-
}
126-
127114
private static async Task LoginAsync(IImapClient client, MailSortConfig config)
128115
{
129116
await client.ConnectAsync(config.Host, config.NoSsl ? ImapPort : EncryptedImapPort, !config.NoSsl);
130117
await client.AuthenticateAsync(config.Username, config.Password);
131118
}
132119

133-
private static async Task AddMessageToFolderAsync(IMailFolder destinationFolder, MimeMessage message, MessageFlags flags, DateTimeOffset internalDate)
134-
{
135-
await destinationFolder.OpenAsync(FolderAccess.ReadWrite);
136-
var appendRequest = new AppendRequest(message, flags, internalDate);
137-
await destinationFolder.AppendAsync(appendRequest);
138-
await destinationFolder.CloseAsync();
139-
}
140-
141120
private static Queue<MailSortRule> GetCombinedRules(MailSortRule rule, Queue<MailSortRule> foundRules, IReadOnlyList<MailSortRule> allRules)
142121
{
143122
if (string.IsNullOrWhiteSpace(rule.CombineWith))

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ The config file is a JSON file where you define your rules. Here's an example:
5656
Let's go through the fields.\
5757
`id`: Can be any string and can also be omitted. Only useful when wanting to refer to the rule in another rule.
5858

59-
`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`.
59+
`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`.\
60+
Fields like `sender` are sometimes represented in the typical IMAP format ("Name" <email@example.com>), so you might want to use the `contains` `matchingMethod` with these emails.
6061

61-
`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`.
62+
`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`.
6263

6364
`needle`: The phrase to search for in the `haystack`.
6465

0 commit comments

Comments
 (0)