mirror of
				https://github.com/Kopano-dev/kopano-ol-extension.git
				synced 2023-10-10 11:37:40 +00:00 
			
		
		
		
	Cleaned up account checking
This commit is contained in:
		@@ -280,6 +280,7 @@
 | 
			
		||||
    <Compile Include="Native\IOleWindow.cs" />
 | 
			
		||||
    <Compile Include="OutlookConstants.cs" />
 | 
			
		||||
    <Compile Include="Stubs\Enums.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IAccount.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IAddIn.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IAddressEntry.cs" />
 | 
			
		||||
    <Compile Include="Stubs\ICommandBars.cs" />
 | 
			
		||||
@@ -288,7 +289,9 @@
 | 
			
		||||
    <Compile Include="Stubs\IItemEvents.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IOutlookWindow.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IRecipient.cs" />
 | 
			
		||||
    <Compile Include="Stubs\IStores.cs" />
 | 
			
		||||
    <Compile Include="Stubs\ISyncObject.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\AccountWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\AddInWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\AddressEntryWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\CommandBarsWrapper.cs" />
 | 
			
		||||
@@ -296,6 +299,7 @@
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\ItemEventsWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\OutlookItemWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\RecipientWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\StoresWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\OutlookWrappers\SyncObjectWrapper.cs" />
 | 
			
		||||
    <Compile Include="Stubs\Wrappers.cs" />
 | 
			
		||||
    <Compile Include="UI\Outlook\OutlookImageList.cs" />
 | 
			
		||||
 
 | 
			
		||||
@@ -103,7 +103,7 @@ namespace Acacia.Features.FreeBusy
 | 
			
		||||
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                RegistryUtil.SetConfigValue(Name, REG_DEFAULTACCOUNT, value == null ? "" : value.SmtpAddress, RegistryValueKind.String);
 | 
			
		||||
                RegistryUtil.SetConfigValue(Name, REG_DEFAULTACCOUNT, value == null ? "" : value.Account.SmtpAddress, RegistryValueKind.String);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ using System.ComponentModel;
 | 
			
		||||
using System.Windows.Forms;
 | 
			
		||||
using Acacia.UI;
 | 
			
		||||
using static Acacia.DebugOptions;
 | 
			
		||||
using Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Features.GAB
 | 
			
		||||
{
 | 
			
		||||
@@ -474,7 +473,7 @@ namespace Acacia.Features.GAB
 | 
			
		||||
        private void AccountDiscovered(ZPushAccount zpush)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.Instance.Info(this, "Account discovered: {0}", zpush.DisplayName);
 | 
			
		||||
            _domains.Add(zpush.DomainName);
 | 
			
		||||
            _domains.Add(zpush.Account.DomainName);
 | 
			
		||||
 | 
			
		||||
            zpush.ConfirmedChanged += (z) =>
 | 
			
		||||
            {
 | 
			
		||||
@@ -606,7 +605,7 @@ namespace Acacia.Features.GAB
 | 
			
		||||
        private void RegisterGABAccount(ZPushAccount account, IFolder folder)
 | 
			
		||||
        {
 | 
			
		||||
            // Determine the domain name
 | 
			
		||||
            string domain = account.DomainName;
 | 
			
		||||
            string domain = account.Account.DomainName;
 | 
			
		||||
 | 
			
		||||
            // Could already be registered if there are multiple accounts on the same domain
 | 
			
		||||
            GABHandler gab;
 | 
			
		||||
@@ -637,7 +636,7 @@ namespace Acacia.Features.GAB
 | 
			
		||||
 | 
			
		||||
        private void ZPushChannelAvailable(IFolder folder)
 | 
			
		||||
        {
 | 
			
		||||
            using (IStore store = folder.Store)
 | 
			
		||||
            using (IStore store = folder.GetStore())
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Debug(this, "Z-Push channel available: {0} on {1}", folder, store.DisplayName);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@ namespace Acacia.Features.GAB
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                using(IStore store = Folder.Store)
 | 
			
		||||
                using(IStore store = Folder.GetStore())
 | 
			
		||||
                    return store.DisplayName;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -232,7 +232,7 @@ namespace Acacia.Features.OutOfOffice
 | 
			
		||||
            if (oof.State != ActiveSync.OOFState.Disabled)
 | 
			
		||||
            {
 | 
			
		||||
                if (MessageBox.Show(
 | 
			
		||||
                                string.Format(Properties.Resources.OOFStartup_Message, account.SmtpAddress),
 | 
			
		||||
                                string.Format(Properties.Resources.OOFStartup_Message, account.Account.SmtpAddress),
 | 
			
		||||
                                Properties.Resources.OOFStartup_Title,
 | 
			
		||||
                                MessageBoxButtons.YesNo,
 | 
			
		||||
                                MessageBoxIcon.Question
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ namespace Acacia.Features.OutOfOffice
 | 
			
		||||
            InitializeComponent();
 | 
			
		||||
 | 
			
		||||
            // Add the email address to the title
 | 
			
		||||
            Text = string.Format(Text, account.SmtpAddress);
 | 
			
		||||
            Text = string.Format(Text, account.Account.SmtpAddress);
 | 
			
		||||
 | 
			
		||||
            // Set the time formats
 | 
			
		||||
            timeFrom.CustomFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ namespace Acacia.Features.SendAs
 | 
			
		||||
        private void MailEvents_Respond(IMailItem mail, IMailItem response)
 | 
			
		||||
        {
 | 
			
		||||
            Logger.Instance.Trace(this, "Responding to mail, checking");
 | 
			
		||||
            using (IStore store = mail.Store)
 | 
			
		||||
            using (IStore store = mail.GetStore())
 | 
			
		||||
            {
 | 
			
		||||
                ZPushAccount zpush = Watcher.Accounts.GetAccount(store);
 | 
			
		||||
                Logger.Instance.Trace(this, "Checking ZPush: {0}", zpush);
 | 
			
		||||
@@ -114,13 +114,13 @@ namespace Acacia.Features.SendAs
 | 
			
		||||
 | 
			
		||||
        private void MailEvents_ItemSend(IMailItem item, ref bool cancel)
 | 
			
		||||
        {
 | 
			
		||||
            using (IStore store = item.Store)
 | 
			
		||||
            using (IStore store = item.GetStore())
 | 
			
		||||
            {
 | 
			
		||||
                ZPushAccount zpush = Watcher.Accounts.GetAccount(store);
 | 
			
		||||
                if (zpush != null)
 | 
			
		||||
                {
 | 
			
		||||
                    string address = item.SenderEmailAddress;
 | 
			
		||||
                    if (address != null && address != zpush.SmtpAddress)
 | 
			
		||||
                    if (address != null && address != zpush.Account.SmtpAddress)
 | 
			
		||||
                    {
 | 
			
		||||
                        Logger.Instance.Trace(this, "SendAs: {0}: {1}", address, item.SenderName);
 | 
			
		||||
                        item.SetProperty(Constants.ZPUSH_SEND_AS, address);
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ namespace Acacia.Features.SharedFolders
 | 
			
		||||
                ).Images;
 | 
			
		||||
 | 
			
		||||
            // Add the email address to the title
 | 
			
		||||
            Text = string.Format(Text, account.SmtpAddress);
 | 
			
		||||
            Text = string.Format(Text, account.Account.SmtpAddress);
 | 
			
		||||
 | 
			
		||||
            // Set up options
 | 
			
		||||
            ShowOptions(new KTreeNode[0]);
 | 
			
		||||
 
 | 
			
		||||
@@ -100,15 +100,15 @@ namespace Acacia.Features.WebApp
 | 
			
		||||
            // Perform a cached auto discover
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Debug(this, "Starting kdiscover: {0}", account.DomainName);
 | 
			
		||||
                Logger.Instance.Debug(this, "Starting kdiscover: {0}", account.Account.DomainName);
 | 
			
		||||
                string url = PerformAutoDiscover(account);
 | 
			
		||||
                Logger.Instance.Debug(this, "Finished kdiscover: {0}: {1}", account.DomainName, url);
 | 
			
		||||
                Logger.Instance.Debug(this, "Finished kdiscover: {0}: {1}", account.Account.DomainName, url);
 | 
			
		||||
                account.SetFeatureData(this, TXT_KDISCOVER, new URLCached(url));
 | 
			
		||||
                return url;
 | 
			
		||||
            }
 | 
			
		||||
            catch (System.Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Warning(this, "Exception during kdiscover: {0}: {1}", account.DomainName, e);
 | 
			
		||||
                Logger.Instance.Warning(this, "Exception during kdiscover: {0}: {1}", account.Account.DomainName, e);
 | 
			
		||||
                account.SetFeatureData(this, TXT_KDISCOVER, null);
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
@@ -117,7 +117,7 @@ namespace Acacia.Features.WebApp
 | 
			
		||||
        private string PerformAutoDiscover(ZPushAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            // Fetch the txt record
 | 
			
		||||
            IList<string> txt = DnsUtil.GetTxtRecord(account.DomainName);
 | 
			
		||||
            IList<string> txt = DnsUtil.GetTxtRecord(account.Account.DomainName);
 | 
			
		||||
            if (txt == null)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -45,4 +45,11 @@ namespace Acacia.Stubs
 | 
			
		||||
        ManagedEmail = 29,
 | 
			
		||||
        SuggestedContacts = 30
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public enum AccountType
 | 
			
		||||
    {
 | 
			
		||||
        // TODO
 | 
			
		||||
        EAS,
 | 
			
		||||
        Other
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IAccount.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Security;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs
 | 
			
		||||
{
 | 
			
		||||
    public interface IAccount : IDisposable
 | 
			
		||||
    {
 | 
			
		||||
        AccountType AccountType { get; }
 | 
			
		||||
 | 
			
		||||
        IStore Store { get; }
 | 
			
		||||
 | 
			
		||||
        string DisplayName { get; }
 | 
			
		||||
 | 
			
		||||
        string SmtpAddress { get; }
 | 
			
		||||
 | 
			
		||||
        string UserName { get; }
 | 
			
		||||
 | 
			
		||||
        string ServerURL { get; }
 | 
			
		||||
 | 
			
		||||
        string DeviceId { get; }
 | 
			
		||||
 | 
			
		||||
        SecureString Password { get; }
 | 
			
		||||
 | 
			
		||||
        bool HasPassword { get; }
 | 
			
		||||
 | 
			
		||||
        string StoreID { get; }
 | 
			
		||||
 | 
			
		||||
        string DomainName { get; }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -44,9 +44,9 @@ namespace Acacia.Stubs
 | 
			
		||||
        // TODO: clean this up
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sends and receives all accounts.
 | 
			
		||||
        /// Sends and receives all accounts, or a specific account.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        void SendReceive();
 | 
			
		||||
        void SendReceive(IAccount account = null);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Restarts the application
 | 
			
		||||
@@ -63,12 +63,13 @@ namespace Acacia.Stubs
 | 
			
		||||
 | 
			
		||||
        IRecipient ResolveRecipient(string name);
 | 
			
		||||
 | 
			
		||||
        IStore AddFileStore(string path);
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the stores. The caller is responsible for disposing.
 | 
			
		||||
        /// Returns the store manager. This is a shared object and must NOT be disposed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IEnumerable<IStore> Stores { get; }
 | 
			
		||||
        IStores Stores
 | 
			
		||||
        {
 | 
			
		||||
            get;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -42,14 +42,13 @@ namespace Acacia.Stubs
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the store. The owner is responsible for disposing. 
 | 
			
		||||
        /// TODO: make method to make disposing clear
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IStore Store { get; }
 | 
			
		||||
        IStore GetStore();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Quick accessor to Store.Id, to prevent allocating a wrapper for it.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        string StoreId { get; }
 | 
			
		||||
        string StoreID { get; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Quick accessor to Store.DisplayName, to prevent allocating a wrapper for it.
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NSOutlook = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
using NSOutlookDelegates = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs
 | 
			
		||||
{
 | 
			
		||||
@@ -12,32 +12,32 @@ namespace Acacia.Stubs
 | 
			
		||||
        #region Event handlers
 | 
			
		||||
 | 
			
		||||
        // TODO: custom delegates
 | 
			
		||||
        event NSOutlook.ItemEvents_10_AfterWriteEventHandler AfterWrite;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_AttachmentAddEventHandler AttachmentAdd;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_AttachmentReadEventHandler AttachmentRead;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_AttachmentRemoveEventHandler AttachmentRemove;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAttachmentAddEventHandler BeforeAttachmentAdd;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAttachmentPreviewEventHandler BeforeAttachmentPreview;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAttachmentReadEventHandler BeforeAttachmentRead;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAttachmentSaveEventHandler BeforeAttachmentSave;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAttachmentWriteToTempFileEventHandler BeforeAttachmentWriteToTempFile;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeAutoSaveEventHandler BeforeAutoSave;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeCheckNamesEventHandler BeforeCheckNames;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeDeleteEventHandler BeforeDelete;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_BeforeReadEventHandler BeforeRead;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_CloseEventHandler Close;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_CustomActionEventHandler CustomAction;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_CustomPropertyChangeEventHandler CustomPropertyChange;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_ForwardEventHandler Forward;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_OpenEventHandler Open;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_PropertyChangeEventHandler PropertyChange;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_ReadEventHandler Read;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_ReadCompleteEventHandler ReadComplete;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_ReplyEventHandler Reply;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_ReplyAllEventHandler ReplyAll;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_SendEventHandler Send;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_UnloadEventHandler Unload;
 | 
			
		||||
        event NSOutlook.ItemEvents_10_WriteEventHandler Write;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_AfterWriteEventHandler AfterWrite;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_AttachmentAddEventHandler AttachmentAdd;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_AttachmentReadEventHandler AttachmentRead;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_AttachmentRemoveEventHandler AttachmentRemove;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAttachmentAddEventHandler BeforeAttachmentAdd;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAttachmentPreviewEventHandler BeforeAttachmentPreview;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAttachmentReadEventHandler BeforeAttachmentRead;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAttachmentSaveEventHandler BeforeAttachmentSave;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAttachmentWriteToTempFileEventHandler BeforeAttachmentWriteToTempFile;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeAutoSaveEventHandler BeforeAutoSave;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeCheckNamesEventHandler BeforeCheckNames;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeDeleteEventHandler BeforeDelete;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_BeforeReadEventHandler BeforeRead;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_CloseEventHandler Close;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_CustomActionEventHandler CustomAction;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_CustomPropertyChangeEventHandler CustomPropertyChange;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_ForwardEventHandler Forward;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_OpenEventHandler Open;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_PropertyChangeEventHandler PropertyChange;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_ReadEventHandler Read;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_ReadCompleteEventHandler ReadComplete;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_ReplyEventHandler Reply;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_ReplyAllEventHandler ReplyAll;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_SendEventHandler Send;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_UnloadEventHandler Unload;
 | 
			
		||||
        event NSOutlookDelegates.ItemEvents_10_WriteEventHandler Write;
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStores.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/IStores.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs
 | 
			
		||||
{
 | 
			
		||||
    public delegate void IStores_AccountDiscovered(IAccount account);
 | 
			
		||||
    public delegate void IStores_AccountRemoved(IAccount account);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Manages the stores and associated acounts.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IStores: IComWrapper, IEnumerable<IStore>
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the accounts. The accounts are shared objects and must not be disposed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        IEnumerable<IAccount> Accounts { get; }
 | 
			
		||||
 | 
			
		||||
        event IStores_AccountDiscovered AccountDiscovered;
 | 
			
		||||
        event IStores_AccountRemoved AccountRemoved;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adds a file store to the current collection. If the store is already in the collection, an exception is thrown.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="path">The path.</param>
 | 
			
		||||
        /// <returns>The store. The caller is responsible for disposing.</returns>
 | 
			
		||||
        IStore AddFileStore(string path);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NSOutlook = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
using NSOutlookDelegates = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs
 | 
			
		||||
{
 | 
			
		||||
@@ -25,10 +25,10 @@ namespace Acacia.Stubs
 | 
			
		||||
 | 
			
		||||
        #region Events
 | 
			
		||||
        // TODO: custom delegates
 | 
			
		||||
        event NSOutlook.SyncObjectEvents_OnErrorEventHandler OnError;
 | 
			
		||||
        event NSOutlook.SyncObjectEvents_ProgressEventHandler Progress;
 | 
			
		||||
        event NSOutlook.SyncObjectEvents_SyncEndEventHandler SyncEnd;
 | 
			
		||||
        event NSOutlook.SyncObjectEvents_SyncStartEventHandler SyncStart;
 | 
			
		||||
        event NSOutlookDelegates.SyncObjectEvents_OnErrorEventHandler OnError;
 | 
			
		||||
        event NSOutlookDelegates.SyncObjectEvents_ProgressEventHandler Progress;
 | 
			
		||||
        event NSOutlookDelegates.SyncObjectEvents_SyncEndEventHandler SyncEnd;
 | 
			
		||||
        event NSOutlookDelegates.SyncObjectEvents_SyncStartEventHandler SyncStart;
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,153 @@
 | 
			
		||||
using Acacia.Utils;
 | 
			
		||||
using Microsoft.Win32;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Security;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
{
 | 
			
		||||
    [TypeConverter(typeof(ExpandableObjectConverter))]
 | 
			
		||||
    class AccountWrapper : DisposableWrapper, IAccount, LogContext
 | 
			
		||||
    {
 | 
			
		||||
        private readonly string _regPath;
 | 
			
		||||
        private readonly IStore _store;
 | 
			
		||||
 | 
			
		||||
        internal AccountWrapper(string regPath, IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            this._regPath = regPath;
 | 
			
		||||
            this._store = store;
 | 
			
		||||
 | 
			
		||||
            // Cache the SmtpAddress, it is used as the key
 | 
			
		||||
            SmtpAddress = RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EMAIL, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void DoRelease()
 | 
			
		||||
        {
 | 
			
		||||
            _store.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public string LogContextId
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return "ZPushAccount(" + SmtpAddress + ")";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            return SmtpAddress;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Triggers an Outlook send/receive operation.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void SendReceive()
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: ThisAddIn.Instance.SendReceive();
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Properties
 | 
			
		||||
 | 
			
		||||
        public AccountType AccountType
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return (DeviceId == null) ? AccountType.Other : AccountType.EAS;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return _store;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DisplayName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_DISPLAYNAME, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string SmtpAddress
 | 
			
		||||
        {
 | 
			
		||||
            get;
 | 
			
		||||
            private set;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string UserName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_USERNAME, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ServerURL
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_SERVER, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DeviceId
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_DEVICEID, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public SecureString Password
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                byte[] encrypted = (byte[])Registry.GetValue(_regPath, OutlookConstants.REG_VAL_EAS_PASSWORD, null);
 | 
			
		||||
                return PasswordEncryption.Decrypt(encrypted);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public bool HasPassword
 | 
			
		||||
        {
 | 
			
		||||
            get { return Registry.GetValue(_regPath, OutlookConstants.REG_VAL_EAS_PASSWORD, null) != null; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get { return GetStoreId(_regPath); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string GetStoreId(string regPath)
 | 
			
		||||
        {
 | 
			
		||||
            return StringUtil.BytesToHex((byte[])Registry.GetValue(regPath, OutlookConstants.REG_VAL_EAS_STOREID, null));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DomainName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                int index = SmtpAddress.IndexOf('@');
 | 
			
		||||
                if (index < 0)
 | 
			
		||||
                    return SmtpAddress;
 | 
			
		||||
                else
 | 
			
		||||
                    return SmtpAddress.Substring(index + 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -17,17 +17,29 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
{
 | 
			
		||||
    public class AddInWrapper : IAddIn
 | 
			
		||||
    {
 | 
			
		||||
        private readonly NSOutlook.Application _app;
 | 
			
		||||
        private readonly ThisAddIn _thisAddIn;
 | 
			
		||||
        private NSOutlook.Application _app;
 | 
			
		||||
        private readonly StoresWrapper _stores;
 | 
			
		||||
 | 
			
		||||
        public AddInWrapper(ThisAddIn thisAddIn)
 | 
			
		||||
        {
 | 
			
		||||
            this._thisAddIn = thisAddIn;
 | 
			
		||||
            this._app = thisAddIn.Application;
 | 
			
		||||
 | 
			
		||||
            NSOutlook.NameSpace session = _app.Session;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                this._stores = new StoresWrapper(session.Stores);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ComRelease.Release(session);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SendReceive()
 | 
			
		||||
        public void SendReceive(IAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: send/receive specific account
 | 
			
		||||
            NSOutlook.NameSpace session = _app.Session;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@@ -39,6 +51,11 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Start()
 | 
			
		||||
        {
 | 
			
		||||
            _stores.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Restart()
 | 
			
		||||
        {
 | 
			
		||||
            // Can not use the assembly location, as that is in the GAC
 | 
			
		||||
@@ -224,35 +241,9 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore AddFileStore(string path)
 | 
			
		||||
        public IStores Stores
 | 
			
		||||
        {
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                NSOutlook.NameSpace session = com.Add(_app.Session);
 | 
			
		||||
                
 | 
			
		||||
                // Add the store
 | 
			
		||||
                session.AddStore(path);
 | 
			
		||||
 | 
			
		||||
                // And fetch it and wrap
 | 
			
		||||
                NSOutlook.Stores stores = com.Add(session.Stores);
 | 
			
		||||
                return Mapping.Wrap(stores[stores.Count]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<IStore> Stores
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.NameSpace session = com.Add(_app.Session);
 | 
			
		||||
                    NSOutlook.Stores stores = com.Add(session.Stores);
 | 
			
		||||
                    foreach (NSOutlook.Store store in stores)
 | 
			
		||||
                    {
 | 
			
		||||
                        yield return Mapping.Wrap(store);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            get { return _stores; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -116,19 +116,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -241,19 +241,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -257,19 +257,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -100,13 +100,13 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
 | 
			
		||||
        public string EntryID { get { return _item.EntryID; } }
 | 
			
		||||
 | 
			
		||||
        public IStore Store { get { return Mapping.Wrap(_item.Store); } }
 | 
			
		||||
        public IStore GetStore() { return Mapping.Wrap(_item.Store); }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                using (IStore store = Store)
 | 
			
		||||
                using (IStore store = GetStore())
 | 
			
		||||
                {
 | 
			
		||||
                    return store.StoreID;
 | 
			
		||||
                }
 | 
			
		||||
@@ -116,7 +116,7 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                using (IStore store = Store)
 | 
			
		||||
                using (IStore store = GetStore())
 | 
			
		||||
                {
 | 
			
		||||
                    return store.DisplayName;
 | 
			
		||||
                }
 | 
			
		||||
@@ -241,7 +241,7 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                using (IStore store = Store)
 | 
			
		||||
                using (IStore store = GetStore())
 | 
			
		||||
                {
 | 
			
		||||
                    return store.GetItemFromID(entryId);
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -150,19 +150,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -97,19 +97,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -95,19 +95,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,270 @@
 | 
			
		||||
using Acacia.Utils;
 | 
			
		||||
using Microsoft.Win32;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NSOutlook = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
{
 | 
			
		||||
    class StoresWrapper : ComWrapper<NSOutlook.Stores>, IStores
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Accounts indexed by store id. Null values are allowed, if a store has been
 | 
			
		||||
        /// determined to not be associated with an Account. This is required to determine when a store is new.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly Dictionary<string, AccountWrapper> _accountsByStoreId = new Dictionary<string, AccountWrapper>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Accounts indexed by SMTPAddress. Null values are not allowed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly Dictionary<string, AccountWrapper> _accountsBySmtp = new Dictionary<string, AccountWrapper>();
 | 
			
		||||
 | 
			
		||||
        public StoresWrapper(NSOutlook.Stores item) : base(item)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Events
 | 
			
		||||
 | 
			
		||||
        public event IStores_AccountDiscovered AccountDiscovered;
 | 
			
		||||
        public event IStores_AccountRemoved AccountRemoved;
 | 
			
		||||
        
 | 
			
		||||
        private void OnAccountDiscovered(AccountWrapper account)
 | 
			
		||||
        {
 | 
			
		||||
            AccountDiscovered?.Invoke(account);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnAccountRemoved(AccountWrapper account)
 | 
			
		||||
        {
 | 
			
		||||
            AccountRemoved?.Invoke(account);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Implementation
 | 
			
		||||
 | 
			
		||||
        public void Start()
 | 
			
		||||
        {
 | 
			
		||||
            // Check existing stores
 | 
			
		||||
            // TODO: do this in background?
 | 
			
		||||
            foreach(NSOutlook.Store store in _item)
 | 
			
		||||
            {
 | 
			
		||||
                StoreAdded(store);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Register for new stores
 | 
			
		||||
            // The store remove event is not sent, so don't bother registering for that
 | 
			
		||||
            _item.StoreAdd += StoreAdded;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (GlobalOptions.INSTANCE.AccountTimer)
 | 
			
		||||
            {
 | 
			
		||||
                // Set up timer to check for removed accounts
 | 
			
		||||
                Util.Timed(null, Config.ACCOUNT_CHECK_INTERVAL, CheckAccountsRemoved);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Event handler for Stores.StoreAdded event.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void StoreAdded(NSOutlook.Store s)
 | 
			
		||||
        {
 | 
			
		||||
            IStore store = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Accessing the store object causes random crashes, simply iterate to find new stores
 | 
			
		||||
                Logger.Instance.Trace(this, "StoreAdded: {0}", s.StoreID);
 | 
			
		||||
                foreach (NSOutlook.Store rawStore in _item)
 | 
			
		||||
                {
 | 
			
		||||
                    if (!_accountsByStoreId.ContainsKey(rawStore.StoreID))
 | 
			
		||||
                    {
 | 
			
		||||
                        store = new StoreWrapper(rawStore);
 | 
			
		||||
                        Logger.Instance.Trace(this, "New store: {0}", rawStore.DisplayName);
 | 
			
		||||
                        AccountWrapper account = TryCreateFromRegistry(store);
 | 
			
		||||
                        if (account == null)
 | 
			
		||||
                        {
 | 
			
		||||
                            // Add it to the cache so it is not evaluated again.
 | 
			
		||||
                            _accountsByStoreId.Add(store.StoreID, null);
 | 
			
		||||
                            Logger.Instance.Trace(this, "Not an account store: {0}", store.DisplayName);
 | 
			
		||||
                            store.Dispose();
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            // Account has taken ownership of the store
 | 
			
		||||
                            Logger.Instance.Trace(this, "New account store: {0}: {1}", store.DisplayName, account);
 | 
			
		||||
                            OnAccountDiscovered(account);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else ComRelease.Release(rawStore);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (System.Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Error(this, "StoreAdded Exception: {0}", e);
 | 
			
		||||
                if (store != null)
 | 
			
		||||
                    store.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void CheckAccountsRemoved()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Collect all the store ids
 | 
			
		||||
                HashSet<string> stores = new HashSet<string>();
 | 
			
		||||
                foreach (NSOutlook.Store store in _item)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        stores.Add(store.StoreID);
 | 
			
		||||
                    }
 | 
			
		||||
                    finally
 | 
			
		||||
                    {
 | 
			
		||||
                        ComRelease.Release(store);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Check if any relevant ones are removed
 | 
			
		||||
                List<KeyValuePair<string, AccountWrapper>> removed = new List<KeyValuePair<string, AccountWrapper>>();
 | 
			
		||||
                foreach (KeyValuePair<string, AccountWrapper> account in _accountsByStoreId)
 | 
			
		||||
                {
 | 
			
		||||
                    if (!stores.Contains(account.Key))
 | 
			
		||||
                    {
 | 
			
		||||
                        Logger.Instance.Trace(this, "Store not found: {0} - {1}", account.Value, account.Key);
 | 
			
		||||
                        removed.Add(account);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Process any removed stores
 | 
			
		||||
                foreach (KeyValuePair<string, AccountWrapper> remove in removed)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger.Instance.Debug(this, "Account removed: {0} - {1}", remove.Value, remove.Key);
 | 
			
		||||
                    _accountsBySmtp.Remove(remove.Value.SmtpAddress);
 | 
			
		||||
                    _accountsByStoreId.Remove(remove.Key);
 | 
			
		||||
                    OnAccountRemoved(remove.Value);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (System.Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Error(this, "Exception in CheckAccountsRemoved: {0}", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Public interface
 | 
			
		||||
 | 
			
		||||
        public IStore AddFileStore(string path)
 | 
			
		||||
        {
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                NSOutlook.NameSpace session = com.Add(_item.Session);
 | 
			
		||||
 | 
			
		||||
                // Add the store
 | 
			
		||||
                session.AddStore(path);
 | 
			
		||||
 | 
			
		||||
                // And fetch it and wrap
 | 
			
		||||
                return Mapping.Wrap(_item[_item.Count]);
 | 
			
		||||
            }
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerator<IStore> GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (NSOutlook.Store store in _item)
 | 
			
		||||
            {
 | 
			
		||||
                yield return Mapping.Wrap(store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        IEnumerator IEnumerable.GetEnumerator()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (NSOutlook.Store store in _item)
 | 
			
		||||
            {
 | 
			
		||||
                yield return Mapping.Wrap(store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<IAccount> Accounts
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return _accountsBySmtp.Values;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Registry
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates the AccountWrapper for the store, from the registry.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="store">The store. Ownership is transferred to the AccountWrapper. If the account is not created, the store is NOT disposed</param>
 | 
			
		||||
        /// <returns>The AccountWrapper, or null if no account is associated with the store</returns>
 | 
			
		||||
        private AccountWrapper TryCreateFromRegistry(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            using (RegistryKey baseKey = FindRegistryKey(store))
 | 
			
		||||
            {
 | 
			
		||||
                if (baseKey == null)
 | 
			
		||||
                    return null;
 | 
			
		||||
                AccountWrapper account = new AccountWrapper(baseKey.Name, store);
 | 
			
		||||
                Register(account);
 | 
			
		||||
                return account;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Register(AccountWrapper account)
 | 
			
		||||
        {
 | 
			
		||||
            // Register the new account
 | 
			
		||||
            _accountsBySmtp.Add(account.SmtpAddress, account);
 | 
			
		||||
            _accountsByStoreId.Add(account.StoreID, account);
 | 
			
		||||
            Logger.Instance.Trace(this, "Account registered: {0} -> {1}", account.DisplayName, account.StoreID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Finds the registry key for the account associated with the store.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The registry key, or null if it cannot be found</returns>
 | 
			
		||||
        private RegistryKey FindRegistryKey(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            // Find the registry key by store id
 | 
			
		||||
            using (RegistryKey key = OpenBaseKey())
 | 
			
		||||
            {
 | 
			
		||||
                if (key != null)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (string subkey in key.GetSubKeyNames())
 | 
			
		||||
                    {
 | 
			
		||||
                        RegistryKey accountKey = key.OpenSubKey(subkey);
 | 
			
		||||
                        string storeId = AccountWrapper.GetStoreId(accountKey.Name);
 | 
			
		||||
                        if (storeId != null && storeId == store.StoreID)
 | 
			
		||||
                        {
 | 
			
		||||
                            return accountKey;
 | 
			
		||||
                        }
 | 
			
		||||
                        accountKey.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private RegistryKey OpenBaseKey()
 | 
			
		||||
        {
 | 
			
		||||
            NSOutlook.NameSpace session = _item.Session;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                string path = string.Format(OutlookConstants.REG_SUBKEY_ACCOUNTS, session.CurrentProfileName);
 | 
			
		||||
                return OutlookRegistryUtils.OpenOutlookKey(path);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ComRelease.Release(session);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -95,19 +95,16 @@ namespace Acacia.Stubs.OutlookWrappers
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        public IStore GetStore()
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                {
 | 
			
		||||
                    NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                    return Mapping.Wrap(parent?.Store);
 | 
			
		||||
                }
 | 
			
		||||
                NSOutlook.Folder parent = com.Add(_item.Parent);
 | 
			
		||||
                return Mapping.Wrap(parent?.Store);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreId
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -146,7 +146,10 @@ namespace Acacia
 | 
			
		||||
 | 
			
		||||
                // Start watching events
 | 
			
		||||
                if (DebugOptions.GetOption(null, DebugOptions.WATCHER_ENABLED))
 | 
			
		||||
                {
 | 
			
		||||
                    ((AddInWrapper)Instance).Start();
 | 
			
		||||
                    Watcher.Start();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Done
 | 
			
		||||
                Logger.Instance.Debug(this, "Startup done");
 | 
			
		||||
 
 | 
			
		||||
@@ -88,5 +88,44 @@ namespace Acacia.Utils
 | 
			
		||||
                GC.WaitForPendingFinalizers();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region Timers
 | 
			
		||||
 | 
			
		||||
        public static void Delayed(LogContext log, int millis, System.Action action)
 | 
			
		||||
        {
 | 
			
		||||
            RegisterTimer(log, millis, action, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Timed(LogContext log, int millis, System.Action action)
 | 
			
		||||
        {
 | 
			
		||||
            RegisterTimer(log, millis, action, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void RegisterTimer(LogContext log, int millis, System.Action action, bool repeat)
 | 
			
		||||
        {
 | 
			
		||||
            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
 | 
			
		||||
            timer.Interval = millis;
 | 
			
		||||
            timer.Tick += (s, eargs) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    action();
 | 
			
		||||
                    if (!repeat)
 | 
			
		||||
                    {
 | 
			
		||||
                        timer.Enabled = false;
 | 
			
		||||
                        timer.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (System.Exception e)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger.Instance.Trace(log, "Exception in timer: {0}", e);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            timer.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -147,9 +147,9 @@ namespace Acacia.ZPush.Connect
 | 
			
		||||
            // TODO: it would be nice to let the system handle the SecureString for the password. However,
 | 
			
		||||
            //       when specifying credentials for an HttpClient, they are only used after a 401 is received
 | 
			
		||||
            //       on the first request, basically doubling the number of requests.
 | 
			
		||||
            using (SecureString pass = _account.Password)
 | 
			
		||||
            using (SecureString pass = _account.Account.Password)
 | 
			
		||||
            {
 | 
			
		||||
                var byteArray = Encoding.UTF8.GetBytes(_account.UserName + ":" + pass.ConvertToUnsecureString());
 | 
			
		||||
                var byteArray = Encoding.UTF8.GetBytes(_account.Account.UserName + ":" + pass.ConvertToUnsecureString());
 | 
			
		||||
                var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
 | 
			
		||||
                _client.DefaultRequestHeaders.Authorization = header;
 | 
			
		||||
            }
 | 
			
		||||
@@ -278,8 +278,8 @@ namespace Acacia.ZPush.Connect
 | 
			
		||||
 | 
			
		||||
            public Response Execute(ActiveSync.RequestBase request)
 | 
			
		||||
            {
 | 
			
		||||
                string url = string.Format(ACTIVESYNC_URL, _account.ServerURL, _account.DeviceId,
 | 
			
		||||
                    request.Command, _account.UserName, "WindowsOutlook");
 | 
			
		||||
                string url = string.Format(ACTIVESYNC_URL, _account.Account.ServerURL, _account.Account.DeviceId,
 | 
			
		||||
                    request.Command, _account.Account.UserName, "WindowsOutlook");
 | 
			
		||||
 | 
			
		||||
                // Construct the body
 | 
			
		||||
                WBXMLDocument doc = new WBXMLDocument();
 | 
			
		||||
@@ -291,10 +291,10 @@ namespace Acacia.ZPush.Connect
 | 
			
		||||
 | 
			
		||||
                using (HttpContent content = new ByteArrayContent(contentBody))
 | 
			
		||||
                {
 | 
			
		||||
                    Logger.Instance.Trace(this, "Sending request: {0} -> {1}", _account.ServerURL, doc.ToXMLString());
 | 
			
		||||
                    Logger.Instance.Trace(this, "Sending request: {0} -> {1}", _account.Account.ServerURL, doc.ToXMLString());
 | 
			
		||||
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-sync.wbxml");
 | 
			
		||||
                    string caps = ZPushCapabilities.Client.ToString();
 | 
			
		||||
                    Logger.Instance.Trace(this, "Sending request: {0} -> {1}: {2}", _account.ServerURL, caps, doc.ToXMLString());
 | 
			
		||||
                    Logger.Instance.Trace(this, "Sending request: {0} -> {1}: {2}", _account.Account.ServerURL, caps, doc.ToXMLString());
 | 
			
		||||
                    content.Headers.Add(Constants.ZPUSH_HEADER_CLIENT_CAPABILITIES, caps);
 | 
			
		||||
                    using (HttpResponseMessage response = _client.PostAsync(url, content, _cancel).Result)
 | 
			
		||||
                    {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,14 +46,14 @@ namespace Acacia.ZPush.Connect
 | 
			
		||||
        public ResponseType Execute<ResponseType>(SoapRequest<ResponseType> request)
 | 
			
		||||
        {
 | 
			
		||||
            // Create the url
 | 
			
		||||
            string url = string.Format(ACTIVESYNC_URL, _connection.Account.ServerURL, "webservice",
 | 
			
		||||
            string url = string.Format(ACTIVESYNC_URL, _connection.Account.Account.ServerURL, "webservice",
 | 
			
		||||
                    ServiceName,
 | 
			
		||||
                    // TODO: this username is a bit of a quick hack. 
 | 
			
		||||
                    request.UserName ?? _connection.Account.UserName,
 | 
			
		||||
                    request.UserName ?? _connection.Account.Account.UserName,
 | 
			
		||||
                    "webservice");
 | 
			
		||||
 | 
			
		||||
            // Set up the encoding
 | 
			
		||||
            SoapRequestEncoder encoder = new SoapRequestEncoder(_connection.Account.ServerURL, ServiceParameters, request);
 | 
			
		||||
            SoapRequestEncoder encoder = new SoapRequestEncoder(_connection.Account.Account.ServerURL, ServiceParameters, request);
 | 
			
		||||
            encoder.ServiceName = ServiceName;
 | 
			
		||||
 | 
			
		||||
            // Execute the request
 | 
			
		||||
@@ -85,7 +85,7 @@ namespace Acacia.ZPush.Connect
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                SoapParameters parameters = new SoapParameters();
 | 
			
		||||
                parameters.Add("devid", _connection.Account.DeviceId.ToLower());
 | 
			
		||||
                parameters.Add("devid", _connection.Account.Account.DeviceId.ToLower());
 | 
			
		||||
                return parameters;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,143 +32,41 @@ using System.Threading.Tasks;
 | 
			
		||||
namespace Acacia.ZPush
 | 
			
		||||
{
 | 
			
		||||
    [TypeConverter(typeof(ExpandableObjectConverter))]
 | 
			
		||||
    public class ZPushAccount : DisposableWrapper, LogContext
 | 
			
		||||
    public class ZPushAccount : LogContext
 | 
			
		||||
    {
 | 
			
		||||
        #region Miscellaneous
 | 
			
		||||
 | 
			
		||||
        private readonly string _regPath;
 | 
			
		||||
        private readonly IAccount _account;
 | 
			
		||||
 | 
			
		||||
        private readonly IStore _store;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Constructor.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="regPath">They registry key containing the account settings.</param>
 | 
			
		||||
        /// <param name="store">The store this account represents. The new object takes ownership</param>
 | 
			
		||||
        internal ZPushAccount(string regPath, IStore store)
 | 
			
		||||
        internal ZPushAccount(IAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            this._regPath = regPath;
 | 
			
		||||
            this._store = store;
 | 
			
		||||
 | 
			
		||||
            // Cache the SmtpAddress, it is used as the key
 | 
			
		||||
            SmtpAddress = RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EMAIL, null);
 | 
			
		||||
            this._account = account;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void DoRelease()
 | 
			
		||||
        {
 | 
			
		||||
            _store.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public IAccount Account { get { return _account; } }
 | 
			
		||||
        public String DisplayName { get { return _account.DisplayName; } }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public string LogContextId
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return "ZPushAccount(" + SmtpAddress + ")";
 | 
			
		||||
                return "ZPushAccount(" + _account.SmtpAddress + ")";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
        {
 | 
			
		||||
            return SmtpAddress;
 | 
			
		||||
            return _account.SmtpAddress;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Triggers an Outlook send/receive operation.
 | 
			
		||||
        /// Triggers an Outlook send/receive operation for this account.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void SendReceive()
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: ThisAddIn.Instance.SendReceive();
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Properties
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public IStore Store
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return _store;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DisplayName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_DISPLAYNAME, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string SmtpAddress
 | 
			
		||||
        {
 | 
			
		||||
            get;
 | 
			
		||||
            private set;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string UserName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_USERNAME, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string ServerURL
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_SERVER, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DeviceId
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return RegistryUtil.GetValueString(_regPath, OutlookConstants.REG_VAL_EAS_DEVICEID, null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public SecureString Password
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                byte[] encrypted = (byte[])Registry.GetValue(_regPath, OutlookConstants.REG_VAL_EAS_PASSWORD, null);
 | 
			
		||||
                return PasswordEncryption.Decrypt(encrypted);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Browsable(false)]
 | 
			
		||||
        public bool HasPassword
 | 
			
		||||
        {
 | 
			
		||||
            get { return Registry.GetValue(_regPath, OutlookConstants.REG_VAL_EAS_PASSWORD, null) != null; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string StoreID
 | 
			
		||||
        {
 | 
			
		||||
            get { return GetStoreId(_regPath); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static string GetStoreId(string regPath)
 | 
			
		||||
        {
 | 
			
		||||
            return StringUtil.BytesToHex((byte[])Registry.GetValue(regPath, OutlookConstants.REG_VAL_EAS_STOREID, null));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string DomainName
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                int index = SmtpAddress.IndexOf('@');
 | 
			
		||||
                if (index < 0)
 | 
			
		||||
                    return SmtpAddress;
 | 
			
		||||
                else
 | 
			
		||||
                    return SmtpAddress.Substring(index + 1);
 | 
			
		||||
            }
 | 
			
		||||
            ThisAddIn.Instance.SendReceive(Account);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -23,21 +23,19 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NSOutlook = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.ZPush
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Maintains the mapping from Outlook accounts to ZPush accounts, which
 | 
			
		||||
    /// provide additional functionality and workarounds.
 | 
			
		||||
    /// TODO: split into Outlook and Z-Push specific parts
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ZPushAccounts
 | 
			
		||||
    public class ZPushAccounts : DisposableWrapper
 | 
			
		||||
    {
 | 
			
		||||
        private readonly ZPushWatcher _watcher;
 | 
			
		||||
        // TODO: wrap these
 | 
			
		||||
        private readonly NSOutlook.Application _app;
 | 
			
		||||
        private readonly NSOutlook.NameSpace _session;
 | 
			
		||||
        private readonly NSOutlook.Stores _stores;
 | 
			
		||||
        private readonly IAddIn _addIn;
 | 
			
		||||
        private readonly IStores _stores;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// ZPushAccounts indexed by SMTPAddress. Null values are not allowed.
 | 
			
		||||
@@ -45,351 +43,126 @@ namespace Acacia.ZPush
 | 
			
		||||
        private readonly Dictionary<string, ZPushAccount> _accountsBySmtp = new Dictionary<string, ZPushAccount>();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// ZPushAccounts indexed by store id. Null values are allowed, if a store has been
 | 
			
		||||
        /// determined to not be associated with a ZPushAccount. This is required to determine when a store is new.
 | 
			
		||||
        /// ZPushAccounts indexed by store id. Null values are noy allowed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private readonly Dictionary<string, ZPushAccount> _accountsByStoreId = new Dictionary<string, ZPushAccount>();
 | 
			
		||||
 | 
			
		||||
        public ZPushAccounts(ZPushWatcher watcher, NSOutlook.Application app)
 | 
			
		||||
        public ZPushAccounts(ZPushWatcher watcher, IAddIn addIn)
 | 
			
		||||
        {
 | 
			
		||||
            this._watcher = watcher;
 | 
			
		||||
            this._app = app;
 | 
			
		||||
            this._session = app.Session;
 | 
			
		||||
            this._stores = _session.Stores;
 | 
			
		||||
            this._addIn = addIn;
 | 
			
		||||
            this._stores = addIn.Stores;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Start()
 | 
			
		||||
        protected override void DoRelease()
 | 
			
		||||
        {
 | 
			
		||||
            // Register for new stores
 | 
			
		||||
            // The store remove event is not sent, so don't register for that
 | 
			
		||||
            _stores.StoreAdd += StoreAdded;
 | 
			
		||||
            _stores.Dispose();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Implementation
 | 
			
		||||
 | 
			
		||||
        public void Start()
 | 
			
		||||
        {
 | 
			
		||||
            if (GlobalOptions.INSTANCE.ZPushCheck)
 | 
			
		||||
            {
 | 
			
		||||
                // Process existing accounts
 | 
			
		||||
                using (ComRelease com = new ComRelease())
 | 
			
		||||
                    foreach (NSOutlook.Account account in com.Add(_session.Accounts))
 | 
			
		||||
                foreach (IAccount account in _stores.Accounts)
 | 
			
		||||
                {
 | 
			
		||||
                    Tasks.Task(null, "AccountCheck", () =>
 | 
			
		||||
                    {
 | 
			
		||||
                        Tasks.Task(null, "AccountCheck", () =>
 | 
			
		||||
                        {
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                // TODO: check if EAS account
 | 
			
		||||
                                // account gets released by GetAccount, save DisplayName for log purposes.
 | 
			
		||||
                                string displayName = account.DisplayName;
 | 
			
		||||
                                Logger.Instance.Trace(this, "Checking account: {0}", displayName);
 | 
			
		||||
                                ZPushAccount zpush = GetAccount(account);
 | 
			
		||||
                                if (zpush == null)
 | 
			
		||||
                                {
 | 
			
		||||
                                    Logger.Instance.Trace(this, "Not a ZPush account: {0}", displayName);
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
                                    Logger.Instance.Trace(this, "ZPush account: {0}", zpush);
 | 
			
		||||
                                    _watcher.OnAccountDiscovered(zpush, true);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (System.Exception e)
 | 
			
		||||
                            {
 | 
			
		||||
                                Logger.Instance.Error(this, "Exception processing account: {0}", e);
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
                        AccountAdded(account);
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Tasks.Task(null, "AccountCheckDone", () =>
 | 
			
		||||
                {
 | 
			
		||||
                    _watcher.OnAccountsScanned();
 | 
			
		||||
 | 
			
		||||
                    if (GlobalOptions.INSTANCE.AccountTimer)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Set up timer to check for removed accounts
 | 
			
		||||
                        _watcher.Timed(Config.ACCOUNT_CHECK_INTERVAL, CheckAccountsRemoved);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // Register for account changes
 | 
			
		||||
                _stores.AccountDiscovered += AccountAdded;
 | 
			
		||||
                _stores.AccountRemoved += AccountRemoved;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void CheckAccountsRemoved()
 | 
			
		||||
        private void AccountAdded(IAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Collect all the store ids
 | 
			
		||||
                HashSet<string> stores = new HashSet<string>();
 | 
			
		||||
                foreach (NSOutlook.Store store in _stores)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        stores.Add(store.StoreID);
 | 
			
		||||
                    }
 | 
			
		||||
                    finally
 | 
			
		||||
                    {
 | 
			
		||||
                        ComRelease.Release(store);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                Logger.Instance.Trace(this, "Checking account: {0}", account);
 | 
			
		||||
 | 
			
		||||
                // Check if any relevant ones are removed
 | 
			
		||||
                List<KeyValuePair<string, ZPushAccount>> removed = new List<KeyValuePair<string, ZPushAccount>>();
 | 
			
		||||
                foreach(KeyValuePair<string, ZPushAccount> account in _accountsByStoreId)
 | 
			
		||||
                // Only EAS accounts can be zpush accounts
 | 
			
		||||
                if (account.AccountType == AccountType.EAS)
 | 
			
		||||
                {
 | 
			
		||||
                    if (!stores.Contains(account.Key))
 | 
			
		||||
                    {
 | 
			
		||||
                        Logger.Instance.Trace(this, "Store not found: {0} - {1}", account.Value, account.Key);
 | 
			
		||||
                        removed.Add(account);
 | 
			
		||||
                    }
 | 
			
		||||
                    ZPushAccount zpush = new ZPushAccount(account);
 | 
			
		||||
                    _accountsByStoreId.Add(account.StoreID, zpush);
 | 
			
		||||
                    _accountsBySmtp.Add(account.SmtpAddress, zpush);
 | 
			
		||||
                    Logger.Instance.Trace(this, "ZPush account: {0}", zpush);
 | 
			
		||||
                    _watcher.OnAccountDiscovered(zpush);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Process any removed stores
 | 
			
		||||
                foreach(KeyValuePair<string, ZPushAccount> remove in removed)
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    Logger.Instance.Debug(this, "Account removed: {0} - {1}", remove.Value, remove.Key);
 | 
			
		||||
                    _accountsBySmtp.Remove(remove.Value.SmtpAddress);
 | 
			
		||||
                    _accountsByStoreId.Remove(remove.Key);
 | 
			
		||||
                    _watcher.OnAccountRemoved(remove.Value);
 | 
			
		||||
                    Logger.Instance.Trace(this, "Not a ZPush account: {0}", account);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch(System.Exception e)
 | 
			
		||||
            catch (System.Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Error(this, "Exception in CheckAccountsRemoved: {0}", e);
 | 
			
		||||
                Logger.Instance.Error(this, "Exception processing account: {0}", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<ZPushAccount> GetAccounts()
 | 
			
		||||
        private void AccountRemoved(IAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            return _accountsBySmtp.Values;
 | 
			
		||||
            _accountsBySmtp.Remove(account.SmtpAddress);
 | 
			
		||||
            _accountsByStoreId.Remove(account.StoreID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the ZPushAccount on which the folder is located.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The ZPushAccount, or null if the folder is not on a zpush account</returns>
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Account access
 | 
			
		||||
 | 
			
		||||
        public ZPushAccount GetAccount(IFolder folder)
 | 
			
		||||
        {
 | 
			
		||||
            ZPushAccount zpush = null;
 | 
			
		||||
            using (IStore store = folder.Store)
 | 
			
		||||
                _accountsByStoreId.TryGetValue(store.StoreID, out zpush);
 | 
			
		||||
            return zpush;
 | 
			
		||||
        }
 | 
			
		||||
        public ZPushAccount GetAccount(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            ZPushAccount zpush = null;
 | 
			
		||||
            _accountsByStoreId.TryGetValue(store.StoreID, out zpush);
 | 
			
		||||
            return zpush;
 | 
			
		||||
        }
 | 
			
		||||
        public ZPushAccount GetAccount(IBase item)
 | 
			
		||||
        {
 | 
			
		||||
            if (item is IFolder)
 | 
			
		||||
                return GetAccount((IFolder)item);
 | 
			
		||||
            else if (item is IStore)
 | 
			
		||||
                return GetAccount((IStore)item);
 | 
			
		||||
            if (item.Parent != null)
 | 
			
		||||
                return GetAccount(item.Parent);
 | 
			
		||||
            return null;
 | 
			
		||||
            ZPushAccount value = null;
 | 
			
		||||
            _accountsByStoreId.TryGetValue(folder.StoreID, out value);
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ZPushAccount GetAccount(NSOutlook.MAPIFolder folder)
 | 
			
		||||
        public ZPushAccount GetAccount(IAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            {
 | 
			
		||||
                ZPushAccount zpush = null;
 | 
			
		||||
                NSOutlook.Store store = com.Add(folder.Store);
 | 
			
		||||
                string storeId = store?.StoreID;
 | 
			
		||||
                if (storeId == null)
 | 
			
		||||
                    return null;
 | 
			
		||||
                _accountsByStoreId.TryGetValue(storeId, out zpush);
 | 
			
		||||
                return zpush;
 | 
			
		||||
            }
 | 
			
		||||
            ZPushAccount value = null;
 | 
			
		||||
            _accountsByStoreId.TryGetValue(account.StoreID, out value);
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ZPushAccount GetAccount(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            ZPushAccount value = null;
 | 
			
		||||
            _accountsByStoreId.TryGetValue(store.StoreID, out value);
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ZPushAccount GetAccount(IBase obj)
 | 
			
		||||
        {
 | 
			
		||||
            if (obj is IFolder)
 | 
			
		||||
                return GetAccount((IFolder)obj);
 | 
			
		||||
            else if (obj is IStore)
 | 
			
		||||
                return GetAccount((IStore)obj);
 | 
			
		||||
            if (obj.Parent != null)
 | 
			
		||||
                return GetAccount(obj.Parent);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ZPushAccount GetAccount(string smtpAddress)
 | 
			
		||||
        {
 | 
			
		||||
            ZPushAccount account = null;
 | 
			
		||||
            _accountsBySmtp.TryGetValue(smtpAddress, out account);
 | 
			
		||||
            return account;
 | 
			
		||||
            ZPushAccount value = null;
 | 
			
		||||
            _accountsBySmtp.TryGetValue(smtpAddress, out value);
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the ZPush account associated with the Outlook account.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="account">The account. This function will release the handle</param>
 | 
			
		||||
        /// <returns>The ZPushAccount, or null if not a ZPush account.</returns>
 | 
			
		||||
        private ZPushAccount GetAccount(NSOutlook.Account account)
 | 
			
		||||
        public IEnumerable<ZPushAccount> GetAccounts()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Only EAS accounts can be zpush accounts
 | 
			
		||||
                if (account.AccountType != NSOutlook.OlAccountType.olEas)
 | 
			
		||||
                    return null;
 | 
			
		||||
 | 
			
		||||
                // Check for a cached value
 | 
			
		||||
                ZPushAccount zpush;
 | 
			
		||||
                if (_accountsBySmtp.TryGetValue(account.SmtpAddress, out zpush))
 | 
			
		||||
                    return zpush;
 | 
			
		||||
 | 
			
		||||
                // Create a new account
 | 
			
		||||
                return CreateFromRegistry(account);
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                ComRelease.Release(account);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Event handler for Stores.StoreAdded event.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void StoreAdded(NSOutlook.Store s)
 | 
			
		||||
        {
 | 
			
		||||
            IStore store = null;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Accessing the store object causes random crashes, simply iterate to find new stores
 | 
			
		||||
                Logger.Instance.Trace(this, "StoreAdded: {0}", s.StoreID);
 | 
			
		||||
                foreach (NSOutlook.Store rawStore in _session.Stores.RawEnum(false))
 | 
			
		||||
                {
 | 
			
		||||
                    if (!_accountsByStoreId.ContainsKey(rawStore.StoreID))
 | 
			
		||||
                    {
 | 
			
		||||
                        Logger.Instance.Trace(this, "New store: {0}", rawStore.DisplayName);
 | 
			
		||||
 | 
			
		||||
                        store = Mapping.Wrap(rawStore);
 | 
			
		||||
                        ZPushAccount zpush = TryCreateFromRegistry(store);
 | 
			
		||||
                        if (zpush == null)
 | 
			
		||||
                        {
 | 
			
		||||
                            // Add it to the cache so it is not evaluated again.
 | 
			
		||||
                            _accountsByStoreId.Add(store.StoreID, null);
 | 
			
		||||
                            Logger.Instance.Trace(this, "Not a ZPush store: {0}", store.DisplayName);
 | 
			
		||||
                            store.Dispose();
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger.Instance.Trace(this, "New ZPush store: {0}: {1}", store.DisplayName, zpush);
 | 
			
		||||
                            _watcher.OnAccountDiscovered(zpush, false);
 | 
			
		||||
                            // zpush has taken ownership
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else ComRelease.Release(rawStore);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch(System.Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Logger.Instance.Error(this, "StoreAdded Exception: {0}", e);
 | 
			
		||||
                if (store != null)
 | 
			
		||||
                    store.Dispose();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Registry
 | 
			
		||||
 | 
			
		||||
        private void Register(ZPushAccount zpush)
 | 
			
		||||
        {
 | 
			
		||||
            // Register the new account
 | 
			
		||||
            _accountsBySmtp.Add(zpush.SmtpAddress, zpush);
 | 
			
		||||
            _accountsByStoreId.Add(zpush.StoreID, zpush);
 | 
			
		||||
            Logger.Instance.Trace(this, "Account registered: {0} -> {1}", zpush.DisplayName, zpush.Store.StoreID);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates the ZPushAccount for the account, from the registry values.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="account">The account. The caller is responsible for releasing this.</param>
 | 
			
		||||
        /// <returns>The associated ZPushAccount</returns>
 | 
			
		||||
        /// <exception cref="Exception">If the registry key cannot be found</exception>
 | 
			
		||||
        // TODO: check owner
 | 
			
		||||
        private ZPushAccount CreateFromRegistry(NSOutlook.Account account)
 | 
			
		||||
        {
 | 
			
		||||
            // TODO: check that caller releases account everywhere
 | 
			
		||||
            using (ComRelease com = new ComRelease())
 | 
			
		||||
            using (RegistryKey baseKey = FindRegistryKey(account))
 | 
			
		||||
            {
 | 
			
		||||
                if (baseKey == null)
 | 
			
		||||
                    throw new System.Exception("Unknown account: " + account.SmtpAddress);
 | 
			
		||||
 | 
			
		||||
                // Get the store id
 | 
			
		||||
                string storeId = ZPushAccount.GetStoreId(baseKey.Name);
 | 
			
		||||
 | 
			
		||||
                // Find the store
 | 
			
		||||
                NSOutlook.Store store = _session.GetStoreFromID(storeId);
 | 
			
		||||
 | 
			
		||||
                // Done, create and register
 | 
			
		||||
                ZPushAccount zpush = new ZPushAccount(baseKey.Name, Mapping.Wrap(store));
 | 
			
		||||
                Register(zpush);
 | 
			
		||||
                return zpush;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates the ZPushAccount for the store, from the registry.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="store">The store. Ownership is transferred to the ZPushAccount. If the account is not created, the store is NOT disposed</param>
 | 
			
		||||
        /// <returns>The ZPushAccount, or null if no account is associated with the store</returns>
 | 
			
		||||
        private ZPushAccount TryCreateFromRegistry(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            using (RegistryKey baseKey = FindRegistryKey(store))
 | 
			
		||||
            {
 | 
			
		||||
                if (baseKey == null)
 | 
			
		||||
                    return null;
 | 
			
		||||
                ZPushAccount zpush = new ZPushAccount(baseKey.Name, store);
 | 
			
		||||
                Register(zpush);
 | 
			
		||||
                return zpush;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private RegistryKey OpenBaseKey()
 | 
			
		||||
        {
 | 
			
		||||
            NSOutlook.NameSpace session = _app.Session;
 | 
			
		||||
            string path = string.Format(OutlookConstants.REG_SUBKEY_ACCOUNTS, session.CurrentProfileName);
 | 
			
		||||
            ComRelease.Release(session);
 | 
			
		||||
            return OutlookRegistryUtils.OpenOutlookKey(path);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Finds the registry key for the account.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The registry key, or null if it cannot be found</returns>
 | 
			
		||||
        private RegistryKey FindRegistryKey(NSOutlook.Account account)
 | 
			
		||||
        {
 | 
			
		||||
            // Find the registry key by email adddress
 | 
			
		||||
            using (RegistryKey key = OpenBaseKey())
 | 
			
		||||
            {
 | 
			
		||||
                if (key != null)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (string subkey in key.GetSubKeyNames())
 | 
			
		||||
                    {
 | 
			
		||||
                        RegistryKey accountKey = key.OpenSubKey(subkey);
 | 
			
		||||
                        if (accountKey.GetValueString(OutlookConstants.REG_VAL_EMAIL) == account.SmtpAddress)
 | 
			
		||||
                        {
 | 
			
		||||
                            return accountKey;
 | 
			
		||||
                        }
 | 
			
		||||
                        accountKey.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Finds the registry key for the account associated with the store.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The registry key, or null if it cannot be found</returns>
 | 
			
		||||
        private RegistryKey FindRegistryKey(IStore store)
 | 
			
		||||
        {
 | 
			
		||||
            // Find the registry key by store id
 | 
			
		||||
            using (RegistryKey key = OpenBaseKey())
 | 
			
		||||
            {
 | 
			
		||||
                if (key != null)
 | 
			
		||||
                {
 | 
			
		||||
                    foreach (string subkey in key.GetSubKeyNames())
 | 
			
		||||
                    {
 | 
			
		||||
                        RegistryKey accountKey = key.OpenSubKey(subkey);
 | 
			
		||||
                        string storeId = ZPushAccount.GetStoreId(accountKey.Name);
 | 
			
		||||
                        if (storeId != null && storeId == store.StoreID)
 | 
			
		||||
                        {
 | 
			
		||||
                            return accountKey;
 | 
			
		||||
                        }
 | 
			
		||||
                        accountKey.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
            return _accountsByStoreId.Values;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,6 @@ using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NSOutlook = Microsoft.Office.Interop.Outlook;
 | 
			
		||||
 | 
			
		||||
namespace Acacia.ZPush
 | 
			
		||||
{
 | 
			
		||||
@@ -88,7 +87,7 @@ namespace Acacia.ZPush
 | 
			
		||||
 | 
			
		||||
                // Path found, create the store
 | 
			
		||||
                Logger.Instance.Info(typeof(ZPushLocalStore), "Creating new store: {0}", path);
 | 
			
		||||
                store = addIn.AddFileStore(path);
 | 
			
		||||
                store = addIn.Stores.AddFileStore(path);
 | 
			
		||||
                Logger.Instance.Debug(typeof(ZPushLocalStore), "Created new store: {0}", store.FilePath);
 | 
			
		||||
 | 
			
		||||
                // Set the display name
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ namespace Acacia.ZPush
 | 
			
		||||
            this._addIn = addIn;
 | 
			
		||||
            this._app = addIn.RawApp;
 | 
			
		||||
            Sync = new ZPushSync(this, addIn);
 | 
			
		||||
            Accounts = new ZPushAccounts(this, _app);
 | 
			
		||||
            Accounts = new ZPushAccounts(this, addIn);
 | 
			
		||||
 | 
			
		||||
            // Need to keep a link to keep receiving events
 | 
			
		||||
            _explorer2 = _app.ActiveExplorer();
 | 
			
		||||
@@ -77,43 +77,6 @@ namespace Acacia.ZPush
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Timers
 | 
			
		||||
 | 
			
		||||
        public void Delayed(int millis, System.Action action)
 | 
			
		||||
        {
 | 
			
		||||
            RegisterTimer(millis, action, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Timed(int millis, System.Action action)
 | 
			
		||||
        {
 | 
			
		||||
            RegisterTimer(millis, action, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void RegisterTimer(int millis, System.Action action, bool repeat)
 | 
			
		||||
        { 
 | 
			
		||||
            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
 | 
			
		||||
            timer.Interval = millis;
 | 
			
		||||
            timer.Tick += (s, eargs) =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    action();
 | 
			
		||||
                    if (!repeat)
 | 
			
		||||
                    {
 | 
			
		||||
                        timer.Enabled = false;
 | 
			
		||||
                        timer.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch(System.Exception e)
 | 
			
		||||
                {
 | 
			
		||||
                    Logger.Instance.Trace(this, "Exception in timer: {0}", e);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            timer.Start();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Accounts
 | 
			
		||||
        
 | 
			
		||||
        public delegate void AccountHandler(ZPushAccount account);
 | 
			
		||||
@@ -134,18 +97,15 @@ namespace Acacia.ZPush
 | 
			
		||||
        /// Handles a new account.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="account">The account.</param>
 | 
			
		||||
        /// <param name="isExisting">True if the account is an existing account, false if
 | 
			
		||||
        ///                          it is a new account</param>
 | 
			
		||||
        internal void OnAccountDiscovered(ZPushAccount account, bool isExisting)
 | 
			
		||||
        internal void OnAccountDiscovered(ZPushAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            // Notify any account listeners
 | 
			
		||||
            if (AccountDiscovered != null)
 | 
			
		||||
                AccountDiscovered(account);
 | 
			
		||||
            AccountDiscovered?.Invoke(account);
 | 
			
		||||
 | 
			
		||||
            // Register any events
 | 
			
		||||
            HandleFolderWatchers(account);
 | 
			
		||||
 | 
			
		||||
            if (account.HasPassword)
 | 
			
		||||
            if (account.Account.HasPassword)
 | 
			
		||||
            {
 | 
			
		||||
                // Send an OOF request to get the OOF state and capabilities
 | 
			
		||||
                Tasks.Task(null, "ZPushCheck: " + account.DisplayName, () =>
 | 
			
		||||
@@ -274,7 +234,7 @@ namespace Acacia.ZPush
 | 
			
		||||
        private void HandleFolderWatchers(ZPushAccount account)
 | 
			
		||||
        {
 | 
			
		||||
            // We need to keep the object alive to keep receiving events
 | 
			
		||||
            _rootFolder = new ZPushFolder(this, account.Store.GetRootFolder());
 | 
			
		||||
            _rootFolder = new ZPushFolder(this, account.Account.Store.GetRootFolder());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void WatchFolder(FolderRegistration folder, FolderEventHandler handler, FolderEventHandler changedHandler = null)
 | 
			
		||||
@@ -367,7 +327,7 @@ namespace Acacia.ZPush
 | 
			
		||||
            
 | 
			
		||||
            string entryId = folder.EntryID;
 | 
			
		||||
 | 
			
		||||
            using (IStore store = folder.Store)
 | 
			
		||||
            using (IStore store = folder.GetStore())
 | 
			
		||||
            { 
 | 
			
		||||
                foreach(DefaultFolder defaultFolderId in BLACKLISTED_MAIL_FOLDERS)
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user