Merge with default OUT-222
authorThomas
Mon, 16 Jul 2018 12:36:58 +0200
branchOUT-222
changeset 2297cc0598df6325
parent 2292 669e39629d45
parent 2296 8be60b97b838
child 2298 bfe1d8b13419
Merge with default
CryptableMailItem.cs
Extensions/MailItemExtensions.cs
UI/FormRegionPrivacyStatus.cs
pEpForOutlook.csproj
     1.1 --- a/CryptableMailItem.cs	Fri Jul 13 10:24:14 2018 +0200
     1.2 +++ b/CryptableMailItem.cs	Mon Jul 16 12:36:58 2018 +0200
     1.3 @@ -106,6 +106,7 @@
     1.4          private BackgroundWorker                  mirrorLocator;
     1.5          private BackgroundWorker                  processor;
     1.6  
     1.7 +        private string                            draftEntryId          = null;
     1.8          private string                            draftFileName         = null;
     1.9          private object                            mutexMailItem         = new object();
    1.10          private static object                     mutexConversation     = new object();
    1.11 @@ -113,25 +114,41 @@
    1.12          private static List<OriginalMailItem>     conversationCache     = new List<OriginalMailItem>();
    1.13          private static Dictionary<string, string> decryptionList        = new Dictionary<string, string>();
    1.14  
    1.15 -        /* Stores the message id of an attached mail item if it is loaded into the preview. 
    1.16 -         * See comments below in MailItem_BeforeAttachmentPreview event handler.
    1.17 -         */
    1.18 -        public static string    PreviewAttachedMailId = null;
    1.19 +        /// <summary>
    1.20 +        /// Stores the message id of an attached mail item if it is loaded into the preview.
    1.21 +        /// See comments below in MailItem_BeforeAttachmentPreview event handler.
    1.22 +        /// </summary>
    1.23 +        public static string PreviewAttachedMailId = null;
    1.24  
    1.25 -        // Whether to cancel the opening event of the internal mail item. Default is false.
    1.26 -        public bool         CancelOpen              { get; set; } = false;
    1.27 +        /// <summary>
    1.28 +        /// Whether to cancel the opening event of the internal mail item. Default is false.
    1.29 +        /// </summary>
    1.30 +        public bool CancelOpen { get; set; } = false;
    1.31  
    1.32 -        // The messageId of the internal mail item. Only needed for special cases like attached mails.
    1.33 -        public string       MessageId               { get; set; } = null;
    1.34 +        /// <summary>
    1.35 +        /// The messageId of the internal mail item. Only needed for special cases like attached mails.
    1.36 +        /// </summary>
    1.37 +        public string MessageId { get; set; } = null;
    1.38  
    1.39 -        // Whether the internal mail item is an attached mail
    1.40 -        public bool         IsSecureAttachedMail    { get; set; } = false;
    1.41 +        /// <summary>
    1.42 +        /// Whether the internal mail item is an inline response
    1.43 +        /// </summary>
    1.44 +        public bool IsInlineResponse { get; set; } = false;
    1.45  
    1.46 -        // The mirror of the internal mail item stored as PEPMessage
    1.47 -        public PEPMessage   Mirror                  { get; set; } = null;
    1.48 +        /// <summary>
    1.49 +        /// Whether the internal mail item is an attached mail.
    1.50 +        /// </summary>
    1.51 +        public bool IsSecureAttachedMail { get; set; } = false;
    1.52  
    1.53 -        // The PEPMessage of this mail item
    1.54 -        public PEPMessage   Message                 { get; set; } = null;
    1.55 +        /// <summary>
    1.56 +        /// The mirror of the internal mail item stored as PEPMessage.
    1.57 +        /// </summary>
    1.58 +        public PEPMessage Mirror { get; set; } = null;
    1.59 +
    1.60 +        /// <summary>
    1.61 +        /// The PEPMessage of this mail item.
    1.62 +        /// </summary>
    1.63 +        public PEPMessage Message { get; set; } = null;
    1.64  
    1.65          /**************************************************************
    1.66           * 
    1.67 @@ -379,6 +396,7 @@
    1.68               * First we try to save it to a custom drafts folder in the pEp store
    1.69               * and make this store visible in the favorites.
    1.70               * If this fails, as a fallback solution, we offer to save as a message file.
    1.71 +             * Note: Inline responses need to be processed differently.
    1.72               */
    1.73              if ((this.HasBeenSent == false) &&
    1.74                  (this.IsPEPMessage == false) &&
    1.75 @@ -386,8 +404,9 @@
    1.76                  ((this.internalMailItem.GetIsInSecureStore() || this.internalMailItem.GetNeverUnsecure())))
    1.77              {
    1.78                  bool useFallback = false;
    1.79 +                Outlook.Folder parentFolder = null;
    1.80                  Outlook.Folder pEpDraftsFolder = null;
    1.81 -                Outlook.Inspector activeInspector = null;
    1.82 +                Outlook.Inspector currentInspector = null;
    1.83                  Outlook.Inspector newInspector = null;
    1.84                  Outlook.MailItem omi = null;
    1.85  
    1.86 @@ -402,32 +421,104 @@
    1.87  
    1.88                  try
    1.89                  {
    1.90 +                    // Get the pEp drafts folder and the current mail item's folder
    1.91                      pEpDraftsFolder = Globals.ThisAddIn.GetPEPStoreDraftsFolder();
    1.92  
    1.93 -                    // Save to pEp drafts folder if available
    1.94 -                    if (pEpDraftsFolder != null)
    1.95 +                    /* Inline responses need a special treatment.
    1.96 +                     * We cannot just intercept the Write event and check, if the item
    1.97 +                     * is in the pEp folder, as it gets synced to the server anyhow if we
    1.98 +                     * don't cancel the event.
    1.99 +                     * So, we look up if the mail item is already present in pEp drafts and overwrite it 
   1.100 +                     * with the current state if possible. If the item isn't there yet, create new item, 
   1.101 +                     * move to pEp drafts folder and save current state.
   1.102 +                     */
   1.103 +                    if (this.IsInlineResponse)
   1.104                      {
   1.105 -                        // Try to move mail item to pEp drafts folder, if it's
   1.106 -                        // not already there.
   1.107 -                        var parent = this.internalMailItem.Parent as Outlook.Folder;
   1.108 -                        if (parent != pEpDraftsFolder // identity comparison of folders does not work
   1.109 -                            && parent.FullFolderPath != pEpDraftsFolder.FullFolderPath)
   1.110 +                        Outlook.Items items = null;
   1.111 +                        Outlook.MailItem draft = null;
   1.112 +
   1.113 +                        try
   1.114                          {
   1.115 -                            activeInspector = this.internalMailItem.GetInspector;
   1.116 +                            // Always cancel
   1.117 +                            cancel = true;
   1.118 +
   1.119 +                            // Try to find the draft (if existing)
   1.120 +                            if (string.IsNullOrEmpty(this.draftEntryId) == false)
   1.121 +                            {
   1.122 +                                // Get all items in the pEp drafts folder with the same subject as the current draft
   1.123 +                                items = pEpDraftsFolder?.Items?.Restrict(string.Format("[Subject] = '{0}'", this.internalMailItem?.Subject));
   1.124 +
   1.125 +                                for (int i = 1; i <= items?.Count; i++)
   1.126 +                                {
   1.127 +                                    draft = items[i] as Outlook.MailItem;
   1.128 +
   1.129 +                                    if (draftEntryId.Equals(draft?.EntryID) == true)
   1.130 +                                    {
   1.131 +                                        // Draft found. Just break and continue.
   1.132 +                                        break;
   1.133 +                                    }
   1.134 +
   1.135 +                                    draft = null;
   1.136 +                                }
   1.137 +
   1.138 +                                items = null;
   1.139 +                            }
   1.140 +
   1.141 +                            PEPMessage createdMessage = null;
   1.142 +                            if (PEPMessage.Create(this.internalMailItem, out createdMessage) == Globals.ReturnStatus.Success)
   1.143 +                            {
   1.144 +                                if (draft == null)
   1.145 +                                {
   1.146 +                                    draft = Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
   1.147 +                                    createdMessage.ApplyTo(draft, true, true);
   1.148 +                                    draft = draft.Move(pEpDraftsFolder);
   1.149 +                                    draft.Save();
   1.150 +                                    this.draftEntryId = draft.EntryID;
   1.151 +                                }
   1.152 +                                else
   1.153 +                                {
   1.154 +                                    createdMessage.ApplyTo(draft, true, true);
   1.155 +                                    draft.Save();
   1.156 +                                }
   1.157 +                            }
   1.158 +                            else
   1.159 +                            {
   1.160 +                                Log.Error("MailItem_Write: Error creating PEPMessage.");
   1.161 +                            }
   1.162 +                        }
   1.163 +                        catch (Exception ex)
   1.164 +                        {
   1.165 +                            Log.Error("MailItem_Write: Error saving inline item. " + ex.ToString());
   1.166 +                        }
   1.167 +                        finally
   1.168 +                        {
   1.169 +                            items = null;
   1.170 +                            omi = null;
   1.171 +                        }
   1.172 +                    }
   1.173 +                    else
   1.174 +                    {
   1.175 +                        // Get the mail item's parent folder
   1.176 +                        parentFolder = this.internalMailItem.Parent as Outlook.Folder;
   1.177 +
   1.178 +                        // Save to pEp folder if not already there
   1.179 +                        if (pEpDraftsFolder?.FullFolderPath?.Equals(parentFolder?.FullFolderPath) == false)
   1.180 +                        {
   1.181 +                            currentInspector = this.internalMailItem.GetInspector;
   1.182                              omi = this.internalMailItem.Copy();
   1.183                              omi = omi.Move(pEpDraftsFolder);
   1.184  
   1.185 -                            if (activeInspector != null)
   1.186 +                            if (currentInspector != null)
   1.187                              {
   1.188 -                                Outlook.OlWindowState windowState = activeInspector.WindowState;
   1.189 +                                Outlook.OlWindowState windowState = currentInspector.WindowState;
   1.190                                  newInspector = Globals.ThisAddIn?.Application?.Inspectors?.Add(omi);
   1.191  
   1.192                                  if (windowState == Outlook.OlWindowState.olNormalWindow)
   1.193                                  {
   1.194 -                                    newInspector.Left = activeInspector.Left;
   1.195 -                                    newInspector.Top = activeInspector.Top;
   1.196 -                                    newInspector.Width = activeInspector.Width;
   1.197 -                                    newInspector.Height = activeInspector.Height;
   1.198 +                                    newInspector.Left = currentInspector.Left;
   1.199 +                                    newInspector.Top = currentInspector.Top;
   1.200 +                                    newInspector.Width = currentInspector.Width;
   1.201 +                                    newInspector.Height = currentInspector.Height;
   1.202                                  }
   1.203  
   1.204                                  /* In some circumstances (e.g. ForceProtection on Exchange), the Sender information 
   1.205 @@ -461,7 +552,7 @@
   1.206  
   1.207                                  newInspector.Display();
   1.208                                  newInspector.WindowState = windowState;
   1.209 -                                activeInspector.Close(Outlook.OlInspectorClose.olDiscard);
   1.210 +                                currentInspector.Close(Outlook.OlInspectorClose.olDiscard);
   1.211                              }
   1.212                              else
   1.213                              {
   1.214 @@ -471,45 +562,45 @@
   1.215  
   1.216                              cancel = true;
   1.217                          }
   1.218 +                    }
   1.219  
   1.220 -                        /* Add the pEp drafts folder to favorites.
   1.221 -                         * This is dangerous, as the Add() method crashes Outlook if the pEp store is not visible.
   1.222 -                         * To make this more secure, we only proceed if the pEp store is already visible at this point.
   1.223 -                         * Otherwise, we just set the pEp store's visibility to true and try to add the drafts folder
   1.224 -                         * to the favorites next time.
   1.225 +                    /* Add the pEp drafts folder to favorites.
   1.226 +                     * This is dangerous, as the Add() method crashes Outlook if the pEp store is not visible.
   1.227 +                     * To make this more secure, we only proceed if the pEp store is already visible at this point.
   1.228 +                     * Otherwise, we just set the pEp store's visibility to true and try to add the drafts folder
   1.229 +                     * to the favorites next time.
   1.230 +                     */
   1.231 +                    if (Globals.ThisAddIn.Settings.IsPEPFolderVisible)
   1.232 +                    {
   1.233 +                        // Get favorite folders group. See: https://msdn.microsoft.com/en-us/library/office/ff865603.aspx
   1.234 +                        app = Globals.ThisAddIn?.Application;
   1.235 +                        activeExplorer = app?.ActiveExplorer();
   1.236 +                        navPane = activeExplorer?.NavigationPane;
   1.237 +                        navModules = navPane?.Modules;
   1.238 +                        mailModule = navModules?.GetNavigationModule(Outlook.OlNavigationModuleType.olModuleMail) as Outlook.MailModule;
   1.239 +                        navGroups = mailModule?.NavigationGroups;
   1.240 +                        navGroup = navGroups?.GetDefaultNavigationGroup(Outlook.OlGroupType.olFavoriteFoldersGroup);
   1.241 +                        navFolders = navGroup?.NavigationFolders;
   1.242 +
   1.243 +                        /* Check, if pEp drafts folder is already in favorites
   1.244 +                         * WARNING: If for whatever reason, the pEp store is not visible
   1.245 +                         * at this point, the Add() method crashes Outlook!
   1.246                           */
   1.247 -                        if (Globals.ThisAddIn.Settings.IsPEPFolderVisible)
   1.248 +                        if (navFolders[Globals.PEP_DRAFTS_FOLDER_NAME] == null)
   1.249                          {
   1.250 -                            // Get favorite folders group. See: https://msdn.microsoft.com/en-us/library/office/ff865603.aspx
   1.251 -                            app = Globals.ThisAddIn?.Application;
   1.252 -                            activeExplorer = app?.ActiveExplorer();
   1.253 -                            navPane = activeExplorer?.NavigationPane;
   1.254 -                            navModules = navPane?.Modules;
   1.255 -                            mailModule = navModules?.GetNavigationModule(Outlook.OlNavigationModuleType.olModuleMail) as Outlook.MailModule;
   1.256 -                            navGroups = mailModule?.NavigationGroups;
   1.257 -                            navGroup = navGroups?.GetDefaultNavigationGroup(Outlook.OlGroupType.olFavoriteFoldersGroup);
   1.258 -                            navFolders = navGroup?.NavigationFolders;
   1.259 -
   1.260 -                            /* Check, if pEp drafts folder is already in favorites
   1.261 -                             * WARNING: If for whatever reason, the pEp store is not visible
   1.262 -                             * at this point, the Add() method crashes Outlook!
   1.263 -                             */
   1.264 -                            if (navFolders[Globals.PEP_DRAFTS_FOLDER_NAME] == null)
   1.265 +                            if (navFolders != null)
   1.266                              {
   1.267 -                                if (navFolders != null)
   1.268 -                                {
   1.269 -                                    navFolders.Add(pEpDraftsFolder);
   1.270 -                                }
   1.271 -                                else
   1.272 -                                {
   1.273 -                                    Log.Error("Cannot add pEp drafts folder to favorites because the folder could not be retrieved.");
   1.274 -                                }
   1.275 +                                navFolders.Add(pEpDraftsFolder);
   1.276 +                            }
   1.277 +                            else
   1.278 +                            {
   1.279 +                                Log.Error("Cannot add pEp drafts folder to favorites because the folder could not be retrieved.");
   1.280                              }
   1.281                          }
   1.282 -                        else
   1.283 -                        {
   1.284 -                            Globals.ThisAddIn.Settings.IsPEPFolderVisible = true;
   1.285 -                        }
   1.286 +                    }
   1.287 +                    else
   1.288 +                    {
   1.289 +                        Globals.ThisAddIn.Settings.IsPEPFolderVisible = true;
   1.290                      }
   1.291                  }
   1.292                  catch (Exception ex)
   1.293 @@ -519,7 +610,8 @@
   1.294                  }
   1.295                  finally
   1.296                  {
   1.297 -                    activeInspector = null;
   1.298 +                    currentInspector = null;
   1.299 +                    parentFolder = null;
   1.300                      pEpDraftsFolder = null;
   1.301                      omi = null;
   1.302  
     2.1 --- a/Extensions/MailItemExtensions.cs	Fri Jul 13 10:24:14 2018 +0200
     2.2 +++ b/Extensions/MailItemExtensions.cs	Mon Jul 16 12:36:58 2018 +0200
     2.3 @@ -255,7 +255,8 @@
     2.4              /* If S/MIME is enabled by default, the mirror creation by new mail item fails during the
     2.5               * Save() method. 
     2.6               */
     2.7 -            if (omi.GetIsSMIMEEnabled() == false)
     2.8 +            if ((Globals.ThisAddIn.OutlookOptions.IsSMIMEEnabled == false) &&
     2.9 +                (omi.GetIsSMIMEEnabled() == false))
    2.10              {
    2.11                  try
    2.12                  {
     3.1 --- a/OutlookOptions.cs	Fri Jul 13 10:24:14 2018 +0200
     3.2 +++ b/OutlookOptions.cs	Mon Jul 16 12:36:58 2018 +0200
     3.3 @@ -19,6 +19,13 @@
     3.4          private readonly string officeVersion = Globals.ThisAddIn.Application.Version.Substring(0, 2) + ".0";
     3.5  
     3.6          /// <summary>
     3.7 +        /// Gets whether S/MIME encryption or signatures are enabled.
     3.8 +        /// Note: The registry value that is set when enabling S/MIME won't get unset or changed
     3.9 +        ///       again after disabling it. So this might yield a false positive.
    3.10 +        /// </summary>
    3.11 +        public bool IsSMIMEEnabled { get; set; } = false;
    3.12 +
    3.13 +        /// <summary>
    3.14          /// Read email messages in plain text
    3.15          /// See: https://support.office.com/en-us/article/Read-email-messages-in-plain-text-2443DA66-4AB8-451E-98A8-489A58D00A40
    3.16          /// </summary>
    3.17 @@ -29,8 +36,14 @@
    3.18          /// </summary>
    3.19          public void ReadOptionsFromRegistry()
    3.20          {
    3.21 +            // Path to Outlook
    3.22 +            string registryPathOutlook = Path.Combine("Software", "Microsoft", "Office", officeVersion, "Outlook");
    3.23 +
    3.24 +            // Path to Security settings
    3.25 +            string registryPathSecurity = Path.Combine(registryPathOutlook, "Security");
    3.26 +
    3.27              // Path to Outlook options
    3.28 -            string registryPathOptions = Path.Combine("Software", "Microsoft", "Office", officeVersion, "Outlook", "Options");
    3.29 +            string registryPathOptions = Path.Combine(registryPathOutlook, "Options");
    3.30  
    3.31              // Path to Mail options
    3.32              string registryPathMail = Path.Combine(registryPathOptions, "Mail");
    3.33 @@ -40,7 +53,7 @@
    3.34              {
    3.35                  using (RegistryKey mailOptions = Registry.CurrentUser.OpenSubKey(registryPathMail))
    3.36                  {
    3.37 -                    this.ReadAsPlain = mailOptions?.GetValue(nameof(ReadAsPlain)) as int? == 1;
    3.38 +                    this.ReadAsPlain = ((mailOptions?.GetValue(nameof(ReadAsPlain)) as int?) == 1);
    3.39                  }
    3.40              }
    3.41              catch (Exception ex)
    3.42 @@ -48,6 +61,28 @@
    3.43                  this.ReadAsPlain = false;
    3.44                  Log.Error("OutlookOptions.ReadOptionsFromRegistry: Error getting ReadAsPlain value. " + ex.ToString());
    3.45              }
    3.46 +
    3.47 +            // Get whether an S/MIME option is enabled
    3.48 +            try
    3.49 +            {
    3.50 +                using (RegistryKey securityOptions = Registry.CurrentUser.OpenSubKey(registryPathSecurity))
    3.51 +                {
    3.52 +                    /* If S/MIME encryption or signature is enabled by default through the Outlook UI,
    3.53 +                     * the Registry values "InitEncrypt" and/or InitSign" are being added to 
    3.54 +                     * HKCU\Software\Microsoft\Office\<version no.>\Outlook\Security and set to 2 (enabled).
    3.55 +                     * However, if they are being disabled again through the UI, those values remain with
    3.56 +                     * the same value (at least in some environments). The following condition is therefore prone
    3.57 +                     * to yield false positives. Until a better solution is found, we will use this approximation.
    3.58 +                     */ 
    3.59 +                    this.IsSMIMEEnabled = (((securityOptions?.GetValue("InitEncrypt") as int?) == 2) ||
    3.60 +                                           ((securityOptions?.GetValue("InitSign") as int?) == 2));
    3.61 +                }
    3.62 +            }
    3.63 +            catch (Exception ex)
    3.64 +            {
    3.65 +                this.IsSMIMEEnabled = false;
    3.66 +                Log.Error("OutlookOptions.ReadOptionsFromRegistry: Error getting IsSMIMEEnabled value. " + ex.ToString());
    3.67 +            }
    3.68          }
    3.69  
    3.70          /// <summary>
     4.1 --- a/ThisAddIn.cs	Fri Jul 13 10:24:14 2018 +0200
     4.2 +++ b/ThisAddIn.cs	Mon Jul 16 12:36:58 2018 +0200
     4.3 @@ -54,12 +54,16 @@
     4.4          private AdapterCallbacks adapterCallbacks = null;
     4.5  #endif
     4.6  
     4.7 -        private bool                       initialized               = false;
     4.8 -        private bool                       isItemSendHandlerEnabled  = true;
     4.9 -        private FormControlOptions.State   lastOptionsState          = null;
    4.10 -        private Dictionary<string, string> userIdCache               = new Dictionary<string, string>();
    4.11 -        private List<WatchedFolder>        watchedFolders            = new List<WatchedFolder>();
    4.12 -        private System.Windows.Forms.Timer inboxCleaner              = null;
    4.13 +        private bool                        initialized                 = false;
    4.14 +        private bool                        isItemSendHandlerEnabled    = true;
    4.15 +        private FormControlOptions.State    lastOptionsState            = null;
    4.16 +        private Dictionary<string, string>  userIdCache                 = new Dictionary<string, string>();
    4.17 +        private List<WatchedFolder>         watchedFolders              = new List<WatchedFolder>();
    4.18 +        private System.Windows.Forms.Timer  inboxCleaner                = null;
    4.19 +
    4.20 +        private List<WatchedExplorer>       watchedExplorers            = new List<WatchedExplorer>();
    4.21 +        private object                      mutexWatchedExplorers       = new object();
    4.22 +        private Outlook.Explorers           explorers                   = null;
    4.23  
    4.24          /**************************************************************
    4.25           * 
    4.26 @@ -212,6 +216,30 @@
    4.27          }
    4.28  
    4.29          /// <summary>
    4.30 +        /// Adds a new WatchedExplorer to the list of watched explorers.
    4.31 +        /// </summary>
    4.32 +        /// <param name="watchedExplorer">The WatchedExplorer to add.</param>
    4.33 +        internal void AddToWatchedExplorers(WatchedExplorer watchedExplorer)
    4.34 +        {
    4.35 +            lock (mutexWatchedExplorers)
    4.36 +            {
    4.37 +                this.watchedExplorers.Add(watchedExplorer);
    4.38 +            }
    4.39 +        }
    4.40 +
    4.41 +        /// <summary>
    4.42 +        /// Removes a WatchedExplorer from the list of watched explorers.
    4.43 +        /// </summary>
    4.44 +        /// <param name="watchedExplorer">The WatchedExplorer to remove.</param>
    4.45 +        internal void RemoveFromWatchedExplorers(WatchedExplorer watchedExplorer)
    4.46 +        {
    4.47 +            lock (mutexWatchedExplorers)
    4.48 +            {
    4.49 +                this.watchedExplorers.Remove(watchedExplorer);
    4.50 +            }
    4.51 +        }
    4.52 +
    4.53 +        /// <summary>
    4.54          /// This updates the accounts list in pEp settings with the ones found in Outlook, adding new accounts and removing
    4.55          /// all accounts that are not there anymore.
    4.56          /// </summary>
    4.57 @@ -2784,6 +2812,10 @@
    4.58                      Log.Info("ThisAddIn_Startup: Connect Watched folders");
    4.59                      this.ConnectWatchedFolders();
    4.60  
    4.61 +                    // Connect watched explorers
    4.62 +                    Log.Info("ThisAddIn_Startup: Connect Watched explorers");
    4.63 +                    this.ConnectWatchedExplorers(true);
    4.64 +
    4.65                      // Connect application events
    4.66                      Log.Info("ThisAddIn_Startup: Connect Application Events");
    4.67                      this.ConnectApplicationEvents(true);
    4.68 @@ -2842,6 +2874,64 @@
    4.69          }
    4.70  
    4.71          /// <summary>
    4.72 +        /// Connects all explorers with their respective events and the Explorers collection
    4.73 +        /// with the NewExplorer event.
    4.74 +        /// <param name="connect">Whether to connect or disconnect the explorers.</param>
    4.75 +        /// </summary>
    4.76 +        private void ConnectWatchedExplorers(bool connect)
    4.77 +        {
    4.78 +            try
    4.79 +            {
    4.80 +                if (connect)
    4.81 +                {
    4.82 +                    this.explorers = this.Application.Explorers;
    4.83 +
    4.84 +                    for (int i = 1; i <= this.explorers.Count; i++)
    4.85 +                    {
    4.86 +                        this.watchedExplorers.Add(new WatchedExplorer(this.explorers[i]));
    4.87 +                    }
    4.88 +
    4.89 +                    this.explorers.NewExplorer += Explorers_NewExplorer;
    4.90 +                }
    4.91 +                else
    4.92 +                {
    4.93 +                    this.explorers.NewExplorer -= Explorers_NewExplorer;
    4.94 +
    4.95 +                    for (int i = 0; i < this.watchedExplorers.Count; i++)
    4.96 +                    {
    4.97 +                        this.RemoveFromWatchedExplorers(this.watchedExplorers[i]);
    4.98 +                        this.watchedExplorers[i].Dispose();
    4.99 +                    }
   4.100 +
   4.101 +                    this.explorers = null;
   4.102 +                }
   4.103 +            }
   4.104 +            catch (Exception ex)
   4.105 +            {
   4.106 +                Log.Error("ConnectWatchedExplorers: Error occured. " + ex.ToString());
   4.107 +            }        
   4.108 +        }
   4.109 +
   4.110 +        /// <summary>
   4.111 +        /// Disconnects all explorer events.
   4.112 +        /// </summary>
   4.113 +        private void DisconnectWatchedExplorers()
   4.114 +        {
   4.115 +            this.explorers.NewExplorer -= Explorers_NewExplorer;
   4.116 +            this.explorers = null;
   4.117 +        }
   4.118 +
   4.119 +        /// <summary>
   4.120 +        /// Event handler for when a new explorer is being opened and 
   4.121 +        /// added to the Explorers collection.
   4.122 +        /// </summary>
   4.123 +        /// <param name="Explorer">The newly opened explorer.</param>
   4.124 +        private void Explorers_NewExplorer(Outlook.Explorer explorer)
   4.125 +        {
   4.126 +            this.AddToWatchedExplorers(new WatchedExplorer(explorer));
   4.127 +        }
   4.128 +
   4.129 +        /// <summary>
   4.130          /// Enables or disables the automatic deletion of old autoconsume messages.
   4.131          /// This gets automatically disabled again if no autoconsume messages are found in the inbox.
   4.132          /// <param name="enable">Whether to enable or disable the automatic cleaning.</param>
   4.133 @@ -3170,6 +3260,9 @@
   4.134              // Disconnect application events
   4.135              this.ConnectApplicationEvents(false);
   4.136  
   4.137 +            // Disconnect watched items
   4.138 +            this.ConnectWatchedExplorers(false);
   4.139 +
   4.140              // Save configuration
   4.141              this._Settings.SaveToRegistry();
   4.142              this._Settings.PropertyChanged -= Settings_PropertyChanged;
     5.1 --- a/UI/FormRegionPrivacyStatus.cs	Fri Jul 13 10:24:14 2018 +0200
     5.2 +++ b/UI/FormRegionPrivacyStatus.cs	Mon Jul 16 12:36:58 2018 +0200
     5.3 @@ -763,6 +763,29 @@
     5.4  
     5.5                  this.cryptableMailItem = new CryptableMailItem(omi, provisionalRating);
     5.6  
     5.7 +                // Check if inline response
     5.8 +                if (omi.GetIsDraft())
     5.9 +                {
    5.10 +                    Outlook.Explorer explorer = null;
    5.11 +                    Outlook.MailItem inlineResponse = null;
    5.12 +
    5.13 +                    try
    5.14 +                    {
    5.15 +                        explorer = this.OutlookFormRegion?.Parent as Outlook.Explorer;
    5.16 +                        inlineResponse = explorer?.ActiveInlineResponse as Outlook.MailItem;
    5.17 +                        this.cryptableMailItem.IsInlineResponse = omi.Equals(inlineResponse);
    5.18 +                    }
    5.19 +                    catch (Exception ex)
    5.20 +                    {
    5.21 +                        Log.Error("FormRegionPrivacyStatus_FormRegionShowing: Error determining whether it's an inline response. " + ex.ToString());
    5.22 +                    }
    5.23 +                    finally
    5.24 +                    {
    5.25 +                        explorer = null;
    5.26 +                        inlineResponse = null;
    5.27 +                    }
    5.28 +                }
    5.29 +
    5.30                  if (isSecureAttachedMail)
    5.31                  {
    5.32                      this.cryptableMailItem.MessageId = messageId;
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/Wrappers/WatchedExplorer.cs	Mon Jul 16 12:36:58 2018 +0200
     6.3 @@ -0,0 +1,153 @@
     6.4 +´╗┐using System;
     6.5 +using Outlook = Microsoft.Office.Interop.Outlook;
     6.6 +
     6.7 +namespace pEp
     6.8 +{
     6.9 +    /// <summary>
    6.10 +    /// Stores an Outlook Explorer with connected events.
    6.11 +    /// </summary>
    6.12 +    public class WatchedExplorer : IDisposable
    6.13 +    {
    6.14 +        private Outlook.Explorer                explorer                   = null;
    6.15 +        private CryptableMailItem               inlineResponseItem         = null;
    6.16 +
    6.17 +        /**************************************************************
    6.18 +         * 
    6.19 +         * Constructors/Destructors
    6.20 +         * 
    6.21 +         *************************************************************/
    6.22 +
    6.23 +        /// <summary>
    6.24 +        /// Primary constructor.
    6.25 +        /// </summary>
    6.26 +        /// <param name="explorer">The explorer to watch.</param>
    6.27 +        public WatchedExplorer(Outlook.Explorer explorer)
    6.28 +        {
    6.29 +            this.explorer = explorer;
    6.30 +
    6.31 +            if (this.explorer != null)
    6.32 +            {
    6.33 +                this.ConnectWatchedExplorerEvents(true);
    6.34 +            }
    6.35 +        }
    6.36 +
    6.37 +        /// <summary>
    6.38 +        /// Destructor.
    6.39 +        /// </summary>
    6.40 +        ~WatchedExplorer()
    6.41 +        {
    6.42 +            this.Dispose(true);
    6.43 +        }
    6.44 +
    6.45 +        #region Methods
    6.46 +        /**************************************************************
    6.47 +         * 
    6.48 +         * Methods
    6.49 +         * 
    6.50 +         *************************************************************/
    6.51 +
    6.52 +        /// <summary>
    6.53 +        /// Releases all resources and disconnects internal events.
    6.54 +        /// </summary>
    6.55 +        public void Dispose()
    6.56 +        {
    6.57 +            this.Dispose(true);
    6.58 +        }
    6.59 +
    6.60 +        /// <summary>
    6.61 +        /// Clean up any resources being used.
    6.62 +        /// </summary>
    6.63 +        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    6.64 +        protected virtual void Dispose(bool disposing)
    6.65 +        {
    6.66 +            if (disposing)
    6.67 +            {
    6.68 +                // Disconnect all events
    6.69 +                this.ConnectWatchedExplorerEvents(false);
    6.70 +
    6.71 +                // Set Outlook objects to null
    6.72 +                this.explorer = null;
    6.73 +                this.inlineResponseItem?.Dispose();
    6.74 +                this.inlineResponseItem = null;
    6.75 +            }
    6.76 +        }
    6.77 +
    6.78 +        /// <summary>
    6.79 +        /// Connects the events for this watched explorer.
    6.80 +        /// <param name="connect">Whether to connect or disconnect the events.</param>
    6.81 +        /// </summary>
    6.82 +        private void ConnectWatchedExplorerEvents(bool connect)
    6.83 +        {
    6.84 +            try
    6.85 +            {
    6.86 +                if (connect)
    6.87 +                {
    6.88 +                    ((Outlook.ExplorerEvents_10_Event)this.explorer).Close += Explorer_Close;
    6.89 +                    ((Outlook.ExplorerEvents_10_Event)this.explorer).InlineResponseClose += Explorer_InlineResponseClose;
    6.90 +                }
    6.91 +                else
    6.92 +                {
    6.93 +                    ((Outlook.ExplorerEvents_10_Event)this.explorer).Close -= Explorer_Close;
    6.94 +                    ((Outlook.ExplorerEvents_10_Event)this.explorer).InlineResponseClose -= Explorer_InlineResponseClose;
    6.95 +                }
    6.96 +            }
    6.97 +            catch (Exception ex)
    6.98 +            {
    6.99 +                Log.Error("ConnectWatchedExplorerEvents: Error occured. " + ex.ToString());
   6.100 +            }
   6.101 +        }
   6.102 +
   6.103 +        #endregion
   6.104 +
   6.105 +        #region Event Handling
   6.106 +        /**************************************************************
   6.107 +         * 
   6.108 +         * Event Handling
   6.109 +         * 
   6.110 +         *************************************************************/
   6.111 +
   6.112 +        /// <summary>
   6.113 +        /// Event handler for when a watched explorer is being closed.
   6.114 +        /// </summary>
   6.115 +        private void Explorer_Close()
   6.116 +        {
   6.117 +            Globals.ThisAddIn.RemoveFromWatchedExplorers(this);
   6.118 +            this.Dispose();
   6.119 +        }
   6.120 +
   6.121 +        /// <summary>
   6.122 +        /// Event handler for when an inline response is being closed.
   6.123 +        /// </summary>
   6.124 +        private void Explorer_InlineResponseClose()
   6.125 +        {
   6.126 +            Outlook.MailItem omi = null;
   6.127 +
   6.128 +            /* Create a new CryptableMailItem. This is needed so that its
   6.129 +             * MailItem_Write event gets called and the message will get saved
   6.130 +             * securely instead of to the server's draft folder.
   6.131 +             * Note: the form region's CMI is already disposed at this point,
   6.132 +             * so that its Write event will never be called.
   6.133 +             */ 
   6.134 +            try
   6.135 +            {
   6.136 +                omi = this.explorer?.ActiveInlineResponse as Outlook.MailItem;
   6.137 +
   6.138 +                if (omi != null)
   6.139 +                {
   6.140 +                    this.inlineResponseItem = new CryptableMailItem(omi, null, false);
   6.141 +                    this.inlineResponseItem.IsInlineResponse = true;
   6.142 +                }
   6.143 +            }
   6.144 +            catch (Exception ex)
   6.145 +            {
   6.146 +                Log.Error("WatchedExplorer_InlineResponseClose: Error setting new inline response item. " + ex.ToString());
   6.147 +            }
   6.148 +            finally
   6.149 +            {
   6.150 +                omi = null;
   6.151 +            }
   6.152 +        }
   6.153 +
   6.154 +        #endregion
   6.155 +    }
   6.156 +}
     7.1 --- a/pEpForOutlook.csproj	Fri Jul 13 10:24:14 2018 +0200
     7.2 +++ b/pEpForOutlook.csproj	Mon Jul 16 12:36:58 2018 +0200
     7.3 @@ -443,6 +443,7 @@
     7.4        <DependentUpon>FormControlManagePrivacyStatus.xaml</DependentUpon>
     7.5      </Compile>
     7.6      <Compile Include="UI\ValueConverters.cs" />
     7.7 +    <Compile Include="Wrappers\WatchedExplorer.cs" />
     7.8      <EmbeddedResource Include="Properties\Resources.hi.resx">
     7.9        <Generator>PublicResXFileCodeGenerator</Generator>
    7.10        <LastGenOutput>Resources.hi.Designer.cs</LastGenOutput>