Adding a interactive dashboard

This commit is contained in:
2026-03-20 22:13:24 +00:00
parent 911f0ddc04
commit 09d57930cf
2 changed files with 393 additions and 201 deletions
+259 -11
View File
@@ -1,4 +1,4 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using System.IO; using System.IO;
@@ -36,6 +36,10 @@ namespace OutlookCaseHelper
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"OutlookCaseHelper", "hotkeys.json"); "OutlookCaseHelper", "hotkeys.json");
// Singleton para janelas abertas
private DashboardForm? _dashboardForm;
private HotkeySettingsForm? _settingsForm;
public Form1() public Form1()
{ {
InitializeComponent(); InitializeComponent();
@@ -160,6 +164,7 @@ namespace OutlookCaseHelper
trayMenu.Items.Add("Remove Rule (Selected Email)", null, RemoveRuleFromSelected_Click); trayMenu.Items.Add("Remove Rule (Selected Email)", null, RemoveRuleFromSelected_Click);
trayMenu.Items.Add("Remove Rule (Manual ID)", null, RemoveRule_Click); trayMenu.Items.Add("Remove Rule (Manual ID)", null, RemoveRule_Click);
trayMenu.Items.Add("Run All Rules Now", null, RunAllRules_Click); trayMenu.Items.Add("Run All Rules Now", null, RunAllRules_Click);
trayMenu.Items.Add("View Active Rules", null, ViewRules_Click);
trayMenu.Items.Add("-"); trayMenu.Items.Add("-");
trayMenu.Items.Add("Settings", null, Settings_Click); trayMenu.Items.Add("Settings", null, Settings_Click);
trayMenu.Items.Add("Start with Windows", null, ToggleStartup_Click); trayMenu.Items.Add("Start with Windows", null, ToggleStartup_Click);
@@ -203,23 +208,49 @@ namespace OutlookCaseHelper
private void Settings_Click(object? sender, EventArgs e) private void Settings_Click(object? sender, EventArgs e)
{ {
var form = new HotkeySettingsForm( if (_settingsForm != null && !_settingsForm.IsDisposed)
{
_settingsForm.BringToFront();
_settingsForm.WindowState = FormWindowState.Normal;
return;
}
_settingsForm = new HotkeySettingsForm(
hotkeyCreateMod, hotkeyCreateKey, hotkeyCreateMod, hotkeyCreateKey,
hotkeyRemoveMod, hotkeyRemoveKey); hotkeyRemoveMod, hotkeyRemoveKey);
form.Owner = this; _settingsForm.Owner = this;
_settingsForm.FormClosed += (s, args) =>
if (form.ShowDialog() == DialogResult.OK)
{ {
hotkeyCreateMod = form.CreateMod; if (_settingsForm?.DialogResult == DialogResult.OK)
hotkeyCreateKey = form.CreateKey; {
hotkeyRemoveMod = form.RemoveMod; hotkeyCreateMod = _settingsForm.CreateMod;
hotkeyRemoveKey = form.RemoveKey; hotkeyCreateKey = _settingsForm.CreateKey;
hotkeyRemoveMod = _settingsForm.RemoveMod;
hotkeyRemoveKey = _settingsForm.RemoveKey;
SaveHotkeySettings(); SaveHotkeySettings();
RegisterHotkeys(); RegisterHotkeys();
MessageBox.Show( MessageBox.Show(
$"Hotkeys updated!\n\nCreate Rule: {form.CreateDescription}\nRemove Rule: {form.RemoveDescription}", $"Hotkeys updated!\n\nCreate Rule: {_settingsForm.CreateDescription}\nRemove Rule: {_settingsForm.RemoveDescription}",
"Settings", MessageBoxButtons.OK, MessageBoxIcon.Information); "Settings", MessageBoxButtons.OK, MessageBoxIcon.Information);
} }
_settingsForm = null;
};
_settingsForm.Show();
}
private void ViewRules_Click(object? sender, EventArgs e)
{
if (_dashboardForm != null && !_dashboardForm.IsDisposed)
{
_dashboardForm.BringToFront();
_dashboardForm.WindowState = FormWindowState.Normal;
return;
}
_dashboardForm = new DashboardForm(outlookHelper);
_dashboardForm.Owner = this;
_dashboardForm.FormClosed += (s, args) => _dashboardForm = null;
_dashboardForm.Show();
} }
private void InitializeTimer() private void InitializeTimer()
@@ -431,6 +462,223 @@ namespace OutlookCaseHelper
Application.Exit(); Application.Exit();
} }
private class DashboardForm : Form
{
private ListView listView = null!;
private OutlookHelper outlookHelper;
public DashboardForm(OutlookHelper helper)
{
outlookHelper = helper;
this.Text = "Active Rules";
this.Size = new Size(720, 450);
this.MinimumSize = new Size(720, 450);
this.MaximumSize = new Size(720, 450);
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
try { this.Icon = new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "casenew.ico")); } catch { }
listView = new ListView
{
Left = 20,
Top = 20,
Width = 665,
Height = 320,
View = View.Details,
FullRowSelect = true,
GridLines = true,
MultiSelect = false
};
listView.Columns.Add("Folder Name", 380);
listView.Columns.Add("TrackingID", 170);
listView.Columns.Add("Emails", 60);
listView.DoubleClick += (s, e) => BtnRename_Click(null, EventArgs.Empty);
var btnAdd = new Button { Text = "Add Rule", Left = 20, Top = 365, Width = 90 };
var btnRename = new Button { Text = "Rename", Left = 118, Top = 365, Width = 90 };
var btnClose = new Button { Text = "Close Case", Left = 216, Top = 365, Width = 90 };
var btnReload = new Button { Text = "Reload Rules", Left = 314, Top = 365, Width = 100 };
var btnRefresh = new Button { Text = "Refresh", Left = 422, Top = 365, Width = 90 };
var btnDismiss = new Button { Text = "Close", Left = 595, Top = 365, Width = 90 };
btnAdd.Click += BtnAdd_Click;
btnRename.Click += BtnRename_Click;
btnClose.Click += BtnClose_Click;
btnReload.Click += BtnReload_Click;
btnRefresh.Click += (s, e) => LoadRules();
btnDismiss.Click += (s, e) => this.Close();
this.Controls.AddRange(new Control[]
{
listView,
btnAdd, btnRename, btnClose, btnReload, btnRefresh, btnDismiss
});
LoadRules();
}
private void LoadRules()
{
listView.Items.Clear();
var rules = outlookHelper.GetActiveRulesInfo();
if (rules.Count == 0)
{
var empty = new ListViewItem("No active rules found.");
empty.SubItems.Add("");
empty.SubItems.Add("");
listView.Items.Add(empty);
return;
}
foreach (var rule in rules)
{
var item = new ListViewItem(rule.FolderName);
item.SubItems.Add(rule.TrackingId);
item.SubItems.Add(rule.EmailCount.ToString());
item.Tag = rule;
listView.Items.Add(item);
}
}
private void BtnAdd_Click(object? sender, EventArgs e)
{
var ruleForm = new CreateRuleForm("", readonlyId: false);
if (ruleForm.ShowDialog() != DialogResult.OK) return;
string trackingId = ruleForm.TrackingId;
string folderName = ruleForm.FolderName;
if (outlookHelper.FindRuleByTrackingId(trackingId) != null)
{
MessageBox.Show($"Rule for TrackingID#{trackingId} already exists!",
"Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (outlookHelper.ExistsInClosed(trackingId))
{
bool reopened = outlookHelper.ReopenFromClosed(trackingId);
if (reopened)
{
MessageBox.Show($"Case reopened!\n\nTrackingID: {trackingId}",
"Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
LoadRules();
}
else
MessageBox.Show("Error reopening case.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
bool success = outlookHelper.CreateFolderAndMoveEmails(trackingId, folderName);
if (success)
{
MessageBox.Show($"Rule created!\n\nFolder: {folderName}",
"Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
LoadRules();
}
else
MessageBox.Show("Error creating rule. Make sure Outlook is open.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void BtnRename_Click(object? sender, EventArgs e)
{
if (listView.SelectedItems.Count == 0)
{
MessageBox.Show("Please select a rule to rename.", "Warning",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var rule = listView.SelectedItems[0].Tag as OutlookHelper.RuleInfo;
if (rule == null) return;
var inputForm = new Form
{
Text = "Rename Rule",
Size = new Size(420, 160),
MinimumSize = new Size(420, 160),
MaximumSize = new Size(420, 160),
FormBorderStyle = FormBorderStyle.FixedDialog,
MaximizeBox = false,
MinimizeBox = false,
StartPosition = FormStartPosition.CenterScreen
};
try { inputForm.Icon = new Icon(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "casenew.ico")); } catch { }
var lbl = new Label { Text = $"New name for TrackingID#{rule.TrackingId}:", Left = 20, Top = 15, Width = 370, Height = 20 };
var txt = new TextBox { Left = 20, Top = 40, Width = 370, Height = 24, Text = rule.FolderName };
var btnOk = new Button { Text = "Rename", Left = 210, Top = 80, Width = 80, DialogResult = DialogResult.OK };
var btnCancel = new Button { Text = "Cancel", Left = 300, Top = 80, Width = 80, DialogResult = DialogResult.Cancel };
inputForm.Controls.AddRange(new Control[] { lbl, txt, btnOk, btnCancel });
inputForm.AcceptButton = btnOk;
inputForm.CancelButton = btnCancel;
if (inputForm.ShowDialog() != DialogResult.OK) return;
string newName = txt.Text.Trim();
if (string.IsNullOrEmpty(newName) || newName == rule.FolderName) return;
bool success = outlookHelper.RenameRule(rule.FolderName, newName);
if (success)
{
MessageBox.Show($"Rule renamed!\n\n{rule.FolderName} → {newName}",
"Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
LoadRules();
}
else
MessageBox.Show("Error renaming rule.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void BtnClose_Click(object? sender, EventArgs e)
{
if (listView.SelectedItems.Count == 0)
{
MessageBox.Show("Please select a rule to close.", "Warning",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
var rule = listView.SelectedItems[0].Tag as OutlookHelper.RuleInfo;
if (rule == null) return;
var confirm = MessageBox.Show(
$"Are you sure you want to close this case?\n\nFolder: {rule.FolderName}\n\nThe folder will be moved to Inbox > Cases > Closed.",
"Close Case", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (confirm != DialogResult.Yes) return;
bool success = outlookHelper.RemoveRuleAndMoveToClosed(rule.FolderName);
if (success)
{
MessageBox.Show("Case closed!\n\nFolder moved to: Inbox > Cases > Closed.",
"Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
LoadRules();
}
else
MessageBox.Show("Error closing case.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
private void BtnReload_Click(object? sender, EventArgs e)
{
if (this.Owner is Form1 form1)
{
form1.ReloadOutlookRules();
LoadRules();
MessageBox.Show("Rules reloaded successfully!", "Success",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
private class HotkeySettingsForm : Form private class HotkeySettingsForm : Form
{ {
private CheckBox chkCreateAlt, chkCreateCtrl, chkCreateShift; private CheckBox chkCreateAlt, chkCreateCtrl, chkCreateShift;
@@ -480,7 +728,6 @@ namespace OutlookCaseHelper
SelectKey(cmbCreateKey, createKey); SelectKey(cmbCreateKey, createKey);
SelectKey(cmbRemoveKey, removeKey); SelectKey(cmbRemoveKey, removeKey);
// Todos os botões na mesma linha
var btnViewRules = new Button { Text = "View Rules", Left = 20, Top = 200, Width = 90 }; var btnViewRules = new Button { Text = "View Rules", Left = 20, Top = 200, Width = 90 };
btnViewRules.Click += (s, e) => btnViewRules.Click += (s, e) =>
{ {
@@ -525,6 +772,7 @@ namespace OutlookCaseHelper
this.AcceptButton = btnOk; this.AcceptButton = btnOk;
this.CancelButton = btnCancel; this.CancelButton = btnCancel;
} }
private void SelectKey(ComboBox cmb, uint keyCode) private void SelectKey(ComboBox cmb, uint keyCode)
{ {
var key = (Keys)keyCode; var key = (Keys)keyCode;
+126 -182
View File
@@ -26,65 +26,6 @@ namespace OutlookCaseHelper
"active_rules.json"); "active_rules.json");
Directory.CreateDirectory(Path.GetDirectoryName(rulesFilePath)!); Directory.CreateDirectory(Path.GetDirectoryName(rulesFilePath)!);
LoadRules(); LoadRules();
}
public void RunAllRules()
{
if (!EnsureOutlookConnected()) return;
if (activeRules.Count == 0) return;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return;
Outlook.Folder? sentFolder =
outlookNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
Outlook.Folder casesFolder = GetOrCreateFolder(inboxFolder, "Cases");
Outlook.Folder activeFolder = GetOrCreateFolder(casesFolder, "Active");
var rootFolder = inboxFolder.Parent as Outlook.Folder;
var allFolders = new List<Outlook.Folder>();
if (rootFolder != null)
GetAllFolders(rootFolder, allFolders, casesFolder.EntryID);
foreach (var folderName in activeRules)
{
string trackingId = ExtractTrackingId(folderName);
string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'";
Outlook.Folder trackingFolder = GetOrCreateFolder(activeFolder, folderName);
foreach (var folder in allFolders)
{
try { MoveFilteredEmails(folder, filter, trackingFolder); } catch { }
}
}
}
catch { }
}
public void ReloadRules()
{
activeRules.Clear();
LoadRules();
}
private void GetAllFolders(Outlook.Folder parent, List<Outlook.Folder> result, string excludeEntryId)
{
foreach (Outlook.Folder folder in parent.Folders)
{
try
{
if (folder.EntryID == excludeEntryId) continue;
result.Add(folder);
if (folder.Folders.Count > 0)
GetAllFolders(folder, result, excludeEntryId);
}
catch { }
}
} }
private bool EnsureOutlookConnected() private bool EnsureOutlookConnected()
@@ -204,26 +145,6 @@ namespace OutlookCaseHelper
return null; return null;
} }
/*public bool ExistsInClosed(string trackingId)
{
try
{
if (!EnsureOutlookConnected()) return false;
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return false;
Outlook.Folder? casesFolder = GetFolder(inboxFolder, "Cases");
if (casesFolder == null) return false;
Outlook.Folder? closedFolder = GetFolder(casesFolder, "Closed");
if (closedFolder == null) return false;
return GetFolderStartingWith(closedFolder, trackingId) != null;
}
catch { return false; }
}*/
public bool ExistsInClosed(string trackingId) public bool ExistsInClosed(string trackingId)
{ {
try try
@@ -269,6 +190,12 @@ namespace OutlookCaseHelper
catch { } catch { }
} }
public void ReloadRules()
{
activeRules.Clear();
LoadRules();
}
public HashSet<string> GetActiveRules() => activeRules; public HashSet<string> GetActiveRules() => activeRules;
public string? GetSelectedEmailTrackingId() public string? GetSelectedEmailTrackingId()
@@ -294,40 +221,6 @@ namespace OutlookCaseHelper
catch { return null; } catch { return null; }
} }
/* public bool ReopenFromClosed(string trackingId, Outlook.MailItem? triggerEmail = null)
{
if (!EnsureOutlookConnected()) return false;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return false;
Outlook.Folder casesFolder = GetOrCreateFolder(inboxFolder, "Cases");
Outlook.Folder activeFolder = GetOrCreateFolder(casesFolder, "Active");
Outlook.Folder? closedFolder = GetFolder(casesFolder, "Closed");
if (closedFolder == null) return false;
Outlook.Folder? closedTracking = GetFolderStartingWith(closedFolder, trackingId);
if (closedTracking == null) return false;
string existingName = closedTracking.Name;
closedTracking.MoveTo(activeFolder);
if (triggerEmail != null)
{
Outlook.Folder? movedFolder = GetFolder(activeFolder, existingName);
if (movedFolder != null)
triggerEmail.Move(movedFolder);
}
activeRules.Add(existingName);
SaveRules();
return true;
}
catch { return false; }
}*/
public bool ReopenFromClosed(string trackingId, Outlook.MailItem? triggerEmail = null) public bool ReopenFromClosed(string trackingId, Outlook.MailItem? triggerEmail = null)
{ {
if (!EnsureOutlookConnected()) return false; if (!EnsureOutlookConnected()) return false;
@@ -347,7 +240,6 @@ namespace OutlookCaseHelper
string existingName = closedTracking.Name; string existingName = closedTracking.Name;
// Verifica se já existe pasta com mesmo nome em Active
Outlook.Folder? existingActive = GetFolder(activeFolder, existingName); Outlook.Folder? existingActive = GetFolder(activeFolder, existingName);
if (existingActive != null) if (existingActive != null)
{ {
@@ -363,7 +255,6 @@ namespace OutlookCaseHelper
closedTracking.MoveTo(activeFolder); closedTracking.MoveTo(activeFolder);
} }
// Move o email trigger — usa try/catch separado para não falhar o resto
if (triggerEmail != null) if (triggerEmail != null)
{ {
try try
@@ -375,14 +266,12 @@ namespace OutlookCaseHelper
catch { } catch { }
} }
// Adiciona regra — independente do email trigger
activeRules.Add(existingName); activeRules.Add(existingName);
SaveRules(); SaveRules();
return true; return true;
} }
catch (Exception ex) catch
{ {
// Se a pasta já foi movida mas a regra não foi adicionada, tenta recuperar
try try
{ {
Outlook.Folder? inboxFolder = Outlook.Folder? inboxFolder =
@@ -394,7 +283,7 @@ namespace OutlookCaseHelper
{ {
activeRules.Add(movedFolder.Name); activeRules.Add(movedFolder.Name);
SaveRules(); SaveRules();
return true; // pasta estava lá, regra foi adicionada return true;
} }
} }
catch { } catch { }
@@ -402,50 +291,6 @@ namespace OutlookCaseHelper
} }
} }
/* public bool CreateFolderAndMoveEmails(string trackingId, string folderName)
{
if (!EnsureOutlookConnected()) return false;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return false;
Outlook.Folder casesFolder = GetOrCreateFolder(inboxFolder, "Cases");
Outlook.Folder activeFolder = GetOrCreateFolder(casesFolder, "Active");
Outlook.Folder trackingFolder = GetOrCreateFolder(activeFolder, folderName);
string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'";
Outlook.Items restricted = inboxFolder.Items.Restrict(filter);
var toMove = new List<Outlook.MailItem>();
foreach (object item in restricted)
if (item is Outlook.MailItem mail) toMove.Add(mail);
foreach (var mail in toMove)
mail.Move(trackingFolder);
Outlook.Folder? sentFolder =
outlookNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
if (sentFolder != null)
{
Outlook.Items restrictedSent = sentFolder.Items.Restrict(filter);
var toMoveSent = new List<Outlook.MailItem>();
foreach (object item in restrictedSent)
if (item is Outlook.MailItem mail) toMoveSent.Add(mail);
foreach (var mail in toMoveSent)
mail.Move(trackingFolder);
}
activeRules.Add(folderName);
SaveRules();
return true;
}
catch (Exception ex)
{
MessageBox.Show($"Error: {ex.Message}", "Error");
return false;
}
}*/
public bool CreateFolderAndMoveEmails(string trackingId, string folderName) public bool CreateFolderAndMoveEmails(string trackingId, string folderName)
{ {
if (!EnsureOutlookConnected()) return false; if (!EnsureOutlookConnected()) return false;
@@ -461,16 +306,13 @@ namespace OutlookCaseHelper
string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'"; string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'";
// Procura em Inbox
MoveFilteredEmails(inboxFolder, filter, trackingFolder); MoveFilteredEmails(inboxFolder, filter, trackingFolder);
// Procura em Sent
Outlook.Folder? sentFolder = Outlook.Folder? sentFolder =
outlookNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder; outlookNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
if (sentFolder != null) if (sentFolder != null)
MoveFilteredEmails(sentFolder, filter, trackingFolder); MoveFilteredEmails(sentFolder, filter, trackingFolder);
// Procura em todas as outras pastas do utilizador
foreach (Outlook.Folder folder in inboxFolder.Parent.Folders) foreach (Outlook.Folder folder in inboxFolder.Parent.Folders)
{ {
if (folder.Name != "Cases" && if (folder.Name != "Cases" &&
@@ -534,6 +376,82 @@ namespace OutlookCaseHelper
catch { return false; } catch { return false; }
} }
public bool RenameRule(string oldFolderName, string newFolderName)
{
if (!EnsureOutlookConnected()) return false;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return false;
Outlook.Folder? casesFolder = GetFolder(inboxFolder, "Cases");
if (casesFolder == null) return false;
Outlook.Folder? activeFolder = GetFolder(casesFolder, "Active");
if (activeFolder == null) return false;
Outlook.Folder? folder = GetFolder(activeFolder, oldFolderName);
if (folder == null) return false;
folder.Name = newFolderName;
activeRules.Remove(oldFolderName);
activeRules.Add(newFolderName);
SaveRules();
return true;
}
catch { return false; }
}
public void RunAllRules()
{
if (!EnsureOutlookConnected()) return;
if (activeRules.Count == 0) return;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return;
Outlook.Folder casesFolder = GetOrCreateFolder(inboxFolder, "Cases");
Outlook.Folder activeFolder = GetOrCreateFolder(casesFolder, "Active");
var rootFolder = inboxFolder.Parent as Outlook.Folder;
var allFolders = new List<Outlook.Folder>();
if (rootFolder != null)
GetAllFolders(rootFolder, allFolders, casesFolder.EntryID);
foreach (var folderName in activeRules)
{
string trackingId = ExtractTrackingId(folderName);
string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'";
Outlook.Folder trackingFolder = GetOrCreateFolder(activeFolder, folderName);
foreach (var folder in allFolders)
{
try { MoveFilteredEmails(folder, filter, trackingFolder); } catch { }
}
}
}
catch { }
}
private void GetAllFolders(Outlook.Folder parent, List<Outlook.Folder> result, string excludeEntryId)
{
foreach (Outlook.Folder folder in parent.Folders)
{
try
{
if (folder.EntryID == excludeEntryId) continue;
result.Add(folder);
if (folder.Folders.Count > 0)
GetAllFolders(folder, result, excludeEntryId);
}
catch { }
}
}
public void ScanInboxOnStartup() public void ScanInboxOnStartup()
{ {
if (activeRules.Count == 0) return; if (activeRules.Count == 0) return;
@@ -555,30 +473,56 @@ namespace OutlookCaseHelper
{ {
string trackingId = ExtractTrackingId(folderName); string trackingId = ExtractTrackingId(folderName);
string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'"; string filter = $"@SQL=\"urn:schemas:httpmail:subject\" LIKE '%TrackingID#{trackingId}%'";
Outlook.Folder trackingFolder = GetOrCreateFolder(activeFolder, folderName); Outlook.Folder trackingFolder = GetOrCreateFolder(activeFolder, folderName);
Outlook.Items restricted = inboxFolder.Items.Restrict(filter); MoveFilteredEmails(inboxFolder, filter, trackingFolder);
var toMove = new List<Outlook.MailItem>();
foreach (object item in restricted)
if (item is Outlook.MailItem mail) toMove.Add(mail);
foreach (var mail in toMove)
mail.Move(trackingFolder);
if (sentFolder != null) if (sentFolder != null)
{ MoveFilteredEmails(sentFolder, filter, trackingFolder);
Outlook.Items restrictedSent = sentFolder.Items.Restrict(filter);
var toMoveSent = new List<Outlook.MailItem>();
foreach (object item in restrictedSent)
if (item is Outlook.MailItem mail) toMoveSent.Add(mail);
foreach (var mail in toMoveSent)
mail.Move(trackingFolder);
}
} }
} }
catch { } catch { }
} }
public class RuleInfo
{
public string FolderName { get; set; } = "";
public string TrackingId { get; set; } = "";
public int EmailCount { get; set; }
}
public List<RuleInfo> GetActiveRulesInfo()
{
var result = new List<RuleInfo>();
if (!EnsureOutlookConnected()) return result;
try
{
Outlook.Folder? inboxFolder =
outlookNamespace!.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox) as Outlook.Folder;
if (inboxFolder == null) return result;
Outlook.Folder? casesFolder = GetFolder(inboxFolder, "Cases");
if (casesFolder == null) return result;
Outlook.Folder? activeFolder = GetFolder(casesFolder, "Active");
if (activeFolder == null) return result;
foreach (var folderName in activeRules)
{
Outlook.Folder? folder = GetFolder(activeFolder, folderName);
result.Add(new RuleInfo
{
FolderName = folderName,
TrackingId = ExtractTrackingId(folderName),
EmailCount = folder?.Items.Count ?? 0
});
}
}
catch { }
return result;
}
public void ProcessActiveRules() { } public void ProcessActiveRules() { }
private Outlook.Folder GetOrCreateFolder(Outlook.Folder parent, string name) private Outlook.Folder GetOrCreateFolder(Outlook.Folder parent, string name)