diff --git a/OutlookDSD/Helper.cs b/OutlookDSD/Helper.cs new file mode 100644 index 0000000..e756fed --- /dev/null +++ b/OutlookDSD/Helper.cs @@ -0,0 +1,41 @@ +using Microsoft.Office.Interop.Outlook; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace OutlookDSD +{ + public static class Helper + { + const string HEADER_TRANSPORT_SCHEMA = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"; + const string HEADER_REGEX_PATTERN = @"^(?[-A-Za-z0-9]+)(?:[ \t]*)(?([^\r\n]|\r\n[ \t]+)*)(?\r\n)"; + + public static ILookup Email_GetHeaders(MailItem emailItem) + { + var headerString = (string)emailItem.PropertyAccessor.GetProperty(HEADER_TRANSPORT_SCHEMA); + var headerMatches = Regex.Matches(headerString, HEADER_REGEX_PATTERN, RegexOptions.Multiline).Cast(); + return headerMatches.ToLookup( + h => h.Groups["header_key"].Value, + h => h.Groups["header_value"].Value + ); + } + + public static string ListToSentence(List list) + { + if (list.Count == 0) + { + return String.Empty; + } + else if (list.Count > 1) + { + return String.Join(", ", list.ToArray(), 0, list.Count - 1) + ", and " + list.LastOrDefault(); + } + else + { + return list.First(); + } + + } + } +} diff --git a/OutlookDSD/InfoBar.Designer.cs b/OutlookDSD/InfoBar.Designer.cs new file mode 100644 index 0000000..06ba23b --- /dev/null +++ b/OutlookDSD/InfoBar.Designer.cs @@ -0,0 +1,163 @@ +namespace OutlookDSD +{ + [System.ComponentModel.ToolboxItemAttribute(false)] + partial class InfoBar : Microsoft.Office.Tools.Outlook.FormRegionBase + { + public InfoBar(Microsoft.Office.Interop.Outlook.FormRegion formRegion) + : base(Globals.Factory, formRegion) + { + InitializeComponent(); + } + + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Form Region Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private static void InitializeManifest(Microsoft.Office.Tools.Outlook.FormRegionManifest manifest, Microsoft.Office.Tools.Outlook.Factory factory) + { + manifest.FormRegionType = Microsoft.Office.Tools.Outlook.FormRegionType.Adjoining; + manifest.Title = "Email Validation by OutlookDSD"; + } + + #endregion + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.messageLabel = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // messageLabel + // + this.messageLabel.AutoSize = true; + this.messageLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.messageLabel.ForeColor = System.Drawing.Color.Red; + this.messageLabel.Location = new System.Drawing.Point(3, 0); + this.messageLabel.Name = "messageLabel"; + this.messageLabel.Size = new System.Drawing.Size(428, 18); + this.messageLabel.TabIndex = 0; + this.messageLabel.Text = "This email has failed DKIM, SPF and DMARC validation."; + // + // InfoBar + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; + this.Controls.Add(this.messageLabel); + this.Name = "InfoBar"; + this.Size = new System.Drawing.Size(1080, 25); + this.FormRegionShowing += new System.EventHandler(this.InfoBar_FormRegionShowing); + this.FormRegionClosed += new System.EventHandler(this.InfoBar_FormRegionClosed); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label messageLabel; + + public partial class InfoBarFactory : Microsoft.Office.Tools.Outlook.IFormRegionFactory + { + public event Microsoft.Office.Tools.Outlook.FormRegionInitializingEventHandler FormRegionInitializing; + + private Microsoft.Office.Tools.Outlook.FormRegionManifest _Manifest; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public InfoBarFactory() + { + this._Manifest = Globals.Factory.CreateFormRegionManifest(); + InfoBar.InitializeManifest(this._Manifest, Globals.Factory); + this.FormRegionInitializing += new Microsoft.Office.Tools.Outlook.FormRegionInitializingEventHandler(this.InfoBarFactory_FormRegionInitializing); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public Microsoft.Office.Tools.Outlook.FormRegionManifest Manifest + { + get + { + return this._Manifest; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + Microsoft.Office.Tools.Outlook.IFormRegion Microsoft.Office.Tools.Outlook.IFormRegionFactory.CreateFormRegion(Microsoft.Office.Interop.Outlook.FormRegion formRegion) + { + InfoBar form = new InfoBar(formRegion); + form.Factory = this; + return form; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + byte[] Microsoft.Office.Tools.Outlook.IFormRegionFactory.GetFormRegionStorage(object outlookItem, Microsoft.Office.Interop.Outlook.OlFormRegionMode formRegionMode, Microsoft.Office.Interop.Outlook.OlFormRegionSize formRegionSize) + { + throw new System.NotSupportedException(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + bool Microsoft.Office.Tools.Outlook.IFormRegionFactory.IsDisplayedForItem(object outlookItem, Microsoft.Office.Interop.Outlook.OlFormRegionMode formRegionMode, Microsoft.Office.Interop.Outlook.OlFormRegionSize formRegionSize) + { + if (this.FormRegionInitializing != null) + { + Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs cancelArgs = Globals.Factory.CreateFormRegionInitializingEventArgs(outlookItem, formRegionMode, formRegionSize, false); + this.FormRegionInitializing(this, cancelArgs); + return !cancelArgs.Cancel; + } + else + { + return true; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + Microsoft.Office.Tools.Outlook.FormRegionKindConstants Microsoft.Office.Tools.Outlook.IFormRegionFactory.Kind + { + get + { + return Microsoft.Office.Tools.Outlook.FormRegionKindConstants.WindowsForms; + } + } + } + } + + partial class WindowFormRegionCollection + { + internal InfoBar InfoBar + { + get + { + foreach (var item in this) + { + if (item.GetType() == typeof(InfoBar)) + return (InfoBar)item; + } + return null; + } + } + } +} diff --git a/OutlookDSD/InfoBar.cs b/OutlookDSD/InfoBar.cs new file mode 100644 index 0000000..eb2a6f3 --- /dev/null +++ b/OutlookDSD/InfoBar.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using Outlook = Microsoft.Office.Interop.Outlook; + +namespace OutlookDSD +{ + partial class InfoBar + { + #region Form Region Factory + + [Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Note)] + [Microsoft.Office.Tools.Outlook.FormRegionName("OutlookDSD.InfoBar")] + public partial class InfoBarFactory + { + + // Occurs before the form region is initialized. + // To prevent the form region from appearing, set e.Cancel to true. + // Use e.OutlookItem to get a reference to the current Outlook item. + private void InfoBarFactory_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e) + { + Outlook.MailItem emailItem = (Outlook.MailItem)e.OutlookItem; + + if (emailItem == null) + { + e.Cancel = true; + return; + } + } + } + + #endregion + + private void InfoBar_FormRegionShowing(object sender, System.EventArgs e) + { + Outlook.MailItem emailItem = (Outlook.MailItem) OutlookItem; + + if (emailItem == null) + { + OutlookFormRegion.Visible = false; + return; + } + + // Only show on emails. + if (emailItem.MessageClass != "IPM.Note") + { + OutlookFormRegion.Visible = false; + return; + } + + // Don't show for any draft emails. + if(emailItem.Sent == false) + { + OutlookFormRegion.Visible = false; + return; + } + + // Now we check our settings to see if the user wants the bar to show + string settingCheck = "bar_show"; + bool showBar = (bool) Properties.Settings.Default[settingCheck]; + if (showBar == false) + { + OutlookFormRegion.Visible = false; + return; + } + + // We don't need to worry about multiple messages being selected in explorer mode + // because Outlook only displays one anyway. + + Validator validator = new Validator(emailItem); + Dictionary results = validator.Results(); + + List failed = new List(); + List missing = new List(); + List error = new List(); + List pass = new List(); + + // Iterate through each mechanism in result and add them to the appropriate list based on their result + foreach (string mechanism in results.Keys) + { + string mechanismResult = results[mechanism][0]; + string mechanismUpper = mechanism.ToUpper(); + switch (mechanismResult) + { + case Validator.RESULT_PASS: + pass.Add(mechanismUpper); + break; + case Validator.RESULT_FAIL: + failed.Add(mechanismUpper); + break; + case Validator.RESULT_NONE: + missing.Add(mechanismUpper); + break; + default: + case Validator.RESULT_ERROR: + error.Add(mechanismUpper); + break; + + } + } + + int badMechanismsCount = error.Count + failed.Count + missing.Count; + + // If all mechnaisms are good then don't display anything. + if (badMechanismsCount == 0) + { + OutlookFormRegion.Visible = false; + return; + } + + // Otherwise we're going to show the warning bar + OutlookFormRegion.Visible = true; + + + List messages = new List(); + if(failed.Count > 0) + { + messages.Add("This email has failed " + Helper.ListToSentence(failed) + " validation."); + } + if (missing.Count > 0) + { + messages.Add("This email is missing " + Helper.ListToSentence(missing) + " validation."); + } + if(error.Count > 0) + { + messages.Add("There was an error analysing " + Helper.ListToSentence(error) + " validation."); + } + messageLabel.Text = String.Join(" ", messages.ToArray()); + } + + // Occurs when the form region is closed. + // Use this.OutlookItem to get a reference to the current Outlook item. + // Use this.OutlookFormRegion to get a reference to the form region. + private void InfoBar_FormRegionClosed(object sender, System.EventArgs e) + { + } + + } +} diff --git a/OutlookDSD/InfoBar.resx b/OutlookDSD/InfoBar.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/OutlookDSD/InfoBar.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/OutlookDSD/OptionsPage.Designer.cs b/OutlookDSD/OptionsPage.Designer.cs new file mode 100644 index 0000000..8b72c97 --- /dev/null +++ b/OutlookDSD/OptionsPage.Designer.cs @@ -0,0 +1,234 @@ +using System.Runtime.InteropServices; + +namespace OutlookDSD +{ + partial class OptionsPage: System.Windows.Forms.UserControl, Microsoft.Office.Interop.Outlook.PropertyPage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label1 = new System.Windows.Forms.Label(); + this.checkBox_ribbon_showOnExplorer = new System.Windows.Forms.CheckBox(); + this.checkBox_ribbon_showOnEmail = new System.Windows.Forms.CheckBox(); + this.checkBox_bar_show = new System.Windows.Forms.CheckBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.lbl_VersionInstalled = new System.Windows.Forms.Label(); + this.lbl_VersionAvaliable = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.btn_Update = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.btn_Help = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; + this.pictureBox1.Image = global::OutlookDSD.Properties.Resources.logo; + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(215, 103); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(3, 116); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(108, 13); + this.label1.TabIndex = 2; + this.label1.Text = "Validation Display"; + // + // checkBox_ribbon_showOnExplorer + // + this.checkBox_ribbon_showOnExplorer.AutoSize = true; + this.checkBox_ribbon_showOnExplorer.Location = new System.Drawing.Point(9, 134); + this.checkBox_ribbon_showOnExplorer.Name = "checkBox_ribbon_showOnExplorer"; + this.checkBox_ribbon_showOnExplorer.Size = new System.Drawing.Size(206, 17); + this.checkBox_ribbon_showOnExplorer.TabIndex = 3; + this.checkBox_ribbon_showOnExplorer.Text = "Show Validation on Ribbon in Explorer"; + this.checkBox_ribbon_showOnExplorer.UseVisualStyleBackColor = true; + this.checkBox_ribbon_showOnExplorer.CheckedChanged += new System.EventHandler(this.SettingChanged); + // + // checkBox_ribbon_showOnEmail + // + this.checkBox_ribbon_showOnEmail.AutoSize = true; + this.checkBox_ribbon_showOnEmail.Location = new System.Drawing.Point(9, 157); + this.checkBox_ribbon_showOnEmail.Name = "checkBox_ribbon_showOnEmail"; + this.checkBox_ribbon_showOnEmail.Size = new System.Drawing.Size(267, 17); + this.checkBox_ribbon_showOnEmail.TabIndex = 4; + this.checkBox_ribbon_showOnEmail.Text = "Show Validation on Ribbon in Message/Email View"; + this.checkBox_ribbon_showOnEmail.UseVisualStyleBackColor = true; + this.checkBox_ribbon_showOnEmail.CheckedChanged += new System.EventHandler(this.SettingChanged); + // + // checkBox_bar_show + // + this.checkBox_bar_show.AutoSize = true; + this.checkBox_bar_show.Location = new System.Drawing.Point(9, 180); + this.checkBox_bar_show.Name = "checkBox_bar_show"; + this.checkBox_bar_show.Size = new System.Drawing.Size(121, 17); + this.checkBox_bar_show.TabIndex = 5; + this.checkBox_bar_show.Text = "Show Validation Bar"; + this.checkBox_bar_show.UseVisualStyleBackColor = true; + this.checkBox_bar_show.CheckedChanged += new System.EventHandler(this.SettingChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(221, 3); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(110, 13); + this.label2.TabIndex = 6; + this.label2.Text = "Add-in Information"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(224, 20); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(87, 13); + this.label3.TabIndex = 7; + this.label3.Text = "Installed Version:"; + // + // lbl_VersionInstalled + // + this.lbl_VersionInstalled.AutoSize = true; + this.lbl_VersionInstalled.Location = new System.Drawing.Point(321, 20); + this.lbl_VersionInstalled.Name = "lbl_VersionInstalled"; + this.lbl_VersionInstalled.Size = new System.Drawing.Size(40, 13); + this.lbl_VersionInstalled.TabIndex = 8; + this.lbl_VersionInstalled.Text = "1.1.1.1"; + // + // lbl_VersionAvaliable + // + this.lbl_VersionAvaliable.AutoSize = true; + this.lbl_VersionAvaliable.Location = new System.Drawing.Point(321, 36); + this.lbl_VersionAvaliable.Name = "lbl_VersionAvaliable"; + this.lbl_VersionAvaliable.Size = new System.Drawing.Size(40, 13); + this.lbl_VersionAvaliable.TabIndex = 10; + this.lbl_VersionAvaliable.Text = "1.1.1.1"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(224, 36); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(77, 13); + this.label5.TabIndex = 9; + this.label5.Text = "Latest Version:"; + // + // btn_Update + // + this.btn_Update.Location = new System.Drawing.Point(224, 57); + this.btn_Update.Name = "btn_Update"; + this.btn_Update.Size = new System.Drawing.Size(90, 29); + this.btn_Update.TabIndex = 11; + this.btn_Update.Text = "Update Add-in"; + this.btn_Update.UseVisualStyleBackColor = true; + this.btn_Update.Visible = false; + this.btn_Update.Click += new System.EventHandler(this.btn_Update_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.ForeColor = System.Drawing.SystemColors.ButtonShadow; + this.label4.Location = new System.Drawing.Point(247, 94); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(170, 13); + this.label4.TabIndex = 12; + this.label4.Text = "Copyright (C) 2023 Matthew Hana."; + // + // label6 + // + this.label6.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.label6.Location = new System.Drawing.Point(0, 110); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(450, 2); + this.label6.TabIndex = 13; + this.label6.Text = "XX"; + this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // btn_Help + // + this.btn_Help.Location = new System.Drawing.Point(320, 57); + this.btn_Help.Name = "btn_Help"; + this.btn_Help.Size = new System.Drawing.Size(90, 29); + this.btn_Help.TabIndex = 14; + this.btn_Help.Text = "Help"; + this.btn_Help.UseVisualStyleBackColor = true; + this.btn_Help.Click += new System.EventHandler(this.btn_Help_Click); + // + // OptionsPage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.btn_Help); + this.Controls.Add(this.label6); + this.Controls.Add(this.label4); + this.Controls.Add(this.btn_Update); + this.Controls.Add(this.lbl_VersionAvaliable); + this.Controls.Add(this.label5); + this.Controls.Add(this.lbl_VersionInstalled); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.checkBox_bar_show); + this.Controls.Add(this.checkBox_ribbon_showOnEmail); + this.Controls.Add(this.checkBox_ribbon_showOnExplorer); + this.Controls.Add(this.label1); + this.Controls.Add(this.pictureBox1); + this.Name = "OptionsPage"; + this.Size = new System.Drawing.Size(420, 420); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.CheckBox checkBox_ribbon_showOnExplorer; + private System.Windows.Forms.CheckBox checkBox_ribbon_showOnEmail; + private System.Windows.Forms.CheckBox checkBox_bar_show; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label lbl_VersionInstalled; + private System.Windows.Forms.Label lbl_VersionAvaliable; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Button btn_Update; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button btn_Help; + } +} \ No newline at end of file diff --git a/OutlookDSD/OptionsPage.cs b/OutlookDSD/OptionsPage.cs new file mode 100644 index 0000000..c0345d1 --- /dev/null +++ b/OutlookDSD/OptionsPage.cs @@ -0,0 +1,256 @@ +using System; +using System.ComponentModel; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Microsoft.Office.Interop.Outlook; + +namespace OutlookDSD +{ + [ComVisible(true)] + public partial class OptionsPage : UserControl, PropertyPage + { + bool isDirty = false; + bool SettingsLoaded = false; + readonly BackgroundWorker UpdateCheckerBGWorker = new BackgroundWorker(); + string CurrentInstalledVersion = ""; + + public OptionsPage() + { + // Create Form components + InitializeComponent(); + // Suspend UI as we make changes + SuspendLayout(); + // Load the version and check for updates + Version_Load(); + // Load settings + Settings_Load(); + //Resume UI + ResumeLayout(false); + } + + private void Settings_Load() + { + + // Load each setting + checkBox_ribbon_showOnEmail.Checked = Properties.Settings.Default.ribbon_showOnEmail; + checkBox_ribbon_showOnExplorer.Checked = Properties.Settings.Default.ribbon_showOnExplorer; + checkBox_bar_show.Checked = Properties.Settings.Default.bar_show; + // Mark settings as loaded so that Change event will work + SettingsLoaded = true; + } + + private void Settings_Save() + { + Properties.Settings.Default.ribbon_showOnEmail = checkBox_ribbon_showOnEmail.Checked; + Properties.Settings.Default.ribbon_showOnExplorer = checkBox_ribbon_showOnExplorer.Checked; + Properties.Settings.Default.bar_show = checkBox_bar_show.Checked; + + Properties.Settings.Default.Save(); + } + + [DispId(-518)] + public string Caption + { + get { return "OutlookDSD"; } + } + + public void GetPageInfo(ref string HelpFile, ref int HelpContext) + { + return; + } + + public void Apply() + { + // Cancel the UpdateChcker if we're closing the dialog + if (UpdateCheckerBGWorker.IsBusy) + { + UpdateCheckerBGWorker.CancelAsync(); + } + + // If no changes have been made then just continue + if (!isDirty) + { + return; + } + // Otherwise save the settings + Settings_Save(); + MessageBox.Show("You may need to restart Oulook for your settings to take effect."); + + // Set isDirty back to false so that any other changes work accordingly + isDirty = false; + } + + public bool Dirty + { + get { return isDirty; } + set { } + } + + private void SettingChanged(object sender, EventArgs e) + { + // If we haven't finished loading the settings yet then just do nothing + if (!SettingsLoaded) + { + return; + } + + // If we've already made a change then don't continue any further. + // This is to prevent GetPropertyPageSite() from being called over and over, + // as it uses Reflection and can impact performance. + if (isDirty) + { + return; + } + + // User has toggled a setting change. Set the dirty flag + isDirty = true; + + // Wrap it in a try because there is no gurantee that we are getting the PropertyPageSite + try + { + // and let the parent page know so that it can activate the Apply button + GetPropertyPageSite().OnStatusChange(); + }catch (System.Exception) + { + + } + } + + // Thanks to KyleMit at https://stackoverflow.com/a/21125886 + private PropertyPageSite GetPropertyPageSite() + { + Type objType = typeof(System.Object); + string assemblyPath = objType.Assembly.CodeBase.Replace("mscorlib.dll", "System.Windows.Forms.dll").Replace("file:///", ""); + string assemblyName = System.Reflection.AssemblyName.GetAssemblyName(assemblyPath).FullName; + + Type unsafeNativeMethods = Type.GetType(System.Reflection.Assembly.CreateQualifiedName(assemblyName, "System.Windows.Forms.UnsafeNativeMethods")); + Type oleObjectType = unsafeNativeMethods.GetNestedType("IOleObject"); + + System.Reflection.MethodInfo methodInfo = oleObjectType.GetMethod("GetClientSite"); + Object propertyPageSite = methodInfo.Invoke(this, null); + + return (PropertyPageSite) propertyPageSite; + } + +#pragma warning disable IDE1006 // Naming Styles + private void btn_Update_Click(object sender, EventArgs e) +#pragma warning restore IDE1006 // Naming Styles + { + // Open a URL to the GitHub page + string url = "https://github.com/MatthewHana/OutlookDSD"; + Web_GoTo(url); + } + +#pragma warning disable IDE1006 // Naming Styles + private void btn_Help_Click(object sender, EventArgs e) +#pragma warning restore IDE1006 // Naming Styles + { + // Open a URL to the GitHub page + string url = "https://github.com/MatthewHana/OutlookDSD"; + Web_GoTo(url); + } + + private void Web_GoTo(string url) + { + System.Diagnostics.Process.Start(url); + } + private void Version_Load() + { + // List the current version + System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); + System.Diagnostics.FileVersionInfo versionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); + CurrentInstalledVersion = versionInfo.ProductVersion.ToString(); + lbl_VersionInstalled.Text = CurrentInstalledVersion; + + // Start the UpdateChecker background + UpdateCheckerBGWorker.WorkerReportsProgress = true; + UpdateCheckerBGWorker.DoWork += new DoWorkEventHandler(Version_CheckForUpdate); + UpdateCheckerBGWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Version_UpdateAvaliable); + UpdateCheckerBGWorker.RunWorkerAsync(); + } + + private void Version_UpdateAvaliable(object sender, RunWorkerCompletedEventArgs e) + { + // If there was an error, stop + if(e.Error != null) + { + lbl_VersionAvaliable.Text = "Error"; + return; + } + string LatestVersion = (string) e.Result; + + // Make sure the versions string obtained is a valid one + string validRegex = @"^(\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1,2})$"; + bool ValidVersion = Regex.IsMatch(LatestVersion, validRegex); + if (!ValidVersion) + { + lbl_VersionAvaliable.Text = "Error"; + return; + } + + lbl_VersionAvaliable.Text = LatestVersion; + + //Compare versions to see if there is an update + var InstalledVerionObj = new Version(CurrentInstalledVersion); + var LatestVerionObj = new Version(LatestVersion); + bool UpdateAvaliable = InstalledVerionObj.CompareTo(LatestVerionObj) < 0; + + // If there's no update, stop here + if (UpdateAvaliable == false) + { + return; + } + + // Otherwise make UI changes + btn_Update.Visible = true; + lbl_VersionAvaliable.ForeColor = System.Drawing.Color.Red; + lbl_VersionAvaliable.Font = new System.Drawing.Font(lbl_VersionAvaliable.Font, System.Drawing.FontStyle.Bold); + } + + private void Version_CheckForUpdate(object sender, DoWorkEventArgs e) + { + //Set URL to check for updates + string updateCheckURL = "https://raw.githubusercontent.com/MatthewHana/OutlookDSD/main/LATEST"; + + //Enable HTTPS + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + HttpWebRequest request = WebRequest.Create(updateCheckURL) as HttpWebRequest; + request.Accept = "text/plain"; + request.UserAgent = Web_GetUA(); + + // Get the response. We don't need to catch anything because we check for errors in our RunWorkerCompleted event callback + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + var encoding = ASCIIEncoding.ASCII; + string responseText; + using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding)) + { + responseText = reader.ReadToEnd(); + } + e.Result = responseText; + } + + private string Web_GetUA() + { + string UA = "Mozilla/5.0 (Windows NT "; + + UA += System.Environment.OSVersion.Version.Major + "." + System.Environment.OSVersion.Version.Minor + ";"; + if (System.Environment.Is64BitOperatingSystem) + { + UA += " Win64; "; + } + else + { + UA += " Win32; "; + } + + UA += System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLower() + ") "; + UA += "OutlookDSD/" + CurrentInstalledVersion; + + return UA; + } + } +} diff --git a/OutlookDSD/OptionsPage.resx b/OutlookDSD/OptionsPage.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/OutlookDSD/OptionsPage.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/OutlookDSD/OutlookDSD.csproj b/OutlookDSD/OutlookDSD.csproj new file mode 100644 index 0000000..1779731 --- /dev/null +++ b/OutlookDSD/OutlookDSD.csproj @@ -0,0 +1,300 @@ + + + + + {BAA0C2D2-18E2-41B9-852F-F413020CAA33};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + AnyCPU + {77F8E6A3-2276-44B2-8F1B-689F165D4FA9} + Library + false + OutlookDSD + OutlookDSD + v4.7.2 + VSTO40 + False + true + publish\ + + en + 1.0.1.6 + true + true + 7 + days + OutlookDSD + Matthew Hana + https://github.com/MatthewHana/OutlookDSD + OutlookDSD + A simple add-in for Outlook that shows a messages DKIM, SPF and DMARC status. + 3 + + + + False + Microsoft .NET Framework 4.7.2 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Microsoft Visual Studio 2010 Tools for Office Runtime %28x86 and x64%29 + true + + + + + Outlook + + + + true + full + false + bin\Debug\ + false + $(DefineConstants);DEBUG;TRACE + 4 + + + + pdbonly + true + bin\Release\ + false + $(DefineConstants);TRACE + 4 + + + + + + + + + + + + + + + + + False + + + False + + + False + + + False + + + False + + + + + True + + + True + + + + + False + true + + + False + true + + + False + + + + + + + UserControl + + + InfoBar.cs + + + UserControl + + + OptionsPage.cs + + + Code + + + true + + + + InfoBar.cs + + + OptionsPage.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + Code + + + ThisAddIn.cs + + + ThisAddIn.Designer.xml + + + + + + + + + + + + + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + true + + + OutlookDSD_TemporaryKey.pfx + + + 58DCF1A36BF694DAE8A86968B27B436C6F196537 + + + icon.ico + + + false + + + OutlookDSD_TemporaryKey.pfx + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OutlookDSD/Properties/AssemblyInfo.cs b/OutlookDSD/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7481648 --- /dev/null +++ b/OutlookDSD/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OutlookDSD")] +[assembly: AssemblyDescription("A simple add-in for Outlook that shows a messages DKIM, SPF and DMARC status.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Matthew Hana")] +[assembly: AssemblyProduct("OutlookDSD")] +[assembly: AssemblyCopyright("Copyright © 2023, Matthew Hana.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("26ba9089-ab9d-44b1-99cb-a96cbd91bf45")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] + diff --git a/OutlookDSD/Properties/Resources.Designer.cs b/OutlookDSD/Properties/Resources.Designer.cs new file mode 100644 index 0000000..6d910f5 --- /dev/null +++ b/OutlookDSD/Properties/Resources.Designer.cs @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OutlookDSD.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OutlookDSD.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap disabled { + get { + object obj = ResourceManager.GetObject("disabled", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap error { + get { + object obj = ResourceManager.GetObject("error", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap fail { + get { + object obj = ResourceManager.GetObject("fail", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icon { + get { + object obj = ResourceManager.GetObject("icon", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap logo { + get { + object obj = ResourceManager.GetObject("logo", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap none { + get { + object obj = ResourceManager.GetObject("none", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap pass { + get { + object obj = ResourceManager.GetObject("pass", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/OutlookDSD/Properties/Resources.resx b/OutlookDSD/Properties/Resources.resx new file mode 100644 index 0000000..218f4af --- /dev/null +++ b/OutlookDSD/Properties/Resources.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\none.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\pass.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\fail.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\disabled.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/OutlookDSD/Properties/Settings.Designer.cs b/OutlookDSD/Properties/Settings.Designer.cs new file mode 100644 index 0000000..49e692b --- /dev/null +++ b/OutlookDSD/Properties/Settings.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OutlookDSD.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ribbon_showOnExplorer { + get { + return ((bool)(this["ribbon_showOnExplorer"])); + } + set { + this["ribbon_showOnExplorer"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ribbon_showOnEmail { + get { + return ((bool)(this["ribbon_showOnEmail"])); + } + set { + this["ribbon_showOnEmail"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool bar_show { + get { + return ((bool)(this["bar_show"])); + } + set { + this["bar_show"] = value; + } + } + } +} diff --git a/OutlookDSD/Properties/Settings.settings b/OutlookDSD/Properties/Settings.settings new file mode 100644 index 0000000..794f504 --- /dev/null +++ b/OutlookDSD/Properties/Settings.settings @@ -0,0 +1,15 @@ + + + + + + True + + + True + + + True + + + \ No newline at end of file diff --git a/OutlookDSD/Resources/disabled.png b/OutlookDSD/Resources/disabled.png new file mode 100644 index 0000000..7f802ab Binary files /dev/null and b/OutlookDSD/Resources/disabled.png differ diff --git a/OutlookDSD/Resources/error.png b/OutlookDSD/Resources/error.png new file mode 100644 index 0000000..8fc18da Binary files /dev/null and b/OutlookDSD/Resources/error.png differ diff --git a/OutlookDSD/Resources/fail.png b/OutlookDSD/Resources/fail.png new file mode 100644 index 0000000..5953c84 Binary files /dev/null and b/OutlookDSD/Resources/fail.png differ diff --git a/OutlookDSD/Resources/icon.png b/OutlookDSD/Resources/icon.png new file mode 100644 index 0000000..b0ae856 Binary files /dev/null and b/OutlookDSD/Resources/icon.png differ diff --git a/OutlookDSD/Resources/logo.png b/OutlookDSD/Resources/logo.png new file mode 100644 index 0000000..ac6eaab Binary files /dev/null and b/OutlookDSD/Resources/logo.png differ diff --git a/OutlookDSD/Resources/none.png b/OutlookDSD/Resources/none.png new file mode 100644 index 0000000..a12507f Binary files /dev/null and b/OutlookDSD/Resources/none.png differ diff --git a/OutlookDSD/Resources/pass.png b/OutlookDSD/Resources/pass.png new file mode 100644 index 0000000..d260ca2 Binary files /dev/null and b/OutlookDSD/Resources/pass.png differ diff --git a/OutlookDSD/Ribbon.cs b/OutlookDSD/Ribbon.cs new file mode 100644 index 0000000..0b5c61e --- /dev/null +++ b/OutlookDSD/Ribbon.cs @@ -0,0 +1,251 @@ +using Microsoft.Office.Interop.Outlook; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using Office = Microsoft.Office.Core; + +namespace OutlookDSD +{ + [ComVisible(true)] + public class Ribbon : Office.IRibbonExtensibility + { + private readonly List ribbons = new List (); + private readonly Dictionary validatorCache = new Dictionary(); + private readonly Dictionary enabledStatus = new Dictionary(); + + public Ribbon() + { + } + + public void Invalidate() + { + foreach(Office.IRibbonUI ribbon in ribbons) + { + ribbon.Invalidate(); + } + + } + public void CacheResults(Validator newValidatorObj) + { + MailItem mailItem = newValidatorObj.GetMailItem(); + string entryID = mailItem.EntryID; + if (!validatorCache.ContainsKey(entryID)) + { + validatorCache.Add(entryID, newValidatorObj); + } + Invalidate(); + } + + #region IRibbonExtensibility Members + public string GetCustomUI(string ribbonID) + { + string xmlFile; + string settingCheck; + switch (ribbonID) + { + case "Microsoft.Outlook.Explorer": + settingCheck = "ribbon_showOnExplorer"; + xmlFile = "OutlookDSD.RibbonMain.xml"; + break; + case "Microsoft.Outlook.Mail.Read": + settingCheck = "ribbon_showOnEmail"; + xmlFile = "OutlookDSD.RibbonMessage.xml"; + break; + default: + return null; + } + bool showRibbon = (bool) Properties.Settings.Default[settingCheck]; + if(showRibbon == false) { + return null; + } + string xml = GetResourceText(xmlFile); + return xml; + } + + #endregion + + #region Ribbon Callbacks + // Function signature for all callbacks is at https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa722523(v=office.12) + + // Hanldle clicking on a mechnaism button + public void Btn_Click(Office.IRibbonControl control){ + + // Get the current email from the context that the control belongs to + MailItem mailItem = GetMailItemFromCurrntControl(control); + if (mailItem == null) + { + return; + } + + // Get the result of the mechnaism clicked on + string mechanism = ControlIDtoMechanism(control)[0].ToLower(); + string mechanismUpper = mechanism.ToUpper(); + Validator validator = ValidatorGet(mailItem); + string[] result = validator.Results()[mechanism]; + + // Set the details string to the full details of the result summary + string details = result[1]; + + //If the mechanism result was none, then set an error message as the details string + if (result[0] == Validator.RESULT_NONE) + { + details = mechanismUpper + " was not used."; + } + + // Display the messagebox to the user. + MessageBox.Show(details, "Details for " + mechanismUpper + " - OutlookDSD"); + } + + public void Ribbon_Load(Office.IRibbonUI ribbonUI) + { + ribbons.Add(ribbonUI); + } + #endregion + + public bool Btn_getEnabled(Office.IRibbonControl ctrl) + { + MailItem mailitem = GetMailItemFromCurrntControl(ctrl); + if(mailitem != null) + { + if (enabledStatus.ContainsKey(mailitem.EntryID)) + { + return enabledStatus[mailitem.EntryID]; + } + } + + return false; + } + #region Helpe + + public System.Drawing.Image Btn_GetImage(Office.IRibbonControl ctrl) + { + // Get the current email from the context that the control belongs to + MailItem mailItem = GetMailItemFromCurrntControl(ctrl); + + // If the controls are disabled then return the blank image called disabled + if (null == mailItem || enabledStatus.ContainsKey(mailItem.EntryID) == false || enabledStatus[mailItem.EntryID] == false) + { + return (System.Drawing.Image)Properties.Resources.ResourceManager.GetObject("disabled"); + } + + string[] labelInfo = ControlIDtoMechanism(ctrl); + string mechnaism = labelInfo[0].ToLower(); + string IconName; + + Validator validator = ValidatorGet(mailItem); + + if (!validator.Results().ContainsKey(mechnaism)) + { + IconName = "error"; + } + else + { + IconName = validator.Results()[mechnaism][0]; + } + return (System.Drawing.Image) Properties.Resources.ResourceManager.GetObject(IconName); + } + + private static string GetResourceText(string resourceName) + { + Assembly asm = Assembly.GetExecutingAssembly(); + string[] resourceNames = asm.GetManifestResourceNames(); + for (int i = 0; i < resourceNames.Length; ++i) + { + if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0) + { + using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i]))) + { + if (resourceReader != null) + { + return resourceReader.ReadToEnd(); + } + } + } + } + return null; + } + + private Validator ValidatorGet(MailItem mailItem) + { + string entryID = mailItem.EntryID; + if (validatorCache.ContainsKey(entryID)) + { + validatorCache.TryGetValue(entryID, out Validator validator); + return validator; + } + return new Validator(null); + } + + private string[] ControlIDtoMechanism(Office.IRibbonControl control) + { + string controlId = control.Id; + if (!controlId.StartsWith("emailValidation")){ + return new string[] { String.Empty, String.Empty }; + } + string[] nameParts = controlId.Split("_"[0]); + return new string[]{ + nameParts[2], + nameParts[1], + }; + } + + private MailItem GetMailItemFromCurrntControl(Office.IRibbonControl control) + { + int contextClass = control.Context.Class; + + if (contextClass == 35) // Email - IPM.Note + { + return control.Context.CurrentItem; + } + else if (contextClass == 34) // Outlook Explorer + { + // Wrap the whole thing in a try/catch statement in case ActiveExplorer throws an exception + try + { + var selection = Globals.ThisAddIn.Application.ActiveExplorer().Selection; + if (selection.Count == 1) // One email is selected, let's parse it + { + MailItem emailItem = selection[1]; // Not a bug - Selection index starts at 1 and not 0! + return emailItem; + } + else + { + return null; + } + } + catch(System.Exception) + { + return null; + } + } + else + { + return null; + } + } + + public void Enable(MailItem emailItem) + { + SetEnabled(true, emailItem); + } + + public void Disable(MailItem emailItem) + { + SetEnabled(false, emailItem); + } + + private void SetEnabled(bool isEnabled, MailItem emailItem) + { + if(emailItem != null) + { + enabledStatus[emailItem.EntryID] = isEnabled; + } + Invalidate(); + } + + #endregion + } +} diff --git a/OutlookDSD/RibbonMain.xml b/OutlookDSD/RibbonMain.xml new file mode 100644 index 0000000..75478d3 --- /dev/null +++ b/OutlookDSD/RibbonMain.xml @@ -0,0 +1,14 @@ + + + + + + +