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:
@@ -80,13 +80,16 @@ public class EmailSearchTools
|
|||||||
public static string MoveToJunk(
|
public static string MoveToJunk(
|
||||||
[Description("Exact or partial subject line to match")] string subject,
|
[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("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
|
try
|
||||||
{
|
{
|
||||||
if (!TryParseDate(date, out var targetDate))
|
if (!TryParseDate(date, out var targetDate))
|
||||||
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
|
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();
|
using var outlookApp = new OutlookApp();
|
||||||
var ns = outlookApp.GetNamespace("MAPI");
|
var ns = outlookApp.GetNamespace("MAPI");
|
||||||
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
||||||
@@ -94,7 +97,7 @@ public class EmailSearchTools
|
|||||||
|
|
||||||
foreach (var mailFolder in foldersToSearch)
|
foreach (var mailFolder in foldersToSearch)
|
||||||
{
|
{
|
||||||
var mail = FindEmail(mailFolder, subject, targetDate);
|
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
|
||||||
if (mail != null)
|
if (mail != null)
|
||||||
{
|
{
|
||||||
var emailSubject = mail.Subject;
|
var emailSubject = mail.Subject;
|
||||||
@@ -115,20 +118,23 @@ public class EmailSearchTools
|
|||||||
public static string ReadEmail(
|
public static string ReadEmail(
|
||||||
[Description("Exact or partial subject line to match")] string subject,
|
[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("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
|
try
|
||||||
{
|
{
|
||||||
if (!TryParseDate(date, out var targetDate))
|
if (!TryParseDate(date, out var targetDate))
|
||||||
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
|
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();
|
using var outlookApp = new OutlookApp();
|
||||||
var ns = outlookApp.GetNamespace("MAPI");
|
var ns = outlookApp.GetNamespace("MAPI");
|
||||||
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
||||||
|
|
||||||
foreach (var mailFolder in foldersToSearch)
|
foreach (var mailFolder in foldersToSearch)
|
||||||
{
|
{
|
||||||
var mail = FindEmail(mailFolder, subject, targetDate);
|
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
|
||||||
if (mail != null)
|
if (mail != null)
|
||||||
return FormatFullEmail(mail);
|
return FormatFullEmail(mail);
|
||||||
}
|
}
|
||||||
@@ -145,20 +151,23 @@ public class EmailSearchTools
|
|||||||
public static string AnalyzeSpam(
|
public static string AnalyzeSpam(
|
||||||
[Description("Exact or partial subject line to match")] string subject,
|
[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("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
|
try
|
||||||
{
|
{
|
||||||
if (!TryParseDate(date, out var targetDate))
|
if (!TryParseDate(date, out var targetDate))
|
||||||
return $"Invalid date format '{date}'. Supported formats: yyyy-MM-dd, MM/dd/yyyy, dd/MM/yyyy";
|
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();
|
using var outlookApp = new OutlookApp();
|
||||||
var ns = outlookApp.GetNamespace("MAPI");
|
var ns = outlookApp.GetNamespace("MAPI");
|
||||||
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
var foldersToSearch = GetFoldersToSearch(ns, folder);
|
||||||
|
|
||||||
foreach (var mailFolder in foldersToSearch)
|
foreach (var mailFolder in foldersToSearch)
|
||||||
{
|
{
|
||||||
var mail = FindEmail(mailFolder, subject, targetDate);
|
var mail = FindEmail(mailFolder, subject, targetDate, targetTime);
|
||||||
if (mail != null)
|
if (mail != null)
|
||||||
{
|
{
|
||||||
var detector = new SpamDetector();
|
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;
|
var items = folder.Items;
|
||||||
items.Sort("[ReceivedTime]", true);
|
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 filter = $"[ReceivedTime] >= '{targetDate:MM/dd/yyyy}' AND [ReceivedTime] < '{targetDate.AddDays(1):MM/dd/yyyy}'";
|
||||||
var filteredItems = items.Restrict(filter);
|
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)
|
foreach (var item in filteredItems)
|
||||||
{
|
{
|
||||||
if (item is MailItem mail &&
|
if (item is MailItem mail &&
|
||||||
@@ -664,6 +698,17 @@ public class EmailSearchTools
|
|||||||
out result);
|
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)
|
private static OlImportance? ParseImportance(string? importance)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(importance)) return null;
|
if (string.IsNullOrEmpty(importance)) return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user