internal void DecryptEmail(Outlook.MailItem mailItem) { string mail = mailItem.Body; Outlook.OlBodyFormat mailType = mailItem.BodyFormat; if (mailType != Outlook.OlBodyFormat.olFormatPlain) { MessageBox.Show( "OutlookGnuPG can only decrypt plain text mails.", "Invalid Mail Format", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (Regex.IsMatch(mailItem.Body, _pgpEncryptedHeader) == false) { MessageBox.Show( "OutlookGnuPG cannot help here.", "Mail is not encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Still no gpg.exe path... Annoy the user once again, maybe he'll get it ;) if (string.IsNullOrEmpty(_settings.GnuPgPath)) Settings(); // Stubborn, give up if (string.IsNullOrEmpty(_settings.GnuPgPath)) { MessageBox.Show( "OutlookGnuPG can only decrypt when you provide a valid gpg.exe path. Please open Settings and configure it.", "Invalid GnuPG Executable", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string passphrase = string.Empty; string privateKey = string.Empty; // Popup UI to select the passphrase and private key. Passphrase passphraseDialog = new Passphrase(_settings.DefaultKey, "Decrypt"); DialogResult passphraseResult = passphraseDialog.ShowDialog(); if (passphraseResult != DialogResult.OK) { // The user closed the passphrase dialog, prevent sending the mail return; } passphrase = passphraseDialog.EnteredPassphrase; privateKey = passphraseDialog.SelectedKey; passphraseDialog.Close(); if (string.IsNullOrEmpty(privateKey)) { MessageBox.Show( "OutlookGnuPG needs a private key for decrypting. No keys were detected.", "Invalid Private Key", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Decrypt without fd-status (might already blow up, early out) // Decrypt with fd-status and cut out the stdout of normal decrypt (prevents BAD/GOODMC messages in message confusing us) string stdOutResult = string.Empty; using (MemoryStream inputStream = new MemoryStream(mail.Length)) using (MemoryStream outputStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(inputStream)) { writer.Write(mail); writer.Flush(); inputStream.Position = 0; try { _gnuPg.OutputStatus = false; _gnuPg.Passphrase = passphrase; _gnuPg.Decrypt(inputStream, outputStream, new MemoryStream()); } catch (Exception ex) { string error = ex.Message; // We deal with bad signature later if (!error.ToLowerInvariant().Contains("bad signature")) { MessageBox.Show( error, "GnuPG Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } } using (StreamReader reader = new StreamReader(outputStream)) { outputStream.Position = 0; stdOutResult = reader.ReadToEnd(); } } string verifyResult = string.Empty; string errorResult = string.Empty; using (MemoryStream inputStream = new MemoryStream(mail.Length)) using (MemoryStream outputStream = new MemoryStream()) using (MemoryStream errorStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(inputStream)) { writer.Write(mail); writer.Flush(); inputStream.Position = 0; try { _gnuPg.OutputStatus = true; _gnuPg.Passphrase = passphrase; _gnuPg.Decrypt(inputStream, outputStream, errorStream); } catch (Exception ex) { string error = ex.Message; // We deal with bad signature later if (!error.ToLowerInvariant().Contains("bad signature")) { MessageBox.Show( error, "GnuPG Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } } using (StreamReader reader = new StreamReader(outputStream)) { outputStream.Position = 0; verifyResult = reader.ReadToEnd(); } using (StreamReader reader = new StreamReader(errorStream)) { errorStream.Position = 0; errorResult = reader.ReadToEnd(); } } verifyResult = verifyResult.Replace(stdOutResult, string.Empty); // Verify: status-fd // stdOut: the message // error: gpg error/status if (verifyResult.Contains("BADMDC")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Invalid Encryption", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (verifyResult.Contains("GOODMDC")) { // Decrypted OK, check for validsig if (verifyResult.Contains("BADSIG")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Invalid Signature", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (verifyResult.Contains("GOODSIG")) { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); MessageBox.Show( errorResult, "Valid Signature", MessageBoxButtons.OK, MessageBoxIcon.Information); // Valid signature! mailItem.Body = stdOutResult; } else { // No signature? mailItem.Body = stdOutResult; } } else { errorResult = RemoveInvalidAka(errorResult.Replace("gpg: ", string.Empty)); errorResult = errorResult.Replace("WARNING", Environment.NewLine + "WARNING"); DialogResult res = MessageBox.Show( errorResult + Environment.NewLine + "Decrypt mail anyway?", "Unknown Encryption", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); if (res == DialogResult.OK) mailItem.Body = stdOutResult; } }
private void Application_ItemSend(object Item, ref bool Cancel) { Outlook.MailItem mailItem = Item as Outlook.MailItem; if (mailItem == null) return; #if VS2008 //var inspector = Application.ActiveInspector(); var inspector = mailItem.GetInspector; var currentRibbons = Globals.Ribbons[inspector]; var currentRibbon = currentRibbons.GnuPGRibbonCompose; #else GnuPGRibbon currentRibbon = ribbon; #endif if (currentRibbon == null) return; string mail = mailItem.Body; Outlook.OlBodyFormat mailType = mailItem.BodyFormat; bool needToEncrypt = currentRibbon.EncryptButton.Checked; bool needToSign = currentRibbon.SignButton.Checked; // Early out when we don't need to sign/encrypt if (!needToEncrypt && !needToSign) return; if (mailType != Outlook.OlBodyFormat.olFormatPlain) { MessageBox.Show( "OutlookGnuPG can only sign/encrypt plain text mails. Please change the format, or disable signing/encrypting for this mail.", "Invalid Mail Format", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } // Still no gpg.exe path... Annoy the user once again, maybe he'll get it ;) if (string.IsNullOrEmpty(_settings.GnuPgPath)) Settings(); // Stubborn, give up if (string.IsNullOrEmpty(_settings.GnuPgPath)) { MessageBox.Show( "OutlookGnuPG can only sign/encrypt when you provide a valid gpg.exe path. Please open Settings and configure it.", "Invalid GnuPG Executable", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } string passphrase = string.Empty; string privateKey = string.Empty; if (needToSign) { // Popup UI to select the passphrase and private key. Passphrase passphraseDialog = new Passphrase(_settings.DefaultKey, "Sign"); DialogResult passphraseResult = passphraseDialog.ShowDialog(); if (passphraseResult != DialogResult.OK) { // The user closed the passphrase dialog, prevent sending the mail Cancel = true; return; } passphrase = passphraseDialog.EnteredPassphrase; privateKey = passphraseDialog.SelectedKey; passphraseDialog.Close(); if (string.IsNullOrEmpty(privateKey)) { MessageBox.Show( "OutlookGnuPG needs a private key for signing. No keys were detected.", "Invalid Private Key", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } } #if VS2008 IList<string> recipients = new List<string> { string.Empty }; #else IList<string> recipients = new List<string>(); recipients.Add(string.Empty); #endif if (needToEncrypt) { // Popup UI to select the encryption targets List<string> mailRecipients = new List<string>(); foreach (Outlook.Recipient mailRecipient in mailItem.Recipients) mailRecipients.Add(GetAddressCN(((Outlook.Recipient)mailRecipient).Address)); Recipient recipientDialog = new Recipient(mailRecipients); // Passing in the first addres, maybe it matches DialogResult recipientResult = recipientDialog.ShowDialog(); if (recipientResult != DialogResult.OK) { // The user closed the recipient dialog, prevent sending the mail Cancel = true; return; } recipients = recipientDialog.SelectedKeys; recipientDialog.Close(); if (recipients.Count == 0) { MessageBox.Show( "OutlookGnuPG needs a recipient when encrypting. No keys were detected/selected.", "Invalid Recipient Key", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } } // Sign and encrypt the plaintext mail if ((needToSign) && (needToEncrypt)) { mail = SignAndEncryptEmail(mail, privateKey, passphrase, recipients); } else if (needToSign) { // Sign the plaintext mail if needed mail = SignEmail(mail, privateKey, passphrase); } else if (needToEncrypt) { // Encrypt the plaintext mail if needed mail = EncryptEmail(mail, passphrase, recipients); } // Update the new content if (mail != _gnuPgErrorString) mailItem.Body = mail; else Cancel = true; }