feat: add time parameter to MoveToJunk, ReadEmail, and AnalyzeSpam

When multiple emails share the same subject and date, the optional time
parameter disambiguates by finding the closest match to the specified
time (e.g., '13:46', '1:46 PM').

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 13:11:23 -05:00
parent 0bddb21f8c
commit 27fc3b65e9

View File

@@ -80,13 +80,16 @@ public class EmailSearchTools
public static string MoveToJunk(
[Description("Exact or partial subject line to match")] string subject,
[Description("Date of the email (supports: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy)")] string date,
[Description("Outlook folder to search for the email: Inbox, SentMail, Drafts, All, or any custom folder name (default Inbox)")] string folder = "Inbox")
[Description("Outlook folder to search for the email: Inbox, SentMail, Drafts, All, or any custom folder name (default Inbox)")] string folder = "Inbox",
[Description("Optional time to find the closest match when multiple emails share the same subject and date (e.g., '13:46', '1:46 PM')")] string? time = null)
{
try
{
if (!TryParseDate(date, out var targetDate))
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
TimeSpan? targetTime = TryParseTime(time);
using var outlookApp = new OutlookApp();
var ns = outlookApp.GetNamespace("MAPI");
var foldersToSearch = GetFoldersToSearch(ns, folder);
@@ -94,7 +97,7 @@ public class EmailSearchTools
foreach (var mailFolder in foldersToSearch)
{
var mail = FindEmail(mailFolder, subject, targetDate);
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
if (mail != null)
{
var emailSubject = mail.Subject;
@@ -115,20 +118,23 @@ public class EmailSearchTools
public static string ReadEmail(
[Description("Exact or partial subject line to match")] string subject,
[Description("Date of the email (supports: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy)")] string date,
[Description("Outlook folder: Inbox, SentMail, Drafts, DeletedItems, Junk, All, or any custom folder name (default All)")] string folder = "All")
[Description("Outlook folder: Inbox, SentMail, Drafts, DeletedItems, Junk, All, or any custom folder name (default All)")] string folder = "All",
[Description("Optional time to find the closest match when multiple emails share the same subject and date (e.g., '13:46', '1:46 PM')")] string? time = null)
{
try
{
if (!TryParseDate(date, out var targetDate))
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
TimeSpan? targetTime = TryParseTime(time);
using var outlookApp = new OutlookApp();
var ns = outlookApp.GetNamespace("MAPI");
var foldersToSearch = GetFoldersToSearch(ns, folder);
foreach (var mailFolder in foldersToSearch)
{
var mail = FindEmail(mailFolder, subject, targetDate);
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
if (mail != null)
return FormatFullEmail(mail);
}
@@ -145,20 +151,23 @@ public class EmailSearchTools
public static string AnalyzeSpam(
[Description("Exact or partial subject line to match")] string subject,
[Description("Date of the email (supports: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy)")] string date,
[Description("Outlook folder: Inbox, SentMail, Drafts, DeletedItems, Junk, All, or any custom folder name (default All)")] string folder = "All")
[Description("Outlook folder: Inbox, SentMail, Drafts, DeletedItems, Junk, All, or any custom folder name (default All)")] string folder = "All",
[Description("Optional time to find the closest match when multiple emails share the same subject and date (e.g., '13:46', '1:46 PM')")] string? time = null)
{
try
{
if (!TryParseDate(date, out var targetDate))
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
TimeSpan? targetTime = TryParseTime(time);
using var outlookApp = new OutlookApp();
var ns = outlookApp.GetNamespace("MAPI");
var foldersToSearch = GetFoldersToSearch(ns, folder);
foreach (var mailFolder in foldersToSearch)
{
var mail = FindEmail(mailFolder, subject, targetDate);
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
if (mail != null)
{
var detector = new SpamDetector();
@@ -436,7 +445,7 @@ public class EmailSearchTools
}
}
private static MailItem? FindEmail(MAPIFolder folder, string subject, DateTime targetDate)
private static MailItem? FindEmail(MAPIFolder folder, string subject, DateTime targetDate, TimeSpan? targetTime = null)
{
var items = folder.Items;
items.Sort("[ReceivedTime]", true);
@@ -445,6 +454,31 @@ public class EmailSearchTools
var filter = $"[ReceivedTime] >= '{targetDate:MM/dd/yyyy}' AND [ReceivedTime] < '{targetDate.AddDays(1):MM/dd/yyyy}'";
var filteredItems = items.Restrict(filter);
if (targetTime.HasValue)
{
// Find the email closest to the specified time
var targetDateTime = targetDate.Date + targetTime.Value;
MailItem? bestMatch = null;
var bestDiff = TimeSpan.MaxValue;
foreach (var item in filteredItems)
{
if (item is MailItem mail &&
mail.Subject != null &&
mail.Subject.Contains(subject, StringComparison.OrdinalIgnoreCase))
{
var diff = (mail.ReceivedTime - targetDateTime).Duration();
if (diff < bestDiff)
{
bestDiff = diff;
bestMatch = mail;
}
}
}
return bestMatch;
}
foreach (var item in filteredItems)
{
if (item is MailItem mail &&
@@ -664,6 +698,17 @@ public class EmailSearchTools
out result);
}
private static TimeSpan? TryParseTime(string? timeString)
{
if (string.IsNullOrWhiteSpace(timeString))
return null;
if (DateTime.TryParse(timeString, CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out var parsed))
return parsed.TimeOfDay;
return null;
}
private static OlImportance? ParseImportance(string? importance)
{
if (string.IsNullOrEmpty(importance)) return null;