Merge with default Redesign_Ribbon
authorThomas
Tue, 22 May 2018 11:35:06 +0200
branchRedesign_Ribbon
changeset 2206 d0173d827aa2
parent 2183 74999a6fa16a (current diff)
parent 2204 94aaeb734ef2 (diff)
child 2207 191d9997af5e
Merge with default
CryptableMailItem.cs
FPPMessage.cs
MsgProcessor.cs
PEPMessage.cs
PEPSettings.cs
Properties/Resources.Designer.cs
Properties/Resources.resx
ThisAddIn.cs
UI/FormControlPreviewMessage.xaml.cs
UI/HandshakeDialog.xaml.cs
UI/KeySyncWizard.xaml.cs
--- a/CryptableMailItem.cs	Thu May 10 12:18:14 2018 +0200
+++ b/CryptableMailItem.cs	Tue May 22 11:35:06 2018 +0200
@@ -97,12 +97,6 @@
         public delegate void OriginallyEncryptedStatusUpdateHandler(object sender, EventArgs e);
         public event OriginallyEncryptedStatusUpdateHandler OriginallyEncryptedStatusUpdated;
 
-        /// <summary>
-        /// Event handler for when a sync message is being detected during decryption.
-        /// </summary>
-        public delegate void SyncMessageReceivedHandler(object sender, CryptableMailItem.SyncMessageEventArgs e);
-        public static event SyncMessageReceivedHandler SyncMessageReceived;
-
         private pEpRating            _LastProcessedRating;
         private Globals.ReturnStatus _LastProcessedStatus;
 
@@ -1227,9 +1221,18 @@
                         // Wait for the other thread to finish
                         if (isAlreadyBeingDecrypted)
                         {
-                            Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
-                            Thread.Sleep(sleepTime);
-                            curWaitTime += sleepTime;
+                            // Do not process multiple times if it is an automatic message
+                            if (this.internalMailItem.GetIsAutoConsume())
+                            {
+                                curWaitTime = maxWaitTime + 1;
+                                Log.Verbose("ProcessAndGetRating: Setting timeout for AutoConsume message.");
+                            }
+                            else
+                            {
+                                Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
+                                Thread.Sleep(sleepTime);
+                                curWaitTime += sleepTime;
+                            }
                         }
                     }
                     while ((isAlreadyBeingDecrypted) && (curWaitTime < maxWaitTime));
@@ -1443,18 +1446,20 @@
                     // Process mail item
                     sts1 = PEPMessage.Create(this.internalMailItem, out message);
 
