Add basic functionality for pEp to pEp OUT-428
authorThomas
Wed, 11 Apr 2018 15:25:48 +0200
branchOUT-428
changeset 2107a5d7688eb17c
parent 2106 7ee0a280030d
child 2108 41eb44080146
Add basic functionality for pEp to pEp
CryptableMailItem.cs
MsgProcessor.cs
ThisAddIn.cs
UI/KeySyncWizard.xaml.cs
     1.1 --- a/CryptableMailItem.cs	Wed Apr 11 15:10:34 2018 +0200
     1.2 +++ b/CryptableMailItem.cs	Wed Apr 11 15:25:48 2018 +0200
     1.3 @@ -7,6 +7,7 @@
     1.4  using System.Diagnostics;
     1.5  using System.IO;
     1.6  using MimeKit;
     1.7 +using pEp.UI;
     1.8  
     1.9  namespace pEp
    1.10  {
    1.11 @@ -28,6 +29,12 @@
    1.12          public delegate void GetMirrorCompletedHandler(object sender, GetMirrorCompletedEventArgs e);
    1.13  
    1.14          /// <summary>
    1.15 +        /// Event handler for when a sync message is being detected during decryption.
    1.16 +        /// </summary>
    1.17 +        public delegate void SyncMessageReceivedHandler(object sender, SyncMessageEventArgs e);
    1.18 +        public static event SyncMessageReceivedHandler SyncMessageReceived;
    1.19 +
    1.20 +        /// <summary>
    1.21          /// Event when the internal mail item before delete event occurs.
    1.22          /// </summary>
    1.23          [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly")]
    1.24 @@ -1445,6 +1452,63 @@
    1.25                              // Save processed message data to Outlook
    1.26                              if (processedMessage != null)
    1.27                              {
    1.28 +                                // Check if key sync wizard is open
    1.29 +                                if (KeySyncWizard.Wizard?.IsVisible == true)
    1.30 +                                {
    1.31 +                                    Log.Verbose("Decrypt: Message decrypted while key sync wizard is open.");
    1.32 +
    1.33 +                                    // Check if formal requirements are met
    1.34 +                                    if ((processedMessage.To.Count == 1) &&
    1.35 +                                        (processedMessage.To[0].Address.Equals(processedMessage.From.Address)))
    1.36 +                                    {
    1.37 +                                        Log.Verbose("Decrypt: Message to myself");
    1.38 +
    1.39 +                                        // Detect message type
    1.40 +                                        if ((processedMessage.Rating == pEpRating.pEpRatingReliable) &&
    1.41 +                                            (decryptionFlags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey) == false))
    1.42 +                                        {
    1.43 +                                            // Message with public key
    1.44 +                                            Log.Verbose("Decrypt: Message rating is reliable and has no private key import flag. Assuming message with public key.");
    1.45 +                                            CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(processedMessage, KeySyncWizard.MessageTypes.PublicKeyMessage));
    1.46 +                                        }
    1.47 +                                        else if ((processedMessage.Rating > pEpRating.pEpRatingReliable) &&
    1.48 +                                                 (decryptionFlags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)))
    1.49 +                                        {
    1.50 +                                            // Message with private key
    1.51 +                                            Log.Verbose("Decrypt: Message rating is trusted and has private key attached. Assuming message with private key.");
    1.52 +                                            CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(processedMessage, KeySyncWizard.MessageTypes.PrivateKeyMessage));
    1.53 +                                        }
    1.54 +                                        else
    1.55 +                                        {
    1.56 +                                            // Message type cannot be determined
    1.57 +                                            Log.Verbose("Decrypt: No known message type. Rating is " + Enum.GetName(typeof(pEpRating), processedMessage.Rating) + ". Has private key flag == " + decryptionFlags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString());
    1.58 +                                        }
    1.59 +                                    }
    1.60 +                                    else
    1.61 +                                    {
    1.62 +                                        // Message doesn't match formal criteria
    1.63 +                                        Log.Verbose("Decrypt: Message not processed as keysync wizard message. Recipients count or addresses do not match.");
    1.64 +                                    }
    1.65 +                                }
    1.66 +                                // Check if message has pEp-key-import header and open key import wizard in this case
    1.67 +                                else if (string.IsNullOrEmpty(processedMessage.KeyImport) == false)
    1.68 +                                {
    1.69 +                                    // Make sure the wizard is not null
    1.70 +                                    if (KeySyncWizard.Wizard != null)
    1.71 +                                    {
    1.72 +                                        // Marshall to main thread and create new wizard
    1.73 +                                        KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
    1.74 +                                        {
    1.75 +                                            KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, this.Myself, processedMessage.KeyImport);
    1.76 +                                            KeySyncWizard.Wizard.Show();
    1.77 +                                        }));
    1.78 +                                    }
    1.79 +                                    else
    1.80 +                                    {
    1.81 +                                        Log.Error("ProcessAndGetRating: KeySyncWizard is null.");
    1.82 +                                    }
    1.83 +                                }
    1.84 +
    1.85                                  // Set the mail item
    1.86                                  mirrorCreated = false;
    1.87                                  if (mirror != null)
    1.88 @@ -2057,5 +2121,26 @@
    1.89                  this.IsEncrypted = false;
    1.90              }
    1.91          }
    1.92 +
    1.93 +        /// <summary>
    1.94 +        /// Class used to store the arguments in the SyncMessageReceived event.
    1.95 +        /// </summary>
    1.96 +        internal class SyncMessageEventArgs : EventArgs
    1.97 +        {
    1.98 +            public PEPMessage Message = null;
    1.99 +            public KeySyncWizard.MessageTypes MessageType = KeySyncWizard.MessageTypes.Undefined;
   1.100 +
   1.101 +            /// <summary>
   1.102 +            /// Constructs a new SyncMessageEventArgs with the given arguments.
   1.103 +            /// </summary>
   1.104 +            /// <param name="message">The message that has been received.</param>
   1.105 +            /// <param name="messageType">The message type of the received message.</param>
   1.106 +            public SyncMessageEventArgs(PEPMessage message,
   1.107 +                                        KeySyncWizard.MessageTypes messageType)
   1.108 +            {
   1.109 +                this.Message = message;
   1.110 +                this.MessageType = messageType;
   1.111 +            }
   1.112 +        }
   1.113      }
   1.114  }
     2.1 --- a/MsgProcessor.cs	Wed Apr 11 15:10:34 2018 +0200
     2.2 +++ b/MsgProcessor.cs	Wed Apr 11 15:25:48 2018 +0200
     2.3 @@ -21,12 +21,6 @@
     2.4  
     2.5          private BackgroundWorker backgroundProcessor;
     2.6  
     2.7 -        /// <summary>
     2.8 -        /// Event handler for when a sync message is being detected during decryption.
     2.9 -        /// </summary>
    2.10 -        public delegate void SyncMessageReceivedHandler(object sender, SyncMessageEventArgs e);
    2.11 -        public static event SyncMessageReceivedHandler SyncMessageReceived;
    2.12 -
    2.13          /**************************************************************
    2.14           * 
    2.15           * Constructors/Destructors
    2.16 @@ -950,46 +944,7 @@
    2.17  
    2.18                  // Copy over lost properties
    2.19                  destMessage.SetNonEnginePropertiesFrom(sourceMessage);
    2.20 -                keyList = dstKeyList;
    2.21 -
    2.22 -                // Check if key sync wizard is open
    2.23 -                if (UI.KeySyncWizard.WizardInProcess)                    
    2.24 -                {
    2.25 -                    Log.Verbose("Decrypt: Message decrypted while key sync wizard is open.");
    2.26 -
    2.27 -                    // Check if formal requirements are met
    2.28 -                    if ((destMessage.To.Count == 1) &&
    2.29 -                        (destMessage.To[0].Address.Equals(destMessage.From.Address)))
    2.30 -                    {
    2.31 -                        Log.Verbose("Decrypt: Message to myself");
    2.32 -
    2.33 -                        // Detect message type
    2.34 -                        if ((destMessage.Rating == pEpRating.pEpRatingReliable) &&
    2.35 -                            (flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey) == false))
    2.36 -                        {
    2.37 -                            // Message with public key
    2.38 -                            Log.Verbose("Decrypt: Message rating is reliable and has no private key import flag. Assuming message with public key.");
    2.39 -                            MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(destMessage, SyncMessageEventArgs.MessageTypes.PublicKey));
    2.40 -                        }
    2.41 -                        else if ((destMessage.Rating > pEpRating.pEpRatingReliable) &&
    2.42 -                                 (flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)))
    2.43 -                        {
    2.44 -                            // Message with private key
    2.45 -                            Log.Verbose("Decrypt: Message rating is trusted and has private key attached. Assuming message with private key.");
    2.46 -                            MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(destMessage, SyncMessageEventArgs.MessageTypes.PrivateKey));
    2.47 -                        }
    2.48 -                        else
    2.49 -                        {
    2.50 -                            // Message type cannot be determined
    2.51 -                            Log.Verbose("Decrypt: No known message type. Rating is " + Enum.GetName(typeof(pEpRating), destMessage.Rating) + ". Has private key flag == " + flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString());
    2.52 -                        }
    2.53 -                    }
    2.54 -                    else
    2.55 -                    {
    2.56 -                        // Message doesn't match formal criteria
    2.57 -                        Log.Verbose("Decrypt: Message not processed as keysync wizard message. Recipients count or addresses do not match.");
    2.58 -                    }
    2.59 -                }
    2.60 +                keyList = dstKeyList;                
    2.61              }
    2.62              else
    2.63              {
    2.64 @@ -1156,36 +1111,5 @@
    2.65                  this.ProcessedStatus = Globals.ReturnStatus.Success;
    2.66              }
    2.67          }
    2.68 -
    2.69 -        /// <summary>
    2.70 -        /// Class used to store the arguments in the SyncMessageReceived event.
    2.71 -        /// </summary>
    2.72 -        internal class SyncMessageEventArgs : EventArgs
    2.73 -        {
    2.74 -            /// <summary>
    2.75 -            /// The message types for sync messages.
    2.76 -            /// </summary>
    2.77 -            public enum MessageTypes
    2.78 -            {
    2.79 -                Undefined,
    2.80 -                PublicKey,
    2.81 -                PrivateKey
    2.82 -            }
    2.83 -
    2.84 -            public PEPMessage Message = null;
    2.85 -            public MessageTypes MessageType = SyncMessageEventArgs.MessageTypes.Undefined;
    2.86 -
    2.87 -            /// <summary>
    2.88 -            /// Constructs a new SyncMessageEventArgs with the given arguments.
    2.89 -            /// </summary>
    2.90 -            /// <param name="message">The message that has been received.</param>
    2.91 -            /// <param name="messageType">The message type of the received message.</param>
    2.92 -            public SyncMessageEventArgs(PEPMessage message,
    2.93 -                                        MessageTypes messageType)
    2.94 -            {
    2.95 -                this.Message = message;
    2.96 -                this.MessageType = messageType;
    2.97 -            }
    2.98 -        }
    2.99      }
   2.100  }
     3.1 --- a/ThisAddIn.cs	Wed Apr 11 15:10:34 2018 +0200
     3.2 +++ b/ThisAddIn.cs	Wed Apr 11 15:25:48 2018 +0200
     3.3 @@ -2746,6 +2746,9 @@
     3.4              Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture.LCID);
     3.5              Log.Info("ThisAddIn_Startup: " + culture.TwoLetterISOLanguageName + " language detected.");
     3.6  
     3.7 +            // Add reference to KeySyncWizard in order to start the dialog from the main thread
     3.8 +            KeySyncWizard.Wizard = new KeySyncWizard();
     3.9 +
    3.10              try
    3.11              {
    3.12                  /* Note: This is sensitive to time as pEp needs to start as fast as possible.
     4.1 --- a/UI/KeySyncWizard.xaml.cs	Wed Apr 11 15:10:34 2018 +0200
     4.2 +++ b/UI/KeySyncWizard.xaml.cs	Wed Apr 11 15:25:48 2018 +0200
     4.3 @@ -15,6 +15,17 @@
     4.4                                             Interfaces.IReset
     4.5      {
     4.6          /// <summary>
     4.7 +        /// The message types for sync messages.
     4.8 +        /// </summary>
     4.9 +        public enum MessageTypes
    4.10 +        {
    4.11 +            Undefined,
    4.12 +            InitialMessage,
    4.13 +            PublicKeyMessage,
    4.14 +            PrivateKeyMessage
    4.15 +        }
    4.16 +
    4.17 +        /// <summary>
    4.18          /// Defines the wizard type.
    4.19          /// </summary>
    4.20          public enum WizardType
    4.21 @@ -51,18 +62,29 @@
    4.22          private PEPIdentity                             _SyncPartner;
    4.23          private ObservableCollection<HandshakeItem>     _Items;
    4.24  
    4.25 -        public static bool                              WizardInProcess = false;
    4.26 -        private static KeySyncWizard                    currentWizard = null;
    4.27 +        public static KeySyncWizard                     Wizard = null;
    4.28  
    4.29          /// <summary>
    4.30          /// Default constructor
    4.31          /// </summary>
    4.32 -        public KeySyncWizard(WizardType type)
    4.33 +        public KeySyncWizard()
    4.34 +        {
    4.35 +        }
    4.36 +
    4.37 +        /// <summary>
    4.38 +        /// Constructor to create a new key sync wizard.
    4.39 +        /// </summary>
    4.40 +        /// <param name="type">The type of this wizard.</param>
    4.41 +        /// <param name="myself">The myself identity.</param>
    4.42 +        /// <param name="partnerFpr">The partner fingerprint.</param>
    4.43 +        public KeySyncWizard(WizardType type,
    4.44 +                             PEPIdentity myself = null,
    4.45 +                             string partnerFpr = null)
    4.46          {
    4.47              // Only allow one wizard at a time
    4.48 -            if (KeySyncWizard.currentWizard != null)
    4.49 +            if (KeySyncWizard.Wizard != null)
    4.50              {
    4.51 -                KeySyncWizard.currentWizard.Close();
    4.52 +                KeySyncWizard.Wizard.Close();
    4.53              }
    4.54  
    4.55              // Initialize the window
    4.56 @@ -74,17 +96,14 @@
    4.57              // Initialize the wizard
    4.58              this.InitializeWizard(type);
    4.59  
    4.60 -            // Set global flag to true
    4.61 -            KeySyncWizard.WizardInProcess = true;
    4.62 -
    4.63              // Attach event handler for new sync messages
    4.64 -            MsgProcessor.SyncMessageReceived += MsgProcessor_SyncMessageReceived;
    4.65 +            CryptableMailItem.SyncMessageReceived += MsgProcessor_SyncMessageReceived;
    4.66  
    4.67              // Send initial message
    4.68 -            this.SendInitialMessage();
    4.69 +            this.SendSyncMessage(myself, partnerFpr);
    4.70  
    4.71              // Set current wizard
    4.72 -            KeySyncWizard.currentWizard = this;
    4.73 +            KeySyncWizard.Wizard = this;
    4.74          }
    4.75  
    4.76          #region Property Accessors
    4.77 @@ -95,6 +114,19 @@
    4.78           *************************************************************/
    4.79  
    4.80          /// <summary>
    4.81 +        /// Gets or sets the explanatory text in the wizard.
    4.82 +        /// </summary>
    4.83 +        public string ExplanationText
    4.84 +        {
    4.85 +            get { return this._ExplanationText; }
    4.86 +            set
    4.87 +            {
    4.88 +                this._ExplanationText = value;
    4.89 +                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
    4.90 +            }
    4.91 +        }
    4.92 +
    4.93 +        /// <summary>
    4.94          /// Gets or sets the list of keys to export.
    4.95          /// </summary>
    4.96          public ObservableCollection<string> KeysToExport
    4.97 @@ -121,6 +153,19 @@
    4.98          }
    4.99  
   4.100          /// <summary>
   4.101 +        /// Gets or sets the Next/Finish button's text.
   4.102 +        /// </summary>
   4.103 +        public string NextButtonText
   4.104 +        {
   4.105 +            get { return this._NextButtonText; }
   4.106 +            set
   4.107 +            {
   4.108 +                this._NextButtonText = value;
   4.109 +                this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
   4.110 +            }
   4.111 +        }
   4.112 +
   4.113 +        /// <summary>
   4.114          /// Gets or sets the Items collection.
   4.115          /// </summary>
   4.116          public ObservableCollection<HandshakeItem> Items
   4.117 @@ -185,32 +230,6 @@
   4.118              }
   4.119          }
   4.120  
   4.121 -        /// <summary>
   4.122 -        /// Gets the Next/Finish button's text depending on the wizard's state.
   4.123 -        /// </summary>
   4.124 -        public string NextButtonText
   4.125 -        {
   4.126 -            get { return this._NextButtonText; }
   4.127 -            set
   4.128 -            {
   4.129 -                this._NextButtonText = value;
   4.130 -                this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
   4.131 -            }
   4.132 -        }
   4.133 -
   4.134 -        /// <summary>
   4.135 -        /// Gets the explanatory text in the wizard depending on its state.
   4.136 -        /// </summary>
   4.137 -        public string ExplanationText
   4.138 -        {
   4.139 -            get { return this._ExplanationText; }
   4.140 -            set
   4.141 -            {
   4.142 -                this._ExplanationText = value;
   4.143 -                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
   4.144 -            }
   4.145 -        }
   4.146 -
   4.147          #endregion
   4.148  
   4.149          #region Event handlers
   4.150 @@ -277,11 +296,11 @@
   4.151          /// <summary>
   4.152          /// Event handler for when a sync message arrives while the wizard is open and in progress.
   4.153          /// </summary>
   4.154 -        private void MsgProcessor_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
   4.155 +        private void MsgProcessor_SyncMessageReceived(object sender, CryptableMailItem.SyncMessageEventArgs e)
   4.156          {
   4.157              // Check message type
   4.158              if ((e.Message != null) &&
   4.159 -                (e.MessageType == MsgProcessor.SyncMessageEventArgs.MessageTypes.PublicKey))
   4.160 +                (e.MessageType == MessageTypes.PublicKeyMessage))
   4.161              {
   4.162                  // Marshall to main thread
   4.163                  this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
   4.164 @@ -289,24 +308,30 @@
   4.165                      // Public key message received. Show trustwords.
   4.166                      PEPIdentity myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(e.Message.To[0].ToCOMType()));
   4.167                      PEPIdentity partner = myself.Copy();
   4.168 -                    string[] keys = e.Message?.KeyList.Split(',');
   4.169 -                    string partnerKey  = null;
   4.170 -                    foreach (var key in keys)
   4.171 +                    string partnerKey  = e.Message?.KeyImport;
   4.172 +
   4.173 +                    // In case of PGP import, we have no KeyImport header. Try to get from KeyList.
   4.174 +                    if (partnerKey == null)
   4.175                      {
   4.176 -                        if (key?.Equals(myself?.Fingerprint) == false)
   4.177 +                        string[] keys = e.Message?.KeyList.Split(',');
   4.178 +                        foreach (var key in keys)
   4.179                          {
   4.180 -                            partnerKey = key;
   4.181 -                            break;
   4.182 +                            if (key?.Equals(myself?.Fingerprint) == false)
   4.183 +                            {
   4.184 +                                partnerKey = key;
   4.185 +                                break;
   4.186 +                            }
   4.187                          }
   4.188                      }
   4.189 +
   4.190                      partner.Fingerprint = partnerKey;
   4.191                      this.KeysToImport.Add(partnerKey);
   4.192  
   4.193                      HandshakeItem item;
   4.194                      if (HandshakeItem.Create(myself, partner, false, out item) == Globals.ReturnStatus.Success)
   4.195                      {
   4.196 -                        item.AreTabControlsVisible = true;
   4.197 -                        item.ActiveTab = HandshakeItem.Tabs.Fingerprint;
   4.198 +                        item.AreTabControlsVisible = (this.Type == WizardType.PGP);
   4.199 +                        item.ActiveTab = (this.Type == WizardType.pEp ? HandshakeItem.Tabs.Trustwords : HandshakeItem.Tabs.Fingerprint);
   4.200                          item.AreHandshakeButtonsVisible = false;
   4.201                          this.Items.Add(item);
   4.202  
   4.203 @@ -320,7 +345,7 @@
   4.204                  }));
   4.205              }
   4.206              else if ((e.Message != null) &&
   4.207 -                     (e.MessageType == MsgProcessor.SyncMessageEventArgs.MessageTypes.PrivateKey))
   4.208 +                     (e.MessageType == MessageTypes.PrivateKeyMessage))
   4.209              {
   4.210                  // Marshall to main thread
   4.211                  this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
   4.212 @@ -340,7 +365,7 @@
   4.213              }
   4.214              else
   4.215              {
   4.216 -                Log.Error("MsgProcessor_SyncMessageReceived: Invalid data received. Message is " + ((e.Message != null) ? "not" : "" + " null. Message type is " + Enum.GetName(typeof(MsgProcessor.SyncMessageEventArgs.MessageTypes), e.MessageType)));
   4.217 +                Log.Error("MsgProcessor_SyncMessageReceived: Invalid data received. Message is " + ((e.Message != null) ? "not" : "" + " null. Message type is " + Enum.GetName(typeof(MessageTypes), e.MessageType)));
   4.218              }
   4.219          }
   4.220  
   4.221 @@ -350,13 +375,10 @@
   4.222          private void Window_Closed(object sender, EventArgs e)
   4.223          {
   4.224              // Remove event handler
   4.225 -            MsgProcessor.SyncMessageReceived += MsgProcessor_SyncMessageReceived;
   4.226 +            CryptableMailItem.SyncMessageReceived += MsgProcessor_SyncMessageReceived;
   4.227  
   4.228 -            // Unset flag
   4.229 -            KeySyncWizard.WizardInProcess = false;
   4.230 -
   4.231 -            // Remove static reference
   4.232 -            KeySyncWizard.currentWizard = null;
   4.233 +            // Reset static reference
   4.234 +            KeySyncWizard.Wizard = new KeySyncWizard();
   4.235          }
   4.236  
   4.237          #endregion
   4.238 @@ -407,87 +429,164 @@
   4.239          }
   4.240  
   4.241          /// <summary>
   4.242 -        /// Sends the initial message to myself to start the sync process.
   4.243 +        /// Sends the next sync message.
   4.244          /// </summary>
   4.245 -        private void SendInitialMessage()
   4.246 +        private void SendSyncMessage(PEPIdentity ownIdentity, string partnerFpr)
   4.247          {
   4.248 -            PEPIdentity ownIdentity = null;
   4.249 -            Outlook.Account account = null;
   4.250 -            Outlook.Accounts accounts = null;
   4.251 -            Outlook.Store deliveryStore = null;
   4.252 -            Outlook.Explorer explorer = null;
   4.253 -            Outlook.Folder folder = null;
   4.254 -            Outlook.NameSpace ns = null;
   4.255 +            // If own identity is null, get default account
   4.256 +            if (ownIdentity == null)
   4.257 +            {
   4.258 +                Outlook.Account account = null;
   4.259 +                Outlook.Accounts accounts = null;
   4.260 +                Outlook.Store deliveryStore = null;
   4.261 +                Outlook.Explorer explorer = null;
   4.262 +                Outlook.Folder folder = null;
   4.263 +                Outlook.NameSpace ns = null;
   4.264  
   4.265 -            // Try to get own identity for current account
   4.266 -            try
   4.267 -            {
   4.268 -                explorer = Globals.ThisAddIn.Application.ActiveExplorer();
   4.269 -                folder = explorer?.CurrentFolder as Outlook.Folder;
   4.270 +                // Try to get own identity for current account
   4.271 +                try
   4.272 +                {
   4.273 +                    explorer = Globals.ThisAddIn.Application.ActiveExplorer();
   4.274 +                    folder = explorer?.CurrentFolder as Outlook.Folder;
   4.275  
   4.276 -                ns = Globals.ThisAddIn.Application.Session;
   4.277 -                accounts = ns.Accounts;
   4.278 +                    ns = Globals.ThisAddIn.Application.Session;
   4.279 +                    accounts = ns.Accounts;
   4.280  
   4.281 -                // Note: Index starts at 1
   4.282 -                for (int i = 1; i <= accounts.Count; i++)
   4.283 +                    // Note: Index starts at 1
   4.284 +                    for (int i = 1; i <= accounts.Count; i++)
   4.285 +                    {
   4.286 +                        account = accounts[i];
   4.287 +
   4.288 +                        // Getting delivery store can fail for new accounts when Outlook is not restarted
   4.289 +                        try
   4.290 +                        {
   4.291 +                            deliveryStore = account.DeliveryStore;
   4.292 +                        }
   4.293 +                        catch (Exception ex)
   4.294 +                        {
   4.295 +                            deliveryStore = null;
   4.296 +                            Log.Error("SendSyncMessage: Error getting delivery store. " + ex.ToString());
   4.297 +                        }
   4.298 +
   4.299 +                        if (deliveryStore?.StoreID?.Equals(folder?.StoreID) == true)
   4.300 +                        {
   4.301 +                            if (PEPIdentity.GetOwnIdentity(account, out ownIdentity) != Globals.ReturnStatus.Success)
   4.302 +                            {
   4.303 +                                ownIdentity = null;
   4.304 +                                Log.Error("SendSyncMessage: Error getting own identity. ReturnStatus != Success.");
   4.305 +                            }
   4.306 +                            break;
   4.307 +                        }
   4.308 +
   4.309 +                        account = null;
   4.310 +                        deliveryStore = null;
   4.311 +                    }
   4.312 +                }
   4.313 +                catch (Exception ex)
   4.314                  {
   4.315 -                    account = accounts[i];
   4.316 -
   4.317 -                    // Getting delivery store can fail for new accounts when Outlook is not restarted
   4.318 -                    try
   4.319 -                    {
   4.320 -                        deliveryStore = account.DeliveryStore;
   4.321 -                    }
   4.322 -                    catch (Exception ex)
   4.323 -                    {
   4.324 -                        deliveryStore = null;
   4.325 -                        Log.Error("InitializeWizard: Error getting delivery store. " + ex.ToString());
   4.326 -                    }
   4.327 -
   4.328 -                    if (deliveryStore?.StoreID?.Equals(folder?.StoreID) == true)
   4.329 -                    {
   4.330 -                        if (PEPIdentity.GetOwnIdentity(account, out ownIdentity) != Globals.ReturnStatus.Success)
   4.331 -                        {
   4.332 -                            ownIdentity = null;
   4.333 -                            Log.Error("InitializeWizard: Error getting own identity. ReturnStatus != Success.");
   4.334 -                        }
   4.335 -                        break;
   4.336 -                    }
   4.337 -
   4.338 +                    Log.Error("SendSyncMessage: Error getting default account. " + ex.ToString());
   4.339 +                }
   4.340 +                finally
   4.341 +                {
   4.342                      account = null;
   4.343 +                    accounts = null;
   4.344                      deliveryStore = null;
   4.345 +                    explorer = null;
   4.346 +                    folder = null;
   4.347 +                    ns = null;
   4.348                  }
   4.349              }
   4.350 -            catch (Exception ex)
   4.351 -            {
   4.352 -                Log.Error("InitializeWizard: Error getting default account. " + ex.ToString());
   4.353 -            }
   4.354 -            finally
   4.355 -            {
   4.356 -                account = null;
   4.357 -                accounts = null;
   4.358 -                deliveryStore = null;
   4.359 -                explorer = null;
   4.360 -                folder = null;
   4.361 -                ns = null;
   4.362 -            }
   4.363  
   4.364 -            // If we have an own identity, send initial message
   4.365 +            // If we have an own identity, send message
   4.366              if (ownIdentity != null)
   4.367              {
   4.368                  PEPMessage message = new PEPMessage
   4.369                  {
   4.370                      From = ownIdentity,
   4.371                      ShortMsg = "pEp",
   4.372 -                    ForceUnencrypted = true
   4.373 +                    ForceUnencrypted = (string.IsNullOrEmpty(partnerFpr) ? true : false),
   4.374 +                    KeyImport = (this.Type == WizardType.pEp ? ownIdentity.Fingerprint : null)
   4.375                  };
   4.376                  message.To.Add(ownIdentity);
   4.377  
   4.378 -                Globals.ThisAddIn.CreateAndSendMessage(message, true, true, true);
   4.379 +                // If we have a partner fpr, encrypt for partner and add own key
   4.380 +                PEPMessage msg;
   4.381 +                if (string.IsNullOrEmpty(partnerFpr) == false)                    
   4.382 +                {
   4.383 +                    // TODO: Use engine method ThisAddIn.PEPEngine.EncryptAndAddKey();
   4.384 +                    if (this.EncryptAndAddPrivateKey(message, new string[] { partnerFpr }, out msg))
   4.385 +                    {
   4.386 +                        message = msg;
   4.387 +                    }
   4.388 +                    else
   4.389 +                    {
   4.390 +                        Log.Error("SendSyncMessage: Error encrypting private key message.");
   4.391 +                        message = null;
   4.392 +                    }
   4.393 +                }
   4.394 +
   4.395 +                if (message != null)
   4.396 +                {
   4.397 +                    Globals.ThisAddIn.CreateAndSendMessage(message, true, true, true);
   4.398 +                }
   4.399              }
   4.400          }
   4.401  
   4.402          /// <summary>
   4.403 +        /// Temp method. Has to be replaced by engine function.
   4.404 +        /// </summary>
   4.405 +        private bool EncryptAndAddPrivateKey(PEPMessage src, string[] extraKeys, out PEPMessage msg)
   4.406 +        {
   4.407 +            bool success = false;
   4.408 +            PEPMessage message = null;
   4.409 +
   4.410 +            try
   4.411 +            {
   4.412 +                string keyFileName = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "pEp", "private_key.asc");
   4.413 +                string keyId = src.From.Fingerprint.Substring(48);
   4.414 +
   4.415 +                // Create GPG ProcessStartInfo
   4.416 +                var startInfo = new System.Diagnostics.ProcessStartInfo
   4.417 +                {
   4.418 +                    FileName = Globals.GetGPGPath(),
   4.419 +                    Arguments = string.Format("gpg --export-secret-keys -a " + keyId + " >" + keyFileName),
   4.420 +                    RedirectStandardError = true,
   4.421 +                    UseShellExecute = false,
   4.422 +                    CreateNoWindow = true
   4.423 +                };
   4.424 +
   4.425 +                // Create process and start it
   4.426 +                var process = new System.Diagnostics.Process
   4.427 +                {
   4.428 +                    StartInfo = startInfo
   4.429 +                };
   4.430 +                process.Start();
   4.431 +                process.WaitForExit(30000); // limit execution time to 30 s
   4.432 +
   4.433 +                // Log errors
   4.434 +                if (process.ExitCode != 0)
   4.435 +                {
   4.436 +                    success = false;
   4.437 +                    string standardError = process.StandardError?.ReadToEnd();
   4.438 +                    Log.Error("EncryptAndAddPrivateKey: Error exporting private key. Exit code " + process.ExitCode + ". Error: " + standardError);
   4.439 +                }
   4.440 +                else
   4.441 +                {
   4.442 +                    message = src.Copy();
   4.443 +                    message.Attachments.Add(new PEPAttachment { Data = System.IO.File.ReadAllBytes(keyFileName), FileName = "secret_key.asc" });
   4.444 +                    message.To[0].Fingerprint = extraKeys[0];
   4.445 +                }
   4.446 +            }
   4.447 +            catch (Exception ex)
   4.448 +            {
   4.449 +                Log.Error("EncryptAndAddPrivateKey: Error encrypting private key message. " + ex.ToString());
   4.450 +            }
   4.451 +
   4.452 +            msg = message;
   4.453 +            return success;
   4.454 +        }
   4.455 +
   4.456 +        /// <summary>
   4.457          /// Trusts the communication partner key (makes the channel green)
   4.458          /// </summary>
   4.459          private void TrustKey()
   4.460 @@ -536,7 +635,7 @@
   4.461                      this.ExplanationText = Properties.Resources.KeySyncWizard_Step3PGPExplanationText;
   4.462                      break;
   4.463                  case WizardState.Step4:
   4.464 -                    this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
   4.465 +                    this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
   4.466                      this.ExplanationText = (this.Success ? Properties.Resources.KeySyncWizard_Step4SuccessExplanationText : Properties.Resources.KeySyncWizard_Step4ErrorExplanationText);
   4.467                      break;
   4.468                  case WizardState.Undefined: