Skip to content

Commit

Permalink
Add date filter, fixes #5.
Browse files Browse the repository at this point in the history
  • Loading branch information
CollinAlpert committed Apr 4, 2023
1 parent 93535cc commit a62a0b3
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 31 deletions.
2 changes: 1 addition & 1 deletion MailSort.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Authors>Collin Alpert</Authors>
<Version>1.2.1</Version>
<Version>1.3.0</Version>
<RepositoryUrl>https://github.com/CollinAlpert/MailSort</RepositoryUrl>
<PackageLicenseUrl>https://github.com/CollinAlpert/MailSort/blob/master/LICENSE</PackageLicenseUrl>
<Copyright>Copyright © 2023 Collin Alpert</Copyright>
Expand Down
4 changes: 2 additions & 2 deletions MailSortRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class MailSortRule

public enum MatchingMethod
{
Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase
Contains, Equals, ContainsIgnoreCase, EqualsIgnoreCase, GreaterThanOrEqual
}

public enum CombinationMethod
Expand All @@ -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
}
31 changes: 5 additions & 26 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Haystack, Func<MimeMessage, string>> HaystackMapping = new Dictionary<Haystack, Func<MimeMessage, string>>
{
[Haystack.Subject] = m => m.Subject,
Expand All @@ -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<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>>>>
Expand Down Expand Up @@ -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<MailSortRule> GetCombinedRules(MailSortRule rule, Queue<MailSortRule> foundRules, IReadOnlyList<MailSortRule> allRules)
{
if (string.IsNullOrWhiteSpace(rule.CombineWith))
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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" <email@example.com>), 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`.

Expand Down

0 comments on commit a62a0b3

Please sign in to comment.