-                    // Block while KeySyncWizard is open and Trustwords haven't been accepted
-                    while ((KeySyncWizard.Wizard?.State == KeySyncWizard.WizardState.Step2) &&
-                            (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
-                            (message.To?.Count == 1) &&
-                            (message.From?.EqualsByAddress(message.To[0]) == true))
+                    // If Key Import Wizard is open, add mail to list to process later
+                    if ((KeySyncWizard.Wizard?.IsVisible == true) &&
+                        (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
+                        (message.To?.Count == 1) &&
+                        (message.From?.EqualsByAddress(message.To[0]) == true))
                     {
-                        Log.Verbose("ProcessAndGetRating: KeySyncWizard in Step 2. Blocking decryption.");
-                        Thread.Sleep(100);
+                        KeySyncWizard.Wizard?.AddToReceivedSyncMessages(message);
                     }
 
+                    // Define decryption flags
+                    decryptionFlags = IsSecurelyStored ? pEpDecryptFlags.pEpDecryptFlagUntrustedServer : pEpDecryptFlags.pEpDecryptFlagsNone;
+
                     // Process
-                    status = msgProcessor.ProcessMessage(message,
+                    status = msgProcessor.ProcessMessage(ref message,
                                                          sts1,
                                                          this.internalMailItem.GetIsInSecureStore(),
                                                          this.internalMailItem.GetIsInSentFolder(),
@@ -1462,7 +1467,7 @@
                                                          out mirror,
                                                          out processedMessage,
                                                          out processedRating,
-                                                         out decryptionFlags);
+                                                         ref decryptionFlags);
 
                     if (status == Globals.ReturnStatus.Success)
                     {
@@ -1491,9 +1496,6 @@
                         }
                         else
                         {
-                            // Check for sync message
-                            this.CheckForSyncMessage((processedRating == pEpRating.pEpRatingUnencrypted) ? message : processedMessage, decryptionFlags);
-
                             // Save processed message data to Outlook
                             if (processedMessage != null)
                             {
@@ -1519,6 +1521,22 @@
 
                                     mailItem = mirrorMailItem;
 
+                                    /* If we have extra keys and are on an untrusted server, reencrypt message
+                                     * for myself and the extra keys.
+                                     */ 
+                                    bool saveInternalMailItem = false;
+                                    if (decryptionFlags.HasFlag(pEpDecryptFlags.pEpDecryptFlagSrcModified))
+                                    {
+                                        if (message.ApplyTo(this.internalMailItem, false, false, true, false) == Globals.ReturnStatus.Success)
+                                        {
+                                            saveInternalMailItem = true;
+                                        }
+                                        else
+                                        {
+                                            Log.Error("ProcessAndGetRating: Error reencrypting with extra keys.");
+                                        }
+                                    }
+
                                     /* OUT - 283 Remove attachment icon for messages on untrusted servers 
                                      * in case decrypted mail has no attachments.
                                      * This is needed for all Exchange stores and IMAP stores on Outlook 2010.
@@ -1546,7 +1564,7 @@
                                                 attachment = null;
                                             }
 
-                                            this.internalMailItem.Save();
+                                            saveInternalMailItem = true;
                                         }
                                         catch (Exception ex)
                                         {
@@ -1558,6 +1576,19 @@
                                             attachment = null;
                                         }
                                     }
+
+                                    // Save mail item again if needed
+                                    if (saveInternalMailItem)
+                                    {
+                                        try
+                                        {
+                                            this.internalMailItem.Save();
+                                        }
+                                        catch (Exception ex)
+                                        {
+                                            Log.Error("ProcessAndGetRating: Error saving internal mail item. " + ex.ToString());
+                                        }
+                                    }
                                 }
                                 else
                                 {
@@ -1839,85 +1870,6 @@
          *************************************************************/
 
         /// <summary>
-        /// Checks if the key sync wizard is open or the message is a sync message.
-        /// If this is true, the message will get processed further, either raising
-        /// the respective event or opening the wizard.
-        /// </summary>
-        /// <param name="message">The message to check.</param>
-        /// <param name="flags">The decrypt flags.</param>
-        private void CheckForSyncMessage(PEPMessage message, pEpDecryptFlags flags)
-        {
-            try
-            {
-                /* To determine whether the processed message is a sync message:
-                 * 1. Is incoming (do not process sent messages)
-                 * 2. Has the KeyImport header (in case of pEp sync) and the header is not
-                 *    the own fingerprint.
-                 * - or -
-                 * 3. a. The WizardType is PGP
-                 *    b. The message has one To recipient that is also the From recipient
-                 *    c. The From recipient is an own identity (seems actually unnecessary)
-                 */
-                if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
-                    (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
-                {
-                    if ((message.To.Count == 1) &&
-                        (message.To[0].EqualsByAddress(message.From)) &&
-                        (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
-                    {
-                        Log.Verbose("CheckForSyncMessage: Sync message found.");
-
-                        if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
-                            (KeySyncWizard.Wizard?.IsVisible == false) &&
-                            (message.Rating < pEpRating.pEpRatingTrusted))
-                        {
-                            Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
-
-                            // Get own identity
-                            PEPIdentity myself = null;
-                            try
-                            {
-                                pEpIdentity _myself = message.To[0].ToCOMType();
-                                myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
-                            }
-                            catch (Exception ex)
-                            {
-                                myself = null;
-                                Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
-                            }
-
-                            // Only open if not sent to myself. Check again if not open
-                            if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
-                                (KeySyncWizard.Wizard?.IsVisible == false))
-                            {
-                                // Marshall to main thread and create new wizard
-                                KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
-                                {
-                                    KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
-                                    KeySyncWizard.Wizard.Show();
-                                    Log.Verbose("CheckForSyncMessage: Wizard opened.");
-                                }));
-                            }
-                        }
-                        else
-                        {
-                            Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
-                            CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
-                        }
-                    }
-                    else
-                    {
-                        Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
-                    }
-                }
-            }
-            catch (Exception ex)
-            {
-                Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
-            }
-        }
-
-        /// <summary>
         /// Releases all resources and disconnects internal events.
         /// The internal mail item will NOT be released -- this is managed externally.
         /// </summary>
@@ -2168,27 +2120,6 @@
         }
 
         /// <summary>
-        /// Class used to store the arguments in the SyncMessageReceived event.
-        /// </summary>
-        internal class SyncMessageEventArgs : EventArgs
-        {
-            public PEPMessage Message = null;
-            public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
-
-            /// <summary>
-            /// Constructs a new SyncMessageEventArgs with the given arguments.
-            /// </summary>
-            /// <param name="message">The message that has been received.</param>
-            /// <param name="flags">The decryption flags of the received message.</param>
-            public SyncMessageEventArgs(PEPMessage message,
-                                        pEpDecryptFlags flags)
-            {
-                this.Message = message;
-                this.Flags = flags;
-            }
-        }
-
-        /// <summary>
         /// Class used to store an entry in the encrypted conversation cache.
         /// This will identify the original parent encrypted mail item.
         /// </summary>
--- a/FPPMessage.cs	Thu May 10 12:18:14 2018 +0200
+++ b/FPPMessage.cs	Tue May 22 11:35:06 2018 +0200
@@ -20,13 +20,24 @@
     {       
         public const string PEP_FPP_MESSAGE_BODY_PLAIN                  = "This message is protected by p≡p. \n\nTo read this message, you can either download the free p≡p Reader here: " +
                                                                           Globals.PEP_WEBSITE_READER_LINK + " \n\nTo read and send protected messages yourself, you can get your copy of p≡p here: " +
-                                                                          Globals.PEP_WEBSITE_UPGRADE_LINK;
+                                                                          Globals.PEP_WEBSITE_UPGRADE_LINK +
+                                                                          "\n\nThis message can only be opened with p≡p for Outlook or p≡p Reader for Outlook.";
         public const string PEP_FPP_MESSAGE_BODY_HTML                   = "This message is protected by <a style=\"color:#03AA4B; text-decoration: none\" href=\"" + Globals.PEP_WEBSITE_LINK + "\">p≡p</a>. <br><br>To read this message, you can either download the free " +
                                                                           "<a style=\"color:#03AA4B; text-decoration: none\" href=\"" + Globals.PEP_WEBSITE_READER_LINK + "\">p≡p Reader</a> or, " +
                                                                           "to read and send protected messages yourself, you can get your copy of <a style=\"color:#03AA4B; text-decoration: none\" href=\"" +
-                                                                          Globals.PEP_WEBSITE_UPGRADE_LINK + "\">p≡p here</a>.";
-        public const string PEP_FPP_MESSAGE_BODY_PLAIN_PEP_INSTALLED    = "This message is protected by p≡p. \n\nTo read this message please click the Privacy Status button and follow the instructions.";
-        public const string PEP_FPP_MESSAGE_BODY_HTML_PEP_INSTALLED     = "This message is protected by <a style=\"color:#03AA4B; text-decoration: none\" href=\"" + Globals.PEP_WEBSITE_LINK + "\">p≡p</a>. <br><br>To read this message please click the Privacy Status button and follow the instructions.";
+                                                                          Globals.PEP_WEBSITE_UPGRADE_LINK + "\">p≡p here</a>." +
+                                                                          "<br><br>This message can only be opened with p≡p for Outlook or p≡p Reader for Outlook.";
+        public const string PEP_FPP_MESSAGE_BODY_PLAIN_PEP_INSTALLED    = "This message is protected by p≡p. \n\nTo read this message please do the following:" +
+                                                                          "\n\n1. Click the Privacy Status button on the bottom of this message to open the Handshake dialog." +
+                                                                          "\n2. Shortly after you opened the Handshake dialog on your computer, the same dialog will show up on the screen of the sender of the message as well (depending on the setup it might take 2-3 minutes). Contact the sender through another communication channel (e.g.phone call)." +
+                                                                          "\n3. Compare the Trustwords with your communication partner. If the Trustwords match, confirm the Trustwords by clicking the green button." +
+                                                                          "\n4. Shortly after, the protected message will automatically decrypt and you can read the message.";
+        public const string PEP_FPP_MESSAGE_BODY_HTML_PEP_INSTALLED     = "<!DOCTYPE html><html><head><meta http-equiv='Content-Type' content='text/html;charset=UTF-8'></head><body>" +
+                                                                          "This message is protected by <a style=\"color:#03AA4B; text-decoration: none\" href=\"" + Globals.PEP_WEBSITE_LINK + "\">p≡p</a>. <br><br>To read this message please do the following:" +
+                                                                          "<br><br>1. Click the Privacy Status button on the bottom of this message to open the Handshake dialog." +
+                                                                          "<br>2. Shortly after you opened the Handshake dialog on your computer, the same dialog will show up on the screen of the sender of the message as well (depending on the setup it might take 2-3 minutes). Contact the sender through another communication channel (e.g.phone call)." +
+                                                                          "<br>3. Compare the Trustwords with your communication partner. If the Trustwords match, confirm the Trustwords by clicking the green button." +
+                                                                          "<br>4. Shortly after, the protected message will automatically decrypt and you can read the message.</body></html>";
         public const string PEP_FPP_ATTACHMENT_FILE_NAME                = "ignore_this_attachment.pEp";
         public const string PEP_FPP_ATTACHMENT_MIME_TYPE                = "application/pEp.forceProtected";
 
@@ -190,11 +201,12 @@
                 PEPMessage processedMessage;
                 pEpRating processedRating;
                 string[] keyList;
-                pEpDecryptFlags flags;
+                pEpDecryptFlags flags = pEpDecryptFlags.pEpDecryptFlagsNone;
 
                 // Decrypt incoming message
                 MsgProcessor msgProcessor = new MsgProcessor();
-                if (msgProcessor.Decrypt(this.CurrentMessage, out processedMessage, out keyList, out flags, out processedRating) == false)
+                PEPMessage message = this.CurrentMessage;
+                if (msgProcessor.Decrypt(ref message, out processedMessage, out keyList, ref flags, out processedRating) == false)
                 {
                     Log.Error("FPPMessage.ProcessIncoming: Error decrypting incoming message.");
                     return Globals.ReturnStatus.Failure;
@@ -222,6 +234,12 @@
                 else
                 {
                     Log.Error("FPPMessage.ProcessIncoming: Task result is failure.");
+
+                    // Decrement decryption counter if necessary
+                    if (manuallyTriggered == false)
+                    {
+                        ThisAddIn.DecryptionStack.DecrementDecryptionCounter();
+                    }
                 }
             }, TaskScheduler.FromCurrentSynchronizationContext());
 
--- a/MsgProcessor.cs	Thu May 10 12:18:14 2018 +0200
+++ b/MsgProcessor.cs	Tue May 22 11:35:06 2018 +0200
@@ -14,14 +14,12 @@
     /// <summary>
     /// Class containing processing methods for PEPMessages.
     /// </summary>
-    internal class MsgProcessor : IDisposable
+    internal class MsgProcessor
     {
-        public delegate void ProcessingCompletedHandler(object sender, ProcessingCompletedEventArgs e);
-
         /// <summary>
         /// Event when processing is completed.
-        /// WARNING: The calling thread is a background worker.
         /// </summary>
+        public delegate void ProcessingCompletedHandler(object sender, ProcessingCompletedEventArgs e);
         public event ProcessingCompletedHandler ProcessingCompleted;
 
         /// <summary>
@@ -58,13 +56,6 @@
         {           
         }
 
-        /// <summary>
-        /// Implementing IDisposable
-        /// </summary>
-        public void Dispose()
-        {           
-        }
-
         /**************************************************************
          * 
          * Methods
@@ -173,17 +164,20 @@
                 }
                 else
                 {
-                    // Block while KeySyncWizard is open and Trustwords haven't been accepted
-                    while ((KeySyncWizard.Wizard?.State == KeySyncWizard.WizardState.Step2) &&
-                            (msgContainer?.Message?.Direction == pEpMsgDirection.pEpDirIncoming) &&
-                            (msgContainer?.Message?.To?.Count == 1) &&
-                            (msgContainer?.Message?.From?.EqualsByAddress(msgContainer.Message.To[0]) == true))
+                    // If Key Import Wizard is open, add mail to list to process later
+                    if ((KeySyncWizard.Wizard?.IsVisible == true) &&
+                        (msgContainer?.Message?.Direction == pEpMsgDirection.pEpDirIncoming) &&
+                        (msgContainer?.Message?.To?.Count == 1) &&
+                        (msgContainer?.Message?.From?.EqualsByAddress(msgContainer?.Message?.To[0]) == true))
                     {
-                        Log.Verbose("Process: KeySyncWizard in Step 2. Blocking decryption.");
-                        Thread.Sleep(100);
+                        KeySyncWizard.Wizard?.AddToReceivedSyncMessages(msgContainer?.Message);
                     }
 
-                    sts = this.ProcessMessage(msgContainer.Message,
+                    // Define decryption flags
+                    decryptionFlags = msgContainer.IsInSecureStore ? pEpDecryptFlags.pEpDecryptFlagUntrustedServer : pEpDecryptFlags.pEpDecryptFlagsNone;
+                    PEPMessage message = msgContainer.Message;
+
+                    sts = this.ProcessMessage(ref message,
                                               msgContainer.MessageCreationStatus,
                                               msgContainer.IsInSecureStore,
                                               msgContainer.IsInSentFolder,
@@ -191,7 +185,7 @@
                                               out mirrorMessage,
                                               out processedMessage,
                                               out processedRating,
-                                              out decryptionFlags);
+                                              ref decryptionFlags);
 
                     if ((decryptionFlags == pEpDecryptFlags.pEpDecryptFlagConsume) ||
                         (decryptionFlags == pEpDecryptFlags.pEpDecryptFlagIgnore))
@@ -202,7 +196,7 @@
                     else
                     {
                         processedMessageContainer.DecryptionFlags = decryptionFlags;
-                        processedMessageContainer.Message = processedMessage;
+                        processedMessageContainer.Message = (decryptionFlags.HasFlag(pEpDecryptFlags.pEpDecryptFlagSrcModified)) ? message : processedMessage;
 
                         if (processedMessage != null)
                         {
@@ -273,9 +267,6 @@
                     // Complete message processing
                     if (msgContainer.Error == null)
                     {
-                        // Check for sync messages
-                        this.CheckForSyncMessage(msgContainer.Message, msgContainer.DecryptionFlags);
-
                         // If Force Protection Message, process accordingly
                         if (string.IsNullOrEmpty(msgContainer.Message?.ForceProtectionId) == false)
                         {
@@ -405,7 +396,7 @@
         /// </summary>
         /// <param name="message">The message to check.</param>
         /// <param name="flags">The decrypt flags.</param>
-        private void CheckForSyncMessage(PEPMessage message, pEpDecryptFlags flags)
+        private void CheckForSyncMessage(PEPMessage message, ref pEpDecryptFlags flags)
         {
             try
             {
@@ -464,6 +455,14 @@
                             Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
                             MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
                         }
+
+                        // Delete message if necessary
+                        if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.pEp) &&
+                            (string.IsNullOrEmpty(message?.KeyImport) == false) &&
+                            (KeySyncWizard.Wizard?.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))
+                        {
+                            flags |= pEpDecryptFlags.pEpDecryptFlagConsume;
+                        }
                     }
                     else
                     {
@@ -477,7 +476,6 @@
             }
         }
 
-
         /// <summary>
         /// Processes the given message including any decryption where necessary.
         /// This will then return the latest pEp rating for the message.
@@ -509,7 +507,8 @@
         ///         |     |      |-- Sent folder        => No decryption needed 
         ///         |     |      |-- Not in Sent folder => Decrypt for message flags
         /// 
-        /// <param name="message">The original message to process.</param>
+        /// <param name="message">The original message to process. Can be returned modified (reencrypted). This will be
+        /// signalled by the pEpDecryptFlagSrcModified flag.</param>
         /// <param name="messageCreationStatus">The return status after creating the message.</param>
         /// <param name="mirror">The existing mirror for the original message (if any).</param>
         /// <param name="isInSecureStore">Whether the message being processed is in a secure (untrusted) store.</param>
@@ -520,9 +519,9 @@
         /// <param name="outProcessedMessage">The processed message. This will contain any updated data for either 
         /// the original message or the mirror. Use the 'outIsMirror' pararameter to determine which.</param>
         /// <param name="outProcessedRating">The processed rating of the message.</param>
-        /// <param name="outDecryptionFlags">The output flags after decrypting the message (if it was decrypted).</param>
+        /// <param name="decryptionFlags">The output flags after decrypting the message (if it was decrypted).</param>
         /// <returns>The status of the method.</returns>
-        public Globals.ReturnStatus ProcessMessage(PEPMessage message,
+        public Globals.ReturnStatus ProcessMessage(ref PEPMessage message,
                                                    Globals.ReturnStatus messageCreationStatus,
                                                    bool isInSecureStore,
                                                    bool isInSentFolder,
@@ -530,12 +529,11 @@
                                                    out PEPMessage outMirror,
                                                    out PEPMessage outProcessedMessage,
                                                    out pEpRating outProcessedRating,
-                                                   out pEpDecryptFlags outDecryptionFlags)
+                                                   ref pEpDecryptFlags decryptionFlags)
         {
             bool success = true;
             bool sentItem = false;
             string[] decryptionKeyList;
-            pEpDecryptFlags decryptionFlags = pEpDecryptFlags.pEpDecryptFlagsNone;
             PEPMessage processedMessage = null;
             PEPMessage mirror = null;
             pEpRating processedRating = pEpRating.pEpRatingUndefined;
@@ -569,10 +567,10 @@
                                 Log.Verbose("ProcessMessage: Secure message");
 
                                 // Decrypt message
-                                success = this.Decrypt(message,
+                                success = this.Decrypt(ref message,
                                                        out processedMessage,
                                                        out decryptionKeyList,
-                                                       out decryptionFlags,
+                                                       ref decryptionFlags,
                                                        out decryptionRating);
 
                                 if (success == false)
@@ -607,10 +605,10 @@
                                 Log.Verbose("ProcessMessage: In secure store or never unprotected");
 
                                 // Decrypt message
-                                success = this.Decrypt(message,
+                                success = this.Decrypt(ref message,
                                                        out processedMessage,
                                                        out decryptionKeyList,
-                                                       out decryptionFlags,
+                                                       ref decryptionFlags,
                                                        out decryptionRating);
 
                                 if (success)
@@ -632,10 +630,10 @@
                                 Log.Verbose("ProcessMessage: Unsecure (trusted) store");
 
                                 // Decrypt message
-                                success = this.Decrypt(message,
+                                success = this.Decrypt(ref message,
                                                        out processedMessage,
                                                        out decryptionKeyList,
-                                                       out decryptionFlags,
+                                                       ref decryptionFlags,
                                                        out decryptionRating);
 
                                 if (success)
@@ -673,10 +671,10 @@
                                  * The processed message itself can be ignored.
                                 */
                                 PEPMessage outMessage;
-                                this.Decrypt(message,
+                                this.Decrypt(ref message,
                                              out outMessage,
                                              out decryptionKeyList,
-                                             out decryptionFlags);
+                                             ref decryptionFlags);
                             }
 
                             /* Check all unsecure messages that are not sent to myself
@@ -684,7 +682,7 @@
                              * Although this is also done in the engine during decryption,
                              * it seems safer to only apply the round-trip Outlook mail item
                              * => PEPMessage => Outlook mail item if really needed.
-                                 */
+                             */
                             bool keyFound = false;
                             bool sentToMyself = false;
 
@@ -745,7 +743,6 @@
             outMirror = mirror;
             outProcessedMessage = processedMessage;
             outProcessedRating = processedRating;
-            outDecryptionFlags = decryptionFlags;
 
             return status;
         }
@@ -840,14 +837,6 @@
 
             Log.Verbose("ProcessSentMessage: Started");
 
-            // Check if we have an extra key for sync messages and add it
-            if (string.IsNullOrEmpty(KeySyncWizard.Wizard?.Partner?.Fingerprint) == false)
-            {
-                List<string> eKeys = extraKeys?.ToList<string>() ?? new List<string>();
-                eKeys.Add(KeySyncWizard.Wizard.Partner.Fingerprint);
-                extraKeys = eKeys.ToArray<string>();
-            }
-
             // Force the working message to outgoing direction.
             // This protects mostly for outgoing rating calculation which requires it.
             // However, if the message is ever incoming direction here, a failure occured elsewhere.
@@ -1214,6 +1203,19 @@
 
         /// <summary>
         /// Decrypts the given pEp message.
+        /// This is a wrapper for special cases where we don't need the actual result.
+        /// </summary>
+        /// <param name="sourceMessage">The message to decrypt.</param>
+        /// <returns>True if decryption was considered successful, otherwise false.</returns>
+        public bool Decrypt(PEPMessage sourceMessage)
+        {
+            PEPMessage outMessage;
+
+            return this.Decrypt(sourceMessage, out outMessage);
+        }
+
+        /// <summary>
+        /// Decrypts the given pEp message.
         /// This is a wrapper for special cases where we don't need to take care of
         /// rating, key list or flags.
         /// </summary>
@@ -1224,10 +1226,10 @@
                             out PEPMessage decryptedMessage)
         {
             string[] keyList;
-            pEpDecryptFlags flags;
+            pEpDecryptFlags flags = pEpDecryptFlags.pEpDecryptFlagsNone;
             pEpRating rating;
 
-            return this.Decrypt(sourceMessage, out decryptedMessage, out keyList, out flags, out rating);
+            return this.Decrypt(ref sourceMessage, out decryptedMessage, out keyList, ref flags, out rating);
         }
 
         /// <summary>
@@ -1240,13 +1242,13 @@
         /// <param name="flags">Decryption flags by the engine.</param>
         /// <param name="rating">The output pEp rating after decryption.</param>
         /// <returns>True if decryption was considered successful, otherwise false.</returns>
-        public bool Decrypt(PEPMessage sourceMessage,
+        public bool Decrypt(ref PEPMessage sourceMessage,
                             out PEPMessage destMessage,
                             out string[] keyList,
-                            out pEpDecryptFlags flags,
+                            ref pEpDecryptFlags flags,
                             out pEpRating rating)
         {
-            rating = this.Decrypt(sourceMessage, out destMessage, out keyList, out flags);
+            rating = this.Decrypt(ref sourceMessage, out destMessage, out keyList, ref flags);
 
             if ((rating == pEpRating.pEpRatingB0rken) ||
                 (rating == pEpRating.pEpRatingUndefined) ||
@@ -1269,18 +1271,17 @@
         /// <param name="keyList">The output keylist used to decrypt.</param>
         /// <param name="flags">Decryption flags by the engine.</param>
         /// <returns>The pEp rating after decryption.</returns>
-        public pEpRating Decrypt(PEPMessage sourceMessage,
+        public pEpRating Decrypt(ref PEPMessage sourceMessage,
                                  out PEPMessage destMessage,
                                  out string[] keyList,
-                                 out pEpDecryptFlags flags)
+                                 ref pEpDecryptFlags flags)
         {
             bool success = false;
-            TextMessage src;
+            TextMessage src = new TextMessage();
             TextMessage dst = new TextMessage();
             string[] dstKeyList = Globals.ThisAddIn.Settings.ExtraKeys ?? new string[0];
             pEpRating rating = pEpRating.pEpRatingCannotDecrypt;
             Globals.ReturnStatus sts;
-            flags = pEpDecryptFlags.pEpDecryptFlagsNone;
 
             Log.Verbose("Decrypt started.");
             Log.SensitiveData("Decrypt: Decrypting " + sourceMessage?.Id);
@@ -1291,7 +1292,7 @@
                 try
                 {
                     src = sourceMessage.ToCOMType();
-                    rating = ThisAddIn.PEPEngine.DecryptMessage(src, out dst, ref dstKeyList, ref flags);
+                    rating = ThisAddIn.PEPEngine.DecryptMessage(ref src, out dst, ref dstKeyList, ref flags);
                     success = true;
                 }
                 catch (COMException ex)
@@ -1316,12 +1317,24 @@
                 // Copy over lost properties
                 destMessage.SetNonEnginePropertiesFrom(sourceMessage);
                 keyList = dstKeyList;
+
+                // Replace original if needed
+                if (flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagSrcModified))
+                {
+                    PEPMessage reencryptedMessage;
+                    sts = PEPMessage.Create(src, out reencryptedMessage);
+                    reencryptedMessage.SetNonEnginePropertiesFrom(sourceMessage);
+                    sourceMessage = reencryptedMessage;
+                }
             }
             else
             {
                 destMessage = null;
                 keyList = new string[0];
-            }            
+            }
+
+            // Check for sync message
+            this.CheckForSyncMessage((rating == pEpRating.pEpRatingUnencrypted) ? sourceMessage : destMessage, ref flags);
 
             Log.SensitiveData("Decrypt: Complete. " + sourceMessage?.Id);
 
--- a/PEPMessage.cs	Thu May 10 12:18:14 2018 +0200
+++ b/PEPMessage.cs	Tue May 22 11:35:06 2018 +0200
@@ -1549,14 +1549,19 @@
         /// Important: Setting this to true for outgoing messages can cause problems with Exchange accounts.</param>
         /// <param name="setRecipients">Whether to set the message recipients manually. This should normally be set to true
         /// for all common messages and makes only sense to be omitted in special cases like a FPP reply message.</param>
+        /// <param name="convertToPGPMIMEAttachment">Whether to convert the message into a PGP/MIME attachment if needed.
+        /// The default behaviour is to convert if the message is PGP/MIME encrypted, which is needed for all outgoing messages
+        /// in order for Outlook to send the message correctly. For special cases like when using EncryptForSelf, we might not 
+        /// want ot do that, so the parameter can be set to false.</param>
         /// <returns>The status of the method.</returns>
         public Globals.ReturnStatus ApplyTo(Outlook.MailItem omi,
                                             bool setInternalHeaderFields,
                                             bool setSender,
-                                            bool setRecipients = true)
+                                            bool setRecipients = true,
+                                            bool? convertToPGPMIMEAttachment = null)
         {
             bool fromRecipientRemoved = false;
-            bool isPGPMIMEMsg = this.IsPGPMIMEEncrypted;
+            bool isPGPMIMEMsg = convertToPGPMIMEAttachment ?? this.IsPGPMIMEEncrypted;
             byte[] bytes;
             Outlook.Attachments attachments = null;
             Outlook.Recipient newRecipient = null;
--- a/PEPSettings.cs	Thu May 10 12:18:14 2018 +0200
+++ b/PEPSettings.cs	Tue May 22 11:35:06 2018 +0200
@@ -1866,7 +1866,6 @@
             protected string        _MirrorStoreId;
             protected string        _SentFolderEntryId;
             protected string        _SmtpAddress;
-            protected string        _StoreId;
             protected string        _Type;
             protected string        _UserName;
 
--- a/Properties/Resources.Designer.cs	Thu May 10 12:18:14 2018 +0200
+++ b/Properties/Resources.Designer.cs	Tue May 22 11:35:06 2018 +0200
@@ -740,6 +740,24 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Back.
+        /// </summary>
+        public static string KeySyncWizard_BackButtonText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_BackButtonText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
+        /// </summary>
+        public static string KeySyncWizard_ErrorExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_ErrorExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Error.
         /// </summary>
         public static string KeySyncWizard_ErrorText {
@@ -749,6 +767,15 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to Export my private key to the other device.
+        /// </summary>
+        public static string KeySyncWizard_ExportOwnPrivateKey {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_ExportOwnPrivateKey", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to Finish.
         /// </summary>
         public static string KeySyncWizard_Finish {
@@ -767,6 +794,89 @@
         }
         
         /// <summary>
+        ///   Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep1ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep1ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to If you initiated a key import for the following account, please click Start.
+        ///
+        ///If this was not you, please cancel..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep1NonInitiatorExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep1NonInitiatorExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
+        /// </summary>
+        public static string KeySyncWizard_PEPStep2ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep2ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Importing key....
+        /// </summary>
+        public static string KeySyncWizard_PEPStep3ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep3ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key import successful!.
+        /// </summary>
+        public static string KeySyncWizard_PEPStep4ExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPStep4ExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key successfully exported!.
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessExport {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessExport", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Key successfully imported!.
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessImport {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessImport", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The key from your other device will now also be used to decrypt messages..
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessOtherKeyUsed {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
+        /// </summary>
+        public static string KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Looks up a localized string similar to To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:  
         ///
         ///1. has your public PGP key attached and
@@ -788,98 +898,56 @@
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+        ///   Looks up a localized string similar to A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain..
         /// </summary>
-        public static string KeySyncWizard_Step1PEPExplanationText {
+        public static string KeySyncWizard_PGPStep1ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep1ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Please import your public p≡p key on your PGP device and reply with a message that:  
-        ///
-        ///1. has your public PGP key attached and
-        ///2. is encrypted with the p≡p key you just imported.
+        ///   Looks up a localized string similar to In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key..
         /// </summary>
-        public static string KeySyncWizard_Step1PGPExplanationText {
+        public static string KeySyncWizard_PGPStep2ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PGPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep2ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to A message with your public key has been sent to yourself..
+        ///   Looks up a localized string similar to Encrypt the answer message with the public p≡p key you just imported and send it..
         /// </summary>
-        public static string KeySyncWizard_Step1PGPSubtitleText {
+        public static string KeySyncWizard_PGPStep3ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step1PGPSubtitleText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
-        /// </summary>
-        public static string KeySyncWizard_Step2PEPExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step2PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep3ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
         ///   Looks up a localized string similar to Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match..
         /// </summary>
-        public static string KeySyncWizard_Step2PGPExplanationText {
+        public static string KeySyncWizard_PGPStep5ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step2PGPExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to Importing key....
-        /// </summary>
-        public static string KeySyncWizard_Step3PEPExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step3PEPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep5ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Please send now another reply message that:  
-        ///
-        ///1. has your private PGP key attached and
-        ///2. is encrypted with the p≡p key you just imported.
+        ///   Looks up a localized string similar to In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key..
         /// </summary>
-        public static string KeySyncWizard_Step3PGPExplanationText {
+        public static string KeySyncWizard_PGPStep6ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step3PGPExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep6ExplanationText", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
-        /// </summary>
-        public static string KeySyncWizard_Step4ErrorExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step4ErrorExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The key from your other device will now be used as your default private key..
+        ///   Looks up a localized string similar to Encrypt the answer message again with the public p≡p key and send it..
         /// </summary>
-        public static string KeySyncWizard_Step4PEPSuccessInitiatorExplanationText {
+        public static string KeySyncWizard_PGPStep7ExplanationText {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessInitiatorExplanationText", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Looks up a localized string similar to The key from the other device can now be used to decrypt messages..
-        /// </summary>
-        public static string KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText {
-            get {
-                return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_PGPStep7ExplanationText", resourceCulture);
             }
         }
         
@@ -888,9 +956,27 @@
         ///
         ///Your private PGP key has been successfully imported and will now be used as default p≡p key..
         /// </summary>
-        public static string KeySyncWizard_Step4SuccessExplanationText {
+        public static string KeySyncWizard_PGPSuccessExplanationText {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_PGPSuccessExplanationText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Use the imported key as default key.
+        /// </summary>
+        public static string KeySyncWizard_SetImportedKeyAsDefault {
             get {
-                return ResourceManager.GetString("KeySyncWizard_Step4SuccessExplanationText", resourceCulture);
+                return ResourceManager.GetString("KeySyncWizard_SetImportedKeyAsDefault", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Start.
+        /// </summary>
+        public static string KeySyncWizard_Start {
+            get {
+                return ResourceManager.GetString("KeySyncWizard_Start", resourceCulture);
             }
         }
         
--- a/Properties/Resources.de.resx	Thu May 10 12:18:14 2018 +0200
+++ b/Properties/Resources.de.resx	Tue May 22 11:35:06 2018 +0200
@@ -651,7 +651,7 @@
     <value>Die Mailgröße überschreitet die zulässige Größenbeschränkung für die Verschlüsselung.</value>
   </data>
   <data name="Handshake_WrongFingerprint" xml:space="preserve">
-    <value>Falscher Fingerprint</value>
+    <value>Falscher Fingerabdruck</value>
   </data>
   <data name="Handshake_TrustwordsExpanderTooltipFull" xml:space="preserve">
     <value>Vollversion der Trustwords anzeigen</value>
@@ -722,22 +722,16 @@
   <data name="KeySyncWizard_Finish" xml:space="preserve">
     <value>Fertig stellen</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
-    <value>Bitte importieren Sie Ihren öffentlichen p≡p-Schlüssel auf Ihrem PGP-Gerät und senden Sie eine Antwortnachricht:  
-
-1. an die Sie Ihren öffentlichen PGP-Schlüssel anhängen und
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln</value>
+  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+    <value>Eine Nachricht mit Ihrem öffentlichen p≡p-Schlüssel wurde an Sie selbst versendet. Bitte öffnen Sie die Nachricht auf Ihrem PGP-Gerät und importieren Sie den Schlüssel in Ihren PGP-Schlüsselring.</value>
   </data>
-  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
-    <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+    <value>Erstellen Sie auf Ihrem PGP-Gerät eine Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben und hängen Sie Ihren öffentlichen PGP-Schlüssel an.</value>
   </data>
-  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
-    <value>Senden Sie nun bitte eine weitere Antwortnachricht:  
-
-1. an die Sie Ihren privaten PGP-Schlüssel anhängen und 
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln </value>
+  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+    <value>Verschlüsseln Sie die Antwortnachricht mit dem öffentlichen p≡p-Schlüssel, den Sie gerade importiert haben und versenden Sie sie.</value>
   </data>
-  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
     <value>Schlüsselimport erfolgreich
 
 Ihr privater PGP-Schlüssel wurde erfolgreich importiert und wird nun standardmäßig auch als p≡p-Schlüssel verwendet.</value>
@@ -745,23 +739,23 @@
   <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
     <value>Schlüsselimport</value>
   </data>
-  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
     <value>Der Schlüsselimportprozess wurde gestartet. Bitte stellen Sie sicher, dass Ihr anderes Gerät, von dem Sie Ihren Schlüssel importieren möchten, eingeschaltet ist.</value>
   </data>
-  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
     <value>Bitte vergleichen Sie die folgenden Trustwords mit denjenigen auf Ihrem anderen Gerät und bestätigen Sie sie, wenn sie übereinstimmen.</value>
   </data>
   <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
     <value>Es wird auf eine Antwort vom anderen Gerät gewartet...</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
-    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+    <value>Schlüsselimport erfolgreich!</value>
   </data>
-  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
     <value>Es ist ein Fehler aufgetreten. Ihr Schlüssel konnte nicht importiert werden. Bitte versuchen Sie es erneut.</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
-    <value>Der Schlüssel des anderen Geräts kann nun zum Entschlüsseln von Nachrichten verwendet werden.</value>
+  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+    <value>Schlüsselexport erfolgreich!</value>
   </data>
   <data name="KeySyncWizard_SuccessText" xml:space="preserve">
     <value>Schlüsselimport erfolgreich!</value>
@@ -769,7 +763,7 @@
   <data name="KeySyncWizard_ErrorText" xml:space="preserve">
     <value>Fehler</value>
   </data>
-  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
     <value>Schlüssel wird importiert...</value>
   </data>
   <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -781,9 +775,6 @@
   <data name="StoreContextMenu_KeyImportText" xml:space="preserve">
     <value>Schlüsselimport</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
-    <value>Eine Nachricht mit Ihrem öffentlichen Schlüssel wurde an Sie selbst versendet.</value>
-  </data>
   <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
     <value>Um mit dem Schlüsselimport fortzufahren, importieren Sie bitte den angehängten öffentlichen p≡p-Schlüssel und senden Sie eine Antwortnachricht:  
 
@@ -793,4 +784,39 @@
   <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
     <value>p≡p-Schlüsselimport</value>
   </data>
+  <data name="KeySyncWizard_Start" xml:space="preserve">
+    <value>Start</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+    <value>Wenn Sie einen Schlüsselimport von einem anderen Gerät gestartet haben, klicken Sie bitte auf Start.
+
+Andernfalls klicken Sie bitte auf Abbrechen.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+    <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+    <value>Erstellen Sie auf Ihrem PGP-Gerät eine neue Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben. Hängen Sie nun bitte Ihren privaten PGP-Schlüssel an.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+    <value>Verschlüsseln Sie die Antwortnachricht nun wieder mit dem öffentlichen p≡p-Schlüssel und versenden Sie sie.</value>
+  </data>
+  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+    <value>Zurück</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+    <value>Schlüsselimport erfolgreich!</value>
+  </data>
+  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+    <value>Meinen privaten Schlüssel auf das andere Gerät exportieren</value>
+  </data>
+  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+    <value>Den importierten Schlüssel standardmäßig verwenden</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+    <value>Der Schlüssel von Ihrem anderen Gerät kann nun ebenfalls zum Entschlüsseln verwendet werden.</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+    <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+  </data>
 </root>
\ No newline at end of file
--- a/Properties/Resources.resx	Thu May 10 12:18:14 2018 +0200
+++ b/Properties/Resources.resx	Tue May 22 11:35:06 2018 +0200
@@ -820,22 +820,16 @@
   <data name="KeySyncWizard_Finish" xml:space="preserve">
     <value>Finish</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
-    <value>Please import your public p≡p key on your PGP device and reply with a message that:  
-
-1. has your public PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+  <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+    <value>A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain.</value>
   </data>
-  <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
-    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+  <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+    <value>In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key.</value>
   </data>
-  <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
-    <value>Please send now another reply message that:  
-
-1. has your private PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+  <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+    <value>Encrypt the answer message with the public p≡p key you just imported and send it.</value>
   </data>
-  <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
     <value>Key successfully imported
 
 Your private PGP key has been successfully imported and will now be used as default p≡p key.</value>
@@ -843,10 +837,10 @@
   <data name="KeySyncWizard_WindowTitle" xml:space="preserve">
     <value>Key Import</value>
   </data>
-  <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
     <value>The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key.</value>
   </data>
-  <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
     <value>Please compare the following Trustwords with the ones on your other device and confirm if they match.</value>
   </data>
   <data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
@@ -855,14 +849,14 @@
   <data name="KeySyncWizard_Next" xml:space="preserve">
     <value>Next</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
-    <value>The key from your other device will now be used as your default private key.</value>
+  <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+    <value>Key successfully imported!</value>
   </data>
-  <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
     <value>An error occured. Your key could not be imported correctly. Please try again.</value>
   </data>
-  <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
-    <value>The key from the other device can now be used to decrypt messages.</value>
+  <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+    <value>Key successfully exported!</value>
   </data>
   <data name="KeySyncWizard_SuccessText" xml:space="preserve">
     <value>Key import successful!</value>
@@ -870,7 +864,7 @@
   <data name="KeySyncWizard_ErrorText" xml:space="preserve">
     <value>Error</value>
   </data>
-  <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+  <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
     <value>Importing key...</value>
   </data>
   <data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -885,9 +879,6 @@
   <data name="ImageLogoIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\resources\imagelogoicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
-  <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
-    <value>A message with your public key has been sent to yourself.</value>
-  </data>
   <data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
     <value>To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:  
 
@@ -897,4 +888,39 @@
   <data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
     <value>p≡p Key Import</value>
   </data>
+  <data name="KeySyncWizard_Start" xml:space="preserve">
+    <value>Start</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+    <value>If you initiated a key import for the following account, please click Start.
+
+If this was not you, please cancel.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+    <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+    <value>In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key.</value>
+  </data>
+  <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+    <value>Encrypt the answer message again with the public p≡p key and send it.</value>
+  </data>
+  <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+    <value>Back</value>
+  </data>
+  <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+    <value>Key import successful!</value>
+  </data>
+  <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+    <value>Export my private key to the other device</value>
+  </data>
+  <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+    <value>Use the imported key as default key</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+    <value>The key from your other device will now be used as your default private key.</value>
+  </data>
+  <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+    <value>The key from your other device will now also be used to decrypt messages.</value>
+  </data>
 </root>
\ No newline at end of file
--- a/ThisAddIn.cs	Thu May 10 12:18:14 2018 +0200
+++ b/ThisAddIn.cs	Tue May 22 11:35:06 2018 +0200
@@ -741,10 +741,12 @@
         /// <param name="validateSendingAccount">Validates that the SendingAccount matches the From identity of the given message.
         /// This can catch situations (and throw exceptions) where the default account would be used instead.</param>
         /// <param name="processMessage">Whether or not to process this message through the pEp engine.</param>
+        /// <param name="setKeyImportHeader">Whether or not to process this message through the pEp engine.</param>
         internal void CreateAndSendMessage(PEPMessage message,
                                            bool deleteAfterSend,
                                            bool validateSendingAccount,
-                                           bool processMessage = false)
+                                           bool processMessage = false,
+                                           bool setKeyImportHeader = false)
         {
             Outlook.MailItem newItem;
             Globals.ReturnStatus sts;
@@ -777,10 +779,31 @@
                     MapiHelper.SetProperty(newItem, MapiProperty.PidLidUseTnef, false);
 
                     // If ForceUnencrypted property is set, add it to mail item
+                    bool save = false;
                     if (message.ForceUnencrypted)
                     {
                         newItem.SetPEPProperty(MailItemExtensions.PEPProperty.ForceUnencrypted, true);
-                        newItem.Save();
+                        save = true;
+                    }
+
+                    // Set KeyImport header if necessary
+                    if (setKeyImportHeader)
+                    {
+                        newItem.SetPEPProperty(MailItemExtensions.PEPProperty.KeyImport, message.KeyImport);
+                        save = true;
+                    }
+
+                    // Save if necessary
+                    if (save)
+                    {
+                        try
+                        {
+                            newItem.Save();
+                        }
+                        catch (Exception ex)
+                        {
+                            Log.Error("CreateAndSendMessage: Error saving new item. " + ex.ToString());
+                        }
                     }
 
                     /* Send
--- a/UI/FormControlPreviewMessage.xaml.cs	Thu May 10 12:18:14 2018 +0200
+++ b/UI/FormControlPreviewMessage.xaml.cs	Tue May 22 11:35:06 2018 +0200
@@ -178,7 +178,14 @@
                     {
                         Regex r = new Regex("<head(.*?)>", RegexOptions.IgnoreCase);
                         Match m2 = r.Match(htmlString);
-                        htmlString = r.Replace(htmlString, m2.Value + "<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>", 1);
+                        if (string.IsNullOrEmpty(m2.Value))
+                        {
+                            htmlString = "<head><meta http-equiv='Content-Type' content='text/html;charset=UTF-8'></head>" + htmlString;
+                        }
+                        else
+                        {
+                            htmlString = r.Replace(htmlString, m2.Value + "<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>", 1);
+                        }
                     }
                     else
                     {
--- a/UI/HandshakeDialog.xaml.cs	Thu May 10 12:18:14 2018 +0200
+++ b/UI/HandshakeDialog.xaml.cs	Tue May 22 11:35:06 2018 +0200
@@ -4,7 +4,6 @@
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Linq;
-using System.Runtime.InteropServices;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
--- a/UI/HandshakeItemsControl.xaml	Thu May 10 12:18:14 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml	Tue May 22 11:35:06 2018 +0200
@@ -201,7 +201,8 @@
                                   SelectedValuePath="Key"
                                   SelectedValue="{Binding Path=TrustwordsCulture, Mode=TwoWay}"
                                   IsEnabled="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Trustwords}"
-                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}" />
+                                  Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}"
+                                  Visibility="{Binding Path=Mode, Converter={StaticResource IsNotSyncModeToVisibility}}" />
                     </StackPanel>
 
                     <!-- Trustwords -->
--- a/UI/HandshakeItemsControl.xaml.cs	Thu May 10 12:18:14 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml.cs	Tue May 22 11:35:06 2018 +0200
@@ -127,5 +127,15 @@
                 handshakeItem.AreTrustwordsExpanded = ((sender as Expander)?.IsExpanded == true);
             }
         }
+
+        /// <summary>
+        /// Raises the property changed event, if possible, with the given arguments.
+        /// </summary>
+        /// <param name="propertyName">The name of the property that changed.</param>
+        private void RaisePropertyChangedEvent(string propertyName)
+        {
+            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+            return;
+        }
     }
 }
--- a/UI/KeySyncWizard.xaml	Thu May 10 12:18:14 2018 +0200
+++ b/UI/KeySyncWizard.xaml	Tue May 22 11:35:06 2018 +0200
@@ -23,94 +23,92 @@
         <ResourceDictionary>
             <!-- Converters -->
             <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
-            <local:InvertBoolConverter x:Key="InvertBool" />
-            <local:ValueConverterGroup x:Key="IsWizardStateToVisibility">
-                <local:IsWizardStateConverter />
-                <BooleanToVisibilityConverter />
-            </local:ValueConverterGroup>
-            <local:ValueConverterGroup x:Key="IsNotWizardStateToVisibility">
-                <local:IsWizardStateConverter />
+            <local:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibility" />
+            <local:ValueConverterGroup x:Key="IsStringNotNullOrEmptyToVisibility">
+                <local:IsStringEmptyConverter />
                 <local:InvertBoolConverter />
                 <BooleanToVisibilityConverter />
             </local:ValueConverterGroup>
-            <local:ValueConverterGroup x:Key="IsNotWizardStateToBool">
-                <local:IsWizardStateConverter />
-                <local:InvertBoolConverter />
-            </local:ValueConverterGroup>
+            <local:IsWizardTypeConverter x:Key="IsWizardType" />
+
+            <!--Dictionary-->
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="pack://application:,,,/pEp;component/Resources/Dictionary.xaml" />
+            </ResourceDictionary.MergedDictionaries>
         </ResourceDictionary>
     </Window.Resources>
 
-    <!--The window content-->
-    <StackPanel Width="470">
-
-        <!--Title section-->
-        <Grid Background="White"
-              Margin="0">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*" />
-                <ColumnDefinition Width="Auto" />
-            </Grid.ColumnDefinitions>
-            <StackPanel Grid.Column="0">
-                <TextBlock Margin="20,10,10,10"
-                       Text="{Binding Path=TitleText}"
-                       FontWeight="Bold" 
-                       VerticalAlignment="Center"/>
-                <TextBlock Margin="20,10,10,10"
-                           Text="{Binding Path=SubtitleText}"
-                           TextWrapping="Wrap"
-                           VerticalAlignment="Center" />
-            </StackPanel>
-            <Image Grid.Column="1"
-                   Stretch="Uniform"
-                   Height="40"
-                   VerticalAlignment="Center"
-                   HorizontalAlignment="Right"
-                   Margin="20,10"
-                   Source="pack://application:,,,/pEp;component/Resources/ImageLogoMedium.png">
-            </Image>
-        </Grid>
-
-        <Separator Margin="0,0,0,20"
-                   Background="LightGray" />
+    <StackPanel Margin="10"
+                Width="470">
 
         <!--Information section-->
-        <TextBlock Text="{Binding Path=ExplanationText}"
+        <TextBlock Text="{Binding Path=CurrentState.TitleText}"
                    TextWrapping="Wrap"
-                   Margin="20,10" />
+                   Margin="5,5,5,15" />
+
+        <!--User name section-->
+        <TextBlock Text="{Binding Path=CurrentState.UserText}"
+                   Padding="10"
+                   MinHeight="80"
+                   Background="White"
+                   FontWeight="DemiBold"
+                   Visibility="{Binding Path=CurrentState.IsUserTextVisible, Converter={StaticResource BoolToVisibility}}" />
 
         <!--Identities section-->
-        <local:HandshakeItemsControl Margin="10,0"
-                                     ItemsSource="{Binding Path=Items}"
-                                     Visibility="{Binding Path=State, Converter={StaticResource IsWizardStateToVisibility}, ConverterParameter=Step2}" />
+        <StackPanel Visibility="{Binding Path=CurrentState.AreTrustwordsVisible, Converter={StaticResource BoolToVisibility}}">
+            <local:HandshakeItemsControl ItemsSource="{Binding Path=Items}" />
+            <StackPanel Orientation="Horizontal"
+                        Margin="5,10,5,0"
+                        Visibility="{Binding Path=IsInitiator, Converter={StaticResource BoolToVisibility}}">
+                <CheckBox VerticalAlignment="Center"
+                          IsChecked="{Binding Path=SetImportedKeyAsDefault}" />
+                <Label Content="{x:Static p:Resources.KeySyncWizard_SetImportedKeyAsDefault}"
+                       MouseUp="LabelSetImportedKeyAsDefault_MouseUp"/>
+            </StackPanel>
+            <StackPanel Orientation="Horizontal"
+                        Margin="5,0,5,5">
+                <StackPanel.Visibility>
+                    <MultiBinding Converter="{StaticResource MultiBooleanToVisibility}">
+                        <Binding Path="IsInitiator" />
+                        <Binding Path="Type" Converter="{StaticResource IsWizardType}" ConverterParameter="pEp" />
+                    </MultiBinding>
+                </StackPanel.Visibility>
+                <CheckBox VerticalAlignment="Center"
+                          IsChecked="{Binding Path=ExportPrivateKey}" />
+                <Label Content="{x:Static p:Resources.KeySyncWizard_ExportOwnPrivateKey}" 
+                       MouseUp="LabelExportPrivateKey_MouseUp"/>
+            </StackPanel>
+        </StackPanel>
 
-        <Separator Margin="10,20,10,0" 
-                   Background="LightGray"/>
+        <!--Subtitle section-->
+        <TextBlock Text="{Binding Path=CurrentState.SubtitleText}"
+                   TextWrapping="Wrap"
+                   Margin="5,15"
+                   Visibility="{Binding Path=CurrentState.SubtitleText, Converter={StaticResource IsStringNotNullOrEmptyToVisibility}}" />
 
         <!--Buttons section-->
-        <Grid>
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*" />
-                <ColumnDefinition Width="Auto" />
-            </Grid.ColumnDefinitions>
-            <StackPanel Grid.Column="1"
-                        Margin="10"
-                        Orientation="Horizontal">
-                <Button x:Name="OKNextButton"
-                        Margin="5"
-                        Padding="5,2"
-                        MinWidth="70"
-                        IsEnabled="{Binding Path=State, Converter={StaticResource IsNotWizardStateToBool}, ConverterParameter=Step1|Step3}"
-                        Click="OKNextButton_Click"
-                        Content="{Binding Path=NextButtonText}" />
-                <Button x:Name="CancelButton"
-                        Margin="5"
-                        Padding="5,2"
-                        MinWidth="70"
-                        Click="CancelButton_Click"
-                        Visibility="{Binding Path=State, Converter={StaticResource IsNotWizardStateToVisibility}, ConverterParameter=Step4}"
-                        Content="{x:Static p:Resources.Options_CancelText}" />
-            </StackPanel>
-        </Grid>
+        <StackPanel Margin="0,10"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Right">
+            <Button x:Name="BackButton"
+                    Style="{StaticResource StyleCancelButton}"
+                    Margin="0,5,5,5"
+                    Click="BackButton_Click"
+                    Content="{x:Static p:Resources.KeySyncWizard_BackButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsBackButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+            <Button x:Name="AcceptButton"
+                    Style="{StaticResource StyleConfirmButton}"
+                    Margin="5"
+                    Click="AcceptButton_Click"
+                    Content="{Binding Path=CurrentState.AcceptButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsAcceptButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+            <Button x:Name="CancelButton"
+                    Margin="5,5,0,5"
+                    Style="{StaticResource StyleWrongButton}"
+                    Click="CancelButton_Click"
+                    Content="{Binding Path=CurrentState.CancelButtonText}"
+                    Visibility="{Binding Path=CurrentState.IsCancelButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+        </StackPanel>
     </StackPanel>
 </Window>
 
--- a/UI/KeySyncWizard.xaml.cs	Thu May 10 12:18:14 2018 +0200
+++ b/UI/KeySyncWizard.xaml.cs	Tue May 22 11:35:06 2018 +0200
@@ -3,7 +3,10 @@
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
+using System.Threading.Tasks;
 using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
 using Outlook = Microsoft.Office.Interop.Outlook;
 
 namespace pEp.UI
@@ -15,8 +18,23 @@
                                            INotifyPropertyChanged,
                                            Interfaces.IReset
     {
-        public const string PEP_PGP_SYNC_MESSAGE_SUBJECT    = "p≡p Key Import";
-        public const string PEP_PGP_SYNC_MESSAGE_BODY       = "";
+        /// <summary>
+        /// Defines the step this wizard is currently in.
+        /// </summary>
+        public enum Steps
+        {
+            Undefined,
+            Success,
+            Error,
+            Step1,
+            Step2,
+            Step3,
+            Step4,
+            Step5,
+            Step6,
+            Step7,
+            Step8
+        }
 
         /// <summary>
         /// The message types for sync messages.
@@ -40,66 +58,33 @@
         }
 
         /// <summary>
-        /// Defines the state (step) this wizard is currently in.
-        /// </summary>
-        public enum WizardState
-        {
-            /// <summary>
-            /// Undefined state. Should never occur.
-            /// </summary>
-            Undefined,
-
-            /// <summary>
-            /// First state on the side of the device that initiated
-            /// the process. Will send a first message and wait for
-            /// an answer message from the other device.
-            /// </summary>
-            Step1,
-
-            /// <summary>
-            /// Showing the Trustwords dialog, waiting for user input.
-            /// </summary>
-            Step2,
-
-            /// <summary>
-            /// Trustwords are accepted, the private key is being sent.
-            /// Waiting for key from other device.
-            /// </summary>
-            Step3,
-
-            /// <summary>
-            /// Process has finished (successfully or not).
-            /// </summary>
-            Step4
-        }
-
-        /// <summary>
         /// Event raised when a property is changed on a component.
         /// </summary>
         public event PropertyChangedEventHandler PropertyChanged;
 
-        private string                                  _ExplanationText;
+        private WizardState                             _CurrentState;
+        private bool                                    _ExportPrivateKey;
+        private bool                                    _IsInitiator;
         private ObservableCollection<HandshakeItem>     _Items;
         private PEPIdentity                             _Myself;
-        private string                                  _NextButtonText;
         private PEPIdentity                             _Partner;
-        private WizardState                             _State;
-        private string                                  _SubtitleText;
-        private bool                                    _Success;
-        private string                                  _TitleText;
+        private Steps                                   _Step;
+        private bool                                    _SetImportedKeyAsDefault;
         private WizardType                              _Type;
 
-        public static KeySyncWizard                     Wizard = null;
+        private bool                                    privateKeyImported = false;
+        private List<MessageTypes>                      sentMessages                = new List<MessageTypes>();
+        private List<PEPMessage>                        receivedSyncMessages        = new List<PEPMessage>();
+        private List<WizardState>                       states = new List<WizardState>();
+        private object                                  mutexReceivedSyncMessages   = new object();
 
-        private bool                                    isInitiator         = false;
-        private List<MessageTypes>                      sentMessages = new List<MessageTypes>();
+        public static KeySyncWizard                     Wizard = null;
 
         /// <summary>
         /// Default constructor
         /// </summary>
         public KeySyncWizard()
-        {
-        }
+        { }
 
         /// <summary>
         /// Constructor to create a new key sync wizard.
@@ -118,57 +103,25 @@
                 KeySyncWizard.Wizard.Close();
             }
 
+            // Reset all values
+            this.Reset();
+
             // Initialize the window
             InitializeComponent();
 
             // Set current wizard
             KeySyncWizard.Wizard = this;
 
-            // Reset all values
-            this.Reset();
-
             // Initialize the wizard
-            this.InitializeWizard(type, myself, partnerFpr);
-
-            // Set if wizard is the one that has started the sync process
-            this.isInitiator = isInitiator;
+            this.InitializeWizard(isInitiator, type, myself, partnerFpr);
 
             // Attach event handler for new sync messages
             MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
 
-            // Either send initial or answer message
-            if (isInitiator)
-            {
-                // Send initial message
-                this.SendSyncMessage(MessageTypes.InitialMessage);
-            }
-            else
+            // Send initial message if necessary
+            if (this.IsInitiator)
             {
-                try
-                {
-                    // Update own identity
-                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
-
-                    // Create handshake item
-                    if (this.CreateHandshakeItem())
-                    {
-                        // Send answer message with pub key
-                        this.SendSyncMessage(MessageTypes.PublicKeyMessage);
-
-                        // Go to next step
-                        this.GoToNextStep();
-                    }
-                    else
-                    {
-                        Log.Error("KeySyncWizard: Error creating handshake item.");
-                        this.GoToLastStep(false);
-                    }
-                }
-                catch (Exception ex)
-                {
-                    Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
-                    this.GoToLastStep(false);
-                }
+                this.SendSyncMessage(MessageTypes.InitialMessage);
             }
         }
 
@@ -180,15 +133,42 @@
          *************************************************************/
 
         /// <summary>
-        /// Gets or sets the explanatory text in the wizard.
+        /// Gets or sets the Items collection.
         /// </summary>
-        public string ExplanationText
+        public WizardState CurrentState
         {
-            get { return this._ExplanationText; }
+            get { return this._CurrentState; }
             set
             {
-                this._ExplanationText = value;
-                this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
+                this._CurrentState = value;
+                this.RaisePropertyChangedEvent(nameof(this.CurrentState));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether to export the private key.
+        /// </summary>
+        public bool ExportPrivateKey
+        {
+            get { return this._ExportPrivateKey; }
+            set
+            {
+                this._ExportPrivateKey = value;
+                this.RaisePropertyChangedEvent(nameof(this.ExportPrivateKey));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets whether this wizard is the one that
+        /// initiated the Key Import process.
+        /// </summary>
+        public bool IsInitiator
+        {
+            get { return this._IsInitiator; }
+            set
+            {
+                this._IsInitiator = value;
+                this.RaisePropertyChangedEvent(nameof(this.IsInitiator));
             }
         }
 
@@ -219,19 +199,6 @@
         }
 
         /// <summary>
-        /// Gets or sets the Next/Finish button's text.
-        /// </summary>
-        public string NextButtonText
-        {
-            get { return this._NextButtonText; }
-            set
-            {
-                this._NextButtonText = value;
-                this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
-            }
-        }
-
-        /// <summary>
         /// Gets or sets the sync partner.
         /// </summary>
         public PEPIdentity Partner
@@ -245,54 +212,28 @@
         }
 
         /// <summary>
-        /// Gets or sets the wizard state.
+        /// Gets or sets the current wizard step.
         /// </summary>
-        public WizardState State
+        public Steps Step
         {
-            get { return this._State; }
+            get { return this._Step; }
             set
             {
-                this._State = value;
-                this.RaisePropertyChangedEvent(nameof(this.State));
+                this._Step = value;
+                this.RaisePropertyChangedEvent(nameof(this.Step));
             }
         }
 
         /// <summary>
-        /// Gets or sets the subtitle text in the wizard.
+        /// Gets or sets whether to use the imported key as default key.
         /// </summary>
-        public string SubtitleText
+        public bool SetImportedKeyAsDefault
         {
-            get { return this._SubtitleText; }
+            get { return this._SetImportedKeyAsDefault; }
             set
             {
-                this._SubtitleText = value;
-                this.RaisePropertyChangedEvent(nameof(this.SubtitleText));
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the success state.
-        /// </summary>
-        public bool Success
-        {
-            get { return this._Success; }
-            set
-            {
-                this._Success = value;
-                this.RaisePropertyChangedEvent(nameof(this.Success));
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the title text in the wizard.
-        /// </summary>
-        public string TitleText
-        {
-            get { return this._TitleText; }
-            set
-            {
-                this._TitleText = value;
-                this.RaisePropertyChangedEvent(nameof(this.TitleText));
+                this._SetImportedKeyAsDefault = value;
+                this.RaisePropertyChangedEvent(nameof(this.SetImportedKeyAsDefault));
             }
         }
 
@@ -309,6 +250,35 @@
             }
         }
 
+        /// <summary>
+        /// Gets the user name to display in the dialog.
+        /// </summary>
+        public string UserName
+        {
+            get
+            {
+                string userName = string.Empty;
+
+                // Try to get user name in format "name (address)"
+                if (string.IsNullOrEmpty(this.Myself?.UserName) == false)
+                {
+                    userName = this.Myself.UserName;
+
+                    if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+                    {
+                        userName += " (" + this.Myself.Address + ")";
+                    }
+                }
+                // If we have no user name, just display address
+                else if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+                {
+                    userName = this.Myself.Address;
+                }
+
+                return userName;
+            }
+        }
+
         #endregion
 
         #region Event handlers
@@ -318,39 +288,195 @@
          * 
          *************************************************************/
 
+        /// <summary>
+        /// Event handler for when the OK/Next button is clicked.
+        /// </summary>
+        private void AcceptButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.CurrentState.AcceptButtonClick();
+        }
+
+        /// <summary>
+        /// Event handler for when the Back button is clicked.
+        /// </summary>
+        private void BackButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.CurrentState.BackButtonClick();
+        }
+
+        /// <summary>
+        /// Event handler for when the Cancel button is clicked.
+        /// </summary>
         private void CancelButton_Click(object sender, RoutedEventArgs e)
         {
-            this.Close();
+            this.CurrentState.CancelButtonClick();
         }
 
-        private void OKNextButton_Click(object sender, RoutedEventArgs e)
+        /// <summary>
+        /// Event handler for when a sync message arrives while the wizard is open and in progress.
+        /// </summary>
+        private void KeySyncWizard_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
         {
-            // Navigation logic
-            switch (this.State)
+            // Ignore outgoing messages
+            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
             {
-                case WizardState.Step2:
+                try
+                {
+                    // Waiting for message with public key from other device
+                    if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step1)) ||
+                        ((this.Type == WizardType.PGP) && (this.Step == Steps.Step4)))
                     {
-                        // User accepts the fingerprint. Make channel green.
-                        this.TrustKey();
+                        string partnerFpr = null;
+
+                        // Make sure the channel is not already trusted (either attack or re-processing)
+                        if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
+                        {
+                            Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
+                            return;
+                        }
+
+                        // In case of pEp sync, use header
+                        if (this.Type == WizardType.pEp)
+                        {
+                            // Public key message received. Show trustwords.
+                            partnerFpr = e.Message?.KeyImport;
+
+                            Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
+
+                            // Doublecheck that it's not the own key
+                            if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
+                            {
+                                partnerFpr = null;
+                            }
+                        }
+                        else if (this.Type == WizardType.PGP)
+                        {
+                            // In case of PGP import, use key list
+                            string[] keys = e.Message?.KeyList?.Split(',');
+                            for (int i = 0; i < keys?.Length; i++)
+                            {
+                                if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
+                                {
+                                    partnerFpr = keys[i];
+                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
+                                    break;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
+                        }
+
+                        // If we have a valid fingerprint, show Trustwords
+                        if ((this.IsInitiator) &&
+                            (string.IsNullOrEmpty(partnerFpr) == false))
+                        {
+                            // Set the partner's fingerprint
+                            this.Partner.Fingerprint = partnerFpr;
+
+                            // Marshall to main thread
+                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+                            {
+                                // Create the handshake item 
+                                if (this.CreateHandshakeItem())
+                                {
+                                    this.GoToNextStep();
+                                }
+                                else
+                                {
+                                    Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
+                                    this.GoToLastStep(false);
+                                }
+                            }));
+                        }
+                        else
+                        {
+                            Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
+                        }
                     }
-                    break;
-                /* 'Step 1' and 'Step 3' are not clickable. 
-                 * 'Step 4' finishes the process. 
-                 * 'Undefined' means an error occured.
-                 */
-                case WizardState.Step1:
-                case WizardState.Step3:
-                case WizardState.Step4:
-                case WizardState.Undefined:
-                default:
+                    // Waiting for private key message
+                    else if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step3)) ||
+                             ((this.Type == WizardType.PGP) && (this.Step == Steps.Step8)))
                     {
-                        this.Close();
+                        /* Finish the process under the following conditions:
+                         *  1. PGP key import + own private key flag
+                         *  2. pEp key import +
+                         *      a. initiator wizard + own private key flag + partner fpr in key import header
+                         *      b. not initiator wizard + trusted message + partner fpr in key import header
+                         */
+                        bool hasDecryptFlagOwnPrivateKey = e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey);
+                        if (((this.Type == WizardType.PGP) && (hasDecryptFlagOwnPrivateKey)) ||
+                            ((this.IsInitiator) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (hasDecryptFlagOwnPrivateKey)) ||
+                            ((this.IsInitiator == false) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (e.Message.Rating >= pEpRating.pEpRatingTrusted)))
+                        {
+                            // Set flag
+                            this.privateKeyImported = hasDecryptFlagOwnPrivateKey;
+
+                            // Marshall to main thread
+                            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+                            {
+                                // Set private key as default if needed
+                                bool success = false;
+                                if ((this.IsInitiator) &&
+                                    (this.SetImportedKeyAsDefault))
+                                {
+                                    try
+                                    {
+                                        pEpIdentity partner = this.Partner.ToCOMType();
+                                        ThisAddIn.PEPEngine.SetOwnKey(partner, partner.fpr);
+                                        success = true;
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        success = false;
+                                        Log.Error("AcceptButtonClick: Error setting own key. " + ex.ToString());
+                                    }
+                                }
+                                else
+                                {
+                                    success = true;
+                                }
+
+                                this.GoToLastStep(success);
+
+                            }));
+                        }
+                        else
+                        {
+                            Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. Steps: Step 3. Own private key flag is " +
+                                        e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
+                                        Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
+                                        e.Message?.KeyImport ?? "null");
+                        }
                     }
-                    break;
+                }
+                catch (Exception ex)
+                {
+                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+                }
             }
         }
 
         /// <summary>
+        /// Event handler for when the label next to the Export Private Key checkbox
+        /// is clicked.
+        /// </summary>
+        private void LabelExportPrivateKey_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            this.ExportPrivateKey = (this.ExportPrivateKey == false);
+        }
+
+        /// <summary>
+        /// Event handler for when the label next to the Set Imported Key As Default checkbox
+        /// is clicked.
+        /// </summary>
+        private void LabelSetImportedKeyAsDefault_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            this.SetImportedKeyAsDefault = (this.SetImportedKeyAsDefault == false);
+        }
+
+        /// <summary>
         /// Raises the property changed event, if possible, with the given arguments.
         /// </summary>
         /// <param name="propertyName">The name of the property that changed.</param>
@@ -361,127 +487,40 @@
         }
 
         /// <summary>
-        /// Event handler for when a sync message arrives while the wizard is open and in progress.
+        /// Shows the handshake window
         /// </summary>
-        private void KeySyncWizard_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
+        private bool ShowHandshake()
         {
-            // Ignore outgoing messages
-            if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
-            {
-                try
-                {
-                    switch (this.State)
-                    {
-                        // Step 1: get partner fingerprint and show Trustwords
-                        case WizardState.Step1:
-                            {
-                                string partnerFpr = null;
-
-                                // Make sure the channel is not already trusted (either attack or re-processing)
-                                if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
-                                {
-                                    Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
-                                    return;
-                                }
-
-                                // In case of pEp sync, use header
-                                if (this.Type == WizardType.pEp)
-                                {
-                                    // Public key message received. Show trustwords.
-                                    partnerFpr = e.Message?.KeyImport;
-
-                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
-
-                                    // Doublecheck that it's not the own key
-                                    if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
-                                    {
-                                        partnerFpr = null;
-                                    }
-                                }
-                                else if (this.Type == WizardType.PGP)
-                                {
-                                    // In case of PGP import, use key list
-                                    string[] keys = e.Message?.KeyList?.Split(',');
-                                    for (int i = 0; i < keys?.Length; i++)
-                                    {
-                                        if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
-                                        {
-                                            partnerFpr = keys[i];
-                                            Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
-                                            break;
-                                        }
-                                    }
-                                }
-                                else
-                                {
-                                    Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
-                                }
+            bool success = false;
 
-                                // If we have a valid fingerprint, show Trustwords
-                                if (string.IsNullOrEmpty(partnerFpr) == false)
-                                {
-                                    // Set the partner's fingerprint
-                                    this.Partner.Fingerprint = partnerFpr;
+            try
+            {
+                // Update own identity if necessary
+                if (string.IsNullOrEmpty(this.Myself?.Fingerprint))
+                {
+                    this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
+                }
 
-                                    // Marshall to main thread
-                                    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
-                                    {
-                                        // Create the handshake item 
-                                        if (this.CreateHandshakeItem())
-                                        {
-                                            this.GoToNextStep();
-                                        }
-                                        else
-                                        {
-                                            Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
-                                            this.GoToLastStep(false);
-                                        }
-                                    }));
-                                }
-                                else
-                                {
-                                    Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
-                                }
-                            }
-                            break;
-                        case WizardState.Step2:
-                            {
-                                Log.Verbose("KeySyncWizard_SyncMessageReceived: Nothing done. WizardState is Step 2.");
-                            }
-                            break;
-                        case WizardState.Step3:
-                            {
-                                /* Finish the process if a private key has been imported and the message
-                                 * is at least trusted.
-                                 * For pEp key import, check also that we don't import our own key.
-                                 */ 
-                                if ((e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)) &&
-                                    (e.Message.Rating >= pEpRating.pEpRatingTrusted) &&
-                                    ((e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) ||
-                                     (this.Type == WizardType.PGP)))
-                                {
-                                    this.CompleteWizard();
-                                }
-                                else
-                                {
-                                    Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. WizardState: Step 3. Own private key flag is " +
-                                                e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
-                                                Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
-                                                e.Message?.KeyImport ?? "null");
-                                }
-                            }
-                            break;
-                        case WizardState.Step4:
-                        case WizardState.Undefined:
-                        default:
-                            break;
-                    }
+                // Create handshake item
+                if (this.CreateHandshakeItem())
+                {
+                    // Set success flag
+                    success = true;
+
+                    // Send answer message with pub key
+                    this.SendSyncMessage(MessageTypes.PublicKeyMessage);
                 }
-                catch (Exception ex)
+                else
                 {
-                    Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+                    Log.Error("KeySyncWizard: Error creating handshake item.");
                 }
             }
+            catch (Exception ex)
+            {
+                Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
+            }
+
+            return success;
         }
 
         /// <summary>
@@ -506,18 +545,71 @@
          *************************************************************/
 
         /// <summary>
+        /// Adds the given PEPMessage to the list of received sync messages.
+        /// </summary>
+        /// <param name="message">The PEPMessage to add to the list.</param>
+        public void AddToReceivedSyncMessages(PEPMessage message)
+        {
+            /* Add message to list if:
+             *  1.  a. WizardType is PGP and message is secure
+             *      b. WizardType is pEp, the current step is Step 2 and the
+             *         message hasn't been sent from myself
+             *  2. Message is not in the list yet
+             *  3. List has max 5 items
+             */
+            lock (mutexReceivedSyncMessages)
+            {
+                if (((this.Type == WizardType.PGP) &&
+                     (message.IsSecure) ||
+                     ((this.Type == WizardType.pEp) &&
+                      (this.Step == Steps.Step2) &&
+                      (this.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))) &&
+                    (this.receivedSyncMessages?.Find(a => (a.Id?.Equals(message.Id) == true)) == null) &&
+                    (this.receivedSyncMessages?.Count <= 5))
+                {
+                    this.receivedSyncMessages?.Add(message);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Closes the wizard and resets the partner identity in the management.db.
+        /// </summary>
+        private void CancelWizard()
+        {
+            try
+            {
+                pEpIdentity partner = this.Partner.Copy().ToCOMType();
+
+                if (string.IsNullOrEmpty(partner.fpr) == false)
+                {
+                    Task.Factory.StartNew(new Action(() =>
+                    {
+                        ThisAddIn.PEPEngine.KeyResetTrust(partner);
+                    }), TaskCreationOptions.LongRunning);
+                }
+            }
+            catch (Exception ex)
+            {
+                Log.Error("CancelWizard: Error resetting identity. " + ex.ToString());
+            }
+
+            this.Close();
+        }
+
+        /// <summary>
         /// Completes the process and moves wizard to last step.
         /// Sets the imported private key as own key, if needed.
         /// </summary>
         private void CompleteWizard()
         {
             // Marshall to main thread
-            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
+            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
             {
                 bool success = false;
 
                 // Private key message received. Set key as default if needed.
-                if (this.isInitiator)
+                if (this.IsInitiator)
                 {
                     try
                     {
@@ -553,9 +645,10 @@
             HandshakeItem item;
             if (HandshakeItem.Create(this.Myself, this.Partner, false, out item) == Globals.ReturnStatus.Success)
             {
-                item.AreTabControlsVisible = (this.Type == WizardType.PGP);
+                item.AreTabControlsVisible = false;
                 item.ActiveTab = (this.Type == WizardType.pEp) ? HandshakeItem.Tabs.Trustwords : HandshakeItem.Tabs.Fingerprint;
                 item.AreHandshakeButtonsVisible = false;
+                item.Mode = HandshakeItem.HandshakeMode.Sync;
                 this.Items.Add(item);
 
                 success = true;
@@ -566,17 +659,658 @@
         }
 
         /// <summary>
+        /// Creates a list of wizard states that serve as model for the wizard.
+        /// The pEp Key Import process consists of the following steps:
+        ///     Step 1:
+        ///         a. Is initiator(user opened wizard): Info message that sync message has been sent.
+        ///            Waiting for answer message from other device.
+        ///         b. Is not initiator (wizard opened through sync message): Info message that key import has been started.
+        ///            Waiting for user decision to continue or abort.
+        ///     Step 2:
+        ///         - Show trustwords. User interaction: confirm or cancel.
+        ///     Step 3: 
+        ///         - Private keys have been sent. Waiting for answer message from other device.
+        ///     Step 4: 
+        ///         - Only on initiator side: Ask user if they want to set imported key as default. Next or Cancel.
+        ///     Success:
+        ///         - Key Import successfully finished.
+        ///     Error:
+        ///         - An error occured during the Key Import process.
+        /// </summary>
+        /// <returns>The list of wizard states.</returns>
+        private List<WizardState> CreatePEPWizardStates()
+        {
+            List<WizardState> states = new List<WizardState>();
+
+            try
+            {
+                // Step 1
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step1,
+
+                    // Title text
+                    TitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_PEPStep1ExplanationText : Properties.Resources.KeySyncWizard_PEPStep1NonInitiatorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Start,
+                    IsAcceptButtonVisible = (this.IsInitiator == false),
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        if (this.ShowHandshake())
+                        {
+                            this.GoToNextStep();
+                        }
+                        else
+                        {
+                            this.GoToLastStep(false);
+                        }
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_WaitingForResponseText : null
+                });
+
+                // Step 2
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step2,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PEPStep2ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = true,
+                    IsUserTextVisible = false,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.Handshake_ConfirmTrustwords,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.TrustKey();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Handshake_WrongTrustwords,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 3
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step3,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PEPStep3ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText
+                });
+
+                // Success
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Success,
+
+                    // Title text
+                    TitleText = null,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.Close();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Error
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Error,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+            }
+            catch (Exception ex)
+            {
+                states = null;
+                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+            }
+
+            return states;
+        }
+
+        /// <summary>
+        /// Creates a list of wizard states that serve as model for the wizard.
+        /// The PGP Key Import process consists of the following steps:
+        ///     Steps 1-3:
+        ///         - Instructions on how to prepare the answer message with pub key.
+        ///     Step 4: 
+        ///         - Waiting for answer message from other device.
+        ///     Step 5: 
+        ///         - Show fingerprints. Confirm or deny them.        
+        ///     Step 6 - 7: 
+        ///         - Instructions on how to prepare the answer message with private key.
+        ///     Success:
+        ///         - Key Import successfully finished.
+        ///     Error:
+        ///         - An error occured during the Key Import process.
+        /// </summary>
+        /// <returns>The list of wizard states.</returns>
+        private List<WizardState> CreatePGPWizardStates()
+        {
+            List<WizardState> states = new List<WizardState>();
+
+            try
+            {
+                // Step 1
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step1,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep1ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 2
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step2,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep2ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 3
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step3,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep3ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.ProcessReceivedSyncMessages();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 4
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step4,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 5
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step5,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep5ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = true,
+                    IsUserTextVisible = false,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.Handshake_ConfirmFingerprint,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.TrustKey();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Handshake_WrongFingerprint,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 6
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step6,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep6ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 7
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step7,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPStep7ExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.GoToNextStep();
+                        this.ProcessReceivedSyncMessages();
+                    }),
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Step 8
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Step8,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = true,
+                    BackButtonClick = new Action(() =>
+                    {
+                        this.GoToPreviousStep();
+                    }),
+
+                    // Accept button
+                    IsAcceptButtonVisible = false,
+
+                    // Cancel button
+                    CancelButtonText = Properties.Resources.Options_CancelText,
+                    IsCancelButtonVisible = true,
+                    CancelButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Success
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Success,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_PGPSuccessExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.Close();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+
+                // Error
+                states.Add(new WizardState
+                {
+                    // Step
+                    Step = Steps.Error,
+
+                    // Title text
+                    TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+                    // Central area
+                    AreTrustwordsVisible = false,
+                    IsUserTextVisible = true,
+                    UserText = this.UserName,
+
+                    // Back button
+                    IsBackButtonVisible = false,
+
+                    // Accept button
+                    AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+                    IsAcceptButtonVisible = true,
+                    AcceptButtonClick = new Action(() =>
+                    {
+                        this.CancelWizard();
+                    }),
+
+                    // Cancel button
+                    IsCancelButtonVisible = false,
+
+                    // Subtitle area
+                    SubtitleText = null
+                });
+            }
+            catch (Exception ex)
+            {
+                states = null;
+                Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+            }
+
+            return states;
+        }
+
+        /// <summary>
         /// Navigates to the last step of the wizard.
         /// </summary>
         /// <param name="success">Whether or not the wizard has been completed successfully.</param>
         private void GoToLastStep(bool success)
         {
             // Go to last step
-            this.State = WizardState.Step4;
-            this.Success = success;
+            this.Step = success ? Steps.Success : Steps.Error;
 
-            // Update content
-            this.UpdateContent();
+            // Update wording and state
+            var lastState = this.states.Find(a => a.Step == this.Step);
+            if (this.IsInitiator)
+            {
+                if (this.SetImportedKeyAsDefault)
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault;
+                }
+                else
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+                }
+            }
+            else
+            {
+                if (this.privateKeyImported)
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+                }
+                else
+                {
+                    lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport;
+                }
+            }
+
+            // Apply state
+            this.CurrentState = lastState;
 
             Log.Verbose("GoToLastStep: Process finished. Success is " + success.ToString());
         }
@@ -587,26 +1321,42 @@
         private void GoToNextStep()
         {
             // Go to next step
-            this.State++;
+            this.Step++;
+
+            // Set current state
+            this.CurrentState = states.Find(a => a.Step == this.Step);
+
+            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
+        }
 
-            // Update content
-            this.UpdateContent();
+        /// <summary>
+        /// Navigates to the previous state of the wizard.
+        /// </summary>
+        private void GoToPreviousStep()
+        {
+            // Go to next step
+            this.Step--;
 
-            Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(WizardState), this.State));
+            // Set current state
+            this.CurrentState = states.Find(a => a.Step == this.Step);
+
+            Log.Verbose("GoToPreviousStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
         }
 
         /// <summary>
         /// Initializes the wizard.
         /// </summary>
-        private void InitializeWizard(WizardType type,
+        private void InitializeWizard(bool isInitiator,
+                                      WizardType type,
                                       PEPIdentity myself,
                                       string partnerFpr)
         {
             // Set initial state
             this.DataContext = this;
             this.Myself = myself;
-            this.State = WizardState.Step1;
+            this.Step = Steps.Step1;
             this.Type = type;
+            this.IsInitiator = isInitiator;
 
             // If own identity is null, get default account
             if (this.Myself == null)
@@ -699,8 +1449,39 @@
                 this.Partner.Fingerprint = partnerFpr;
             }
 
-            // Update dialog content
-            this.UpdateContent();
+            // Define states
+            this.states = (this.Type == WizardType.pEp) ? this.CreatePEPWizardStates() : this.CreatePGPWizardStates();
+
+            // Set current state
+            this.CurrentState = states?.Find(a => a.Step == Steps.Step1);
+        }
+
+        /// <summary>
+        /// Runs through all received sync messages.
+        /// </summary>
+        private void ProcessReceivedSyncMessages()
+        {
+            lock (mutexReceivedSyncMessages)
+            {
+                if (this.receivedSyncMessages != null)
+                {
+                    foreach (var message in this.receivedSyncMessages)
+                    {
+                        try
+                        {
+                            Task.Factory.StartNew(new Action(() =>
+                            {
+                                MsgProcessor msgProcessor = new MsgProcessor();
+                                msgProcessor.Decrypt(message);
+                            }));
+                        }
+                        catch (Exception ex)
+                        {
+                            Log.Error("ProcessReceivedSyncMessages: Error processing sync message. " + ex.ToString());
+                        }
+                    }
+                }
+            }
         }
 
         /// <summary>
@@ -714,93 +1495,117 @@
             {
                 try
                 {
-                    // If we have no partner at this point, use a copy of myself
-                    if (this.Partner == null)
-                    {
-                        this.Partner = this.Myself.Copy();
-                        Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
-                    }
-
-                    // Create basic message
-                    bool processMessage = true;
-                    PEPMessage message = new PEPMessage
+                    // Start sending in background
+                    Task.Factory.StartNew(new Action(() =>
                     {
-                        From = this.Myself,
-                        ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
-                        LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
-                        AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
-                        Direction = pEpMsgDirection.pEpDirOutgoing,
-                        ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
-                        KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
-                    };
-                    message.To.Add(this.Partner);
+                        // If we have no partner at this point, use a copy of myself
+                        if (this.Partner == null)
+                        {
+                            this.Partner = this.Myself.Copy();
+                            this.Partner.Fingerprint = null;
+                            Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
+                        }
+
+                        // Create basic message
+                        bool processMessage = true;
+                        PEPMessage message = new PEPMessage
+                        {
+                            From = this.Myself,
+                            ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
+                            LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
+                            AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
+                            Direction = pEpMsgDirection.pEpDirOutgoing,
+                            ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
+                            KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
+                        };
+                        message.To.Add(this.Partner);
+
+                        Log.Verbose("SendSyncMessage: Basic message successfully created.");
 
-                    Log.Verbose("SendSyncMessage: Basic message successfully created.");
+                        // If message type isn't InitialMessage, encrypt it accordingly
+                        PEPMessage msg;
+                        MsgProcessor msgProcessor = new MsgProcessor();
+                        if ((messageType == MessageTypes.PrivateKeyMessage) &&
+                            (this.ExportPrivateKey))
+                        {
+                            // Encrypt and add private key
+                            if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+                            {
+                                Log.Verbose("SendSyncMessage: Private key message successfully created.");
+                                message = msg;
+                                processMessage = false;
+                            }
+                            else
+                            {
+                                Log.Error("SendSyncMessage: Error encrypting private key message.");
+                                message = null;
+                            }
+                        }
+                        else if (((messageType == MessageTypes.PrivateKeyMessage) &&
+                                  (this.ExportPrivateKey == false)) ||
+                                 (messageType == MessageTypes.PublicKeyMessage))
+                        {
+                            // Encrypt using partner fpr as extra key
+                            if (msgProcessor.Encrypt(message, new string[] { this.Partner.Fingerprint }, out msg))
+                            {
+                                Log.Verbose("SendSyncMessage: Public key message successfully created.");
+                                message = msg;
+                                processMessage = false;
+                            }
+                            else
+                            {
+                                Log.Error("SendSyncMessage: Error encrypting public key message.");
+                                message = null;
+                            }
+                        }
 
-                    // If the message is the private key transport message, add own private key
-                    PEPMessage msg;
-                    if (messageType == MessageTypes.PrivateKeyMessage)
-                    {
-                        MsgProcessor msgProcessor = new MsgProcessor();
-                        if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+                        // If we have a message, send it
+                        if (message != null)
                         {
-                            Log.Verbose("SendSyncMessage: Private key message successfully created.");
-                            message = msg;
-                            processMessage = false;
+                            Log.Verbose("SendSyncMessage: Sending message...");
+
+                            // Disable passive mode if needed
+                            bool reenablePassiveMode = false;
+                            if ((messageType == MessageTypes.InitialMessage) &&
+                                (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
+                            {
+                                try
+                                {
+                                    ThisAddIn.PEPEngine.PassiveMode(false);
+                                    reenablePassiveMode = true;
+                                    Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
+                                }
+                                catch (Exception ex)
+                                {
+                                    Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
+                                }
+                            }
+
+                            // Send message
+                            Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
+
+                            // Log that message has been sent
+                            this.sentMessages?.Add(messageType);
+
+                            // Reenable passive mode if needed
+                            if (reenablePassiveMode)
+                            {
+                                try
+                                {
+                                    ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
+                                    Log.Verbose("SendSyncMessage: Passive mode reenabled.");
+                                }
+                                catch (Exception ex)
+                                {
+                                    Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
+                                }
+                            }
                         }
                         else
                         {
-                            Log.Error("SendSyncMessage: Error encrypting private key message.");
-                            message = null;
-                        }
-                    }
-
-                    // If we have a message, send it
-                    if (message != null)
-                    {
-                        Log.Verbose("SendSyncMessage: Sending message...");
-
-                        // Disable passive mode if needed
-                        bool reenablePassiveMode = false;
-                        if ((messageType == MessageTypes.InitialMessage) &&
-                            (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
-                        {
-                            try
-                            {
-                                ThisAddIn.PEPEngine.PassiveMode(false);
-                                reenablePassiveMode = true;
-                                Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
-                            }
-                            catch (Exception ex)
-                            {
-                                Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
-                            }
+                            Log.Error("SendSyncMessage: Myself identity is null.");
                         }
-
-                        // Send message
-                        Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage);
-
-                        // Log that message has been sent
-                        this.sentMessages?.Add(messageType);
-
-                        // Reenable passive mode if needed
-                        if (reenablePassiveMode)
-                        {
-                            try
-                            {
-                                ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
-                                Log.Verbose("SendSyncMessage: Passive mode reenabled.");
-                            }
-                            catch (Exception ex)
-                            {
-                                Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
-                            }
-                        }
-                    }
-                    else
-                    {
-                        Log.Error("SendSyncMessage: Myself identity is null.");
-                    }
+                    }), TaskCreationOptions.LongRunning);
                 }
                 catch (Exception ex)
                 {
@@ -810,7 +1615,7 @@
         }
 
         /// <summary>
-        /// Trusts the communication partner key (makes the channel green)
+        /// Trusts the communication partner key (makes the channel green).
         /// </summary>
         private void TrustKey()
         {
@@ -818,31 +1623,28 @@
             {
                 try
                 {
-                    Log.Verbose("TrustKey: Trusting partner key...");
-
-                    this._Partner = this.Items[0].Partner;
-                    pEpIdentity partner = this._Partner.ToCOMType();
-                    ThisAddIn.PEPEngine.TrustPersonalKey(partner);
-
-                    // If Trustwords are being accepted after having received
-                    // the private key, finish process.
-                    if (this.State == WizardState.Step3)
+                    // Run in background
+                    Task.Factory.StartNew(new Action(() =>
                     {
-                        Log.Verbose("TrustKey: Private key already received. Completing wizard.");
-                        this.CompleteWizard();
-                    }
-                    else
+                        Log.Verbose("TrustKey: Trusting partner key...");
+
+                        // Trust the partner's key
+                        this._Partner = this.Items[0].Partner;
+                        pEpIdentity partner = this._Partner.ToCOMType();
+                        ThisAddIn.PEPEngine.TrustPersonalKey(partner);
+
+                        // Process messages that might have been received
+                        this.ProcessReceivedSyncMessages();
+
+                    }), TaskCreationOptions.LongRunning).ContinueWith(new Action<Task>((result) =>
                     {
-                        Log.Verbose("TrustKey: No private key received yet. Going to next step.");
-                        this.GoToNextStep();
-                    }
-
-                    // In pEp sync mode, send private key to partner
-                    if (this.Type == WizardType.pEp)
-                    {
-                        Log.Verbose("TrustKey: Sending private key to partner.");
-                        this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
-                    }
+                        // In pEp sync mode, send private key message to partner
+                        if (this.Type == WizardType.pEp)
+                        {
+                            Log.Verbose("TrustKey: Sending private key to partner.");
+                            this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
+                        }
+                    }));
                 }
                 catch (Exception ex)
                 {
@@ -858,108 +1660,42 @@
         }
 
         /// <summary>
-        /// Updates the dialog content according to its current state.
-        /// </summary>
-        private void UpdateContent()
-        {
-            // Set title
-            if (string.IsNullOrEmpty(this._TitleText))
-            {
-                this.TitleText = this.TitleText = this.Myself?.Address;
-            }
-
-            // Set content according to state
-            switch (this.State)
-            {
-                case WizardState.Step1:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step1PEPExplanationText : Properties.Resources.KeySyncWizard_Step1PGPExplanationText;
-                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_WaitingForResponseText : Properties.Resources.KeySyncWizard_Step1PGPSubtitleText;
-                    }
-                    break;
-                case WizardState.Step2:
-                    {
-                        this.NextButtonText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step2PEPExplanationText : Properties.Resources.KeySyncWizard_Step2PGPExplanationText;
-                        this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
-                    }
-                    break;
-                case WizardState.Step3:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
-                        this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step3PEPExplanationText : Properties.Resources.KeySyncWizard_Step3PGPExplanationText;
-                        this.SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText;
-                    }
-                    break;
-                case WizardState.Step4:
-                    {
-                        this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
-
-                        if (this.Success)
-                        {
-                            this.SubtitleText = Properties.Resources.KeySyncWizard_SuccessText;
-
-                            switch (this.Type)
-                            {
-                                case WizardType.PGP:
-                                    {
-                                        this.ExplanationText = Properties.Resources.KeySyncWizard_Step4SuccessExplanationText;
-                                    }
-                                    break;
-                                case WizardType.pEp:
-                                    {
-                                        if (this.isInitiator)
-                                        {
-                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessInitiatorExplanationText;
-                                        }
-                                        else
-                                        {
-                                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText;
-                                        }
-                                    }
-                                    break;
-                                case WizardType.Undefined:
-                                default:
-                                    {
-                                        this.ExplanationText = string.Empty;
-                                    }
-                                    break;
-                            }
-                        }
-                        else
-                        {
-                            this.ExplanationText = Properties.Resources.KeySyncWizard_Step4ErrorExplanationText;
-                            this.SubtitleText = Properties.Resources.KeySyncWizard_ErrorText;
-                        }
-                    }
-                    break;
-                case WizardState.Undefined:
-                default:
-                    this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
-                    this.ExplanationText = string.Empty;
-                    this.SubtitleText = string.Empty;
-                    break;
-            }
-        }
-
-        /// <summary>
         /// Resets the object to its defaults.
         /// </summary>
         public void Reset()
         {
-            this._ExplanationText = null;
+            this._CurrentState = new WizardState();
+            this._ExportPrivateKey = true;
+            this._IsInitiator = false;
             this._Items = new ObservableCollection<HandshakeItem>();
             this._Myself = null;
-            this._NextButtonText = null;
             this._Partner = null;
-            this._State = WizardState.Undefined;
-            this._SubtitleText = null;
-            this._Success = false;
+            this._Step = Steps.Undefined;
+            this._SetImportedKeyAsDefault = true;
             this._Type = WizardType.Undefined;
-            this._TitleText = null;
         }
 
         #endregion
+
+        /// <summary>
+        /// Container to define a wizard state.
+        /// </summary>
+        public class WizardState
+        {
+            public Action                   AcceptButtonClick           { get; set; }   =   null;
+            public string                   AcceptButtonText            { get; set; }   =   null;
+            public bool                     AreTrustwordsVisible        { get; set; }   =   false;
+            public Action                   BackButtonClick             { get; set; }   =   null;
+            public Action                   CancelButtonClick           { get; set; }   =   null;
+            public string                   CancelButtonText            { get; set; }   =   null;
+            public bool                     IsAcceptButtonVisible       { get; set; }   =   true;
+            public bool                     IsBackButtonVisible         { get; set; }   =   false;
+            public bool                     IsCancelButtonVisible       { get; set; }   =   true;
+            public bool                     IsUserTextVisible           { get; set; }   =   true;
+            public KeySyncWizard.Steps      Step                        { get; set; }   =   Steps.Undefined;
+            public string                   SubtitleText                { get; set; }   =   null;
+            public string                   TitleText                   { get; set; }   =   null;
+            public string                   UserText                    { get; set; }   =   null;
+        }
     }
 }
--- a/UI/ValueConverters.cs	Thu May 10 12:18:14 2018 +0200
+++ b/UI/ValueConverters.cs	Tue May 22 11:35:06 2018 +0200
@@ -276,61 +276,6 @@
     }
 
     /// <summary>
-    /// Returns a bool value indicating if the wizard state matches any of the given parameter.
-    /// </summary>
-    public class IsWizardStateConverter : IValueConverter
-    {
-        public object Convert(object value,
-                              Type targetType,
-                              object parameter,
-                              CultureInfo culture)
-        {
-            bool success;
-            KeySyncWizard.WizardState param;
-
-            if ((value is KeySyncWizard.WizardState) &&
-                (parameter is string))
-            {
-                string[] parameters = (parameter as string).Split('|');
-
-                if (parameters?.Length > 0)
-                {
-                    foreach (var p in parameters)
-                    {
-                        success = Enum.TryParse(p, out param);
-
-                        if (success)
-                        {
-                            if (((KeySyncWizard.WizardState)value) == param)
-                            {
-                                return true;
-                            }
-                        }
-                        else
-                        {
-                            throw new ArgumentException();
-                        }
-                    }
-                }
-
-                return false;
-            }
-            else
-            {
-                throw new ArgumentException();
-            }
-        }
-
-        public object ConvertBack(object value,
-                                  Type targetType,
-                                  object parameter,
-                                  CultureInfo culture)
-        {
-            throw new NotImplementedException();
-        }
-    }
-
-    /// <summary>
     /// Converter to check if a list is empty.
     /// </summary>
     public class IsListEmptyConverter : IValueConverter
@@ -530,6 +475,38 @@
     }
 
     /// <summary>
+    /// Returns true if the Wizard is in the given state.
+    /// </summary>
+    public class IsWizardTypeConverter : IValueConverter
+    {
+        public object Convert(object value,
+                              Type targetType,
+                              object parameter,
+                              CultureInfo culture)
+        {
+            string val = null;
+            string param = parameter as string;
+
+            try
+            {
+                val = Enum.GetName(typeof(KeySyncWizard.WizardType), value);
+            }
+            catch
+            {
+                val = null;
+            }
+
+            return (param?.Equals(val) == true);
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+
+    /// <summary>
     /// Converter to AND several bool values and convert to Visibility.
     /// </summary>
     public class MultiBooleanToVisibilityConverter : IMultiValueConverter