private void Application_ItemSend(object Item, ref bool Cancel) { Outlook.MailItem mailItem = Item as Outlook.MailItem; if (mailItem == null) return; GnuPGRibbon currentRibbon = ribbon; 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; // DEFAULT TO CANCEL Cancel = true; try { 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; } IList<string> recipients = new List<string>(); 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 recipientDialog.TopMost = true; DialogResult recipientResult = recipientDialog.ShowDialog(); if (recipientResult != DialogResult.OK) { // The user closed the recipient dialog, prevent sending the mail Cancel = true; return; } foreach (string r in recipientDialog.SelectedKeys) recipients.Add(r); 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; } recipients.Add(GetSMTPAddress(mailItem)); } List<Attachment> attachments = new List<Attachment>(); // Sign and encrypt the plaintext mail if ((needToSign) && (needToEncrypt)) { mail = SignAndEncryptEmail(mail, GetSMTPAddress(mailItem), recipients); if (mail == null) return; List<Microsoft.Office.Interop.Outlook.Attachment> mailAttachments = new List<Outlook.Attachment>(); foreach (Microsoft.Office.Interop.Outlook.Attachment attachment in mailItem.Attachments) mailAttachments.Add(attachment); foreach (var attachment in mailAttachments) { Attachment a = new Attachment(); a.TempFile = Path.GetTempPath(); a.FileName = attachment.FileName; a.DisplayName = attachment.DisplayName; a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); a.TempFile = a.TempFile + ".pgp"; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file byte[] cleartext = File.ReadAllBytes(a.TempFile); string cyphertext = SignAndEncryptAttachment(cleartext, GetSMTPAddress(mailItem), recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } else if (needToSign) { // Sign the plaintext mail if needed mail = SignEmail(mail, GetSMTPAddress(mailItem)); if (mail == null) return; } else if (needToEncrypt) { // Encrypt the plaintext mail if needed mail = EncryptEmail(mail, recipients); if (mail == null) return; List<Microsoft.Office.Interop.Outlook.Attachment> mailAttachments = new List<Outlook.Attachment>(); foreach (Microsoft.Office.Interop.Outlook.Attachment attachment in mailItem.Attachments) mailAttachments.Add(attachment); foreach (var attachment in mailAttachments) { Attachment a = new Attachment(); a.TempFile = Path.GetTempPath(); a.FileName = attachment.FileName; a.DisplayName = attachment.DisplayName; a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); a.TempFile = a.TempFile + ".pgp"; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file byte[] cleartext = File.ReadAllBytes(a.TempFile); string cyphertext = EncryptEmail(cleartext, recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } foreach (var a in attachments) { mailItem.Attachments.Add(a.TempFile, a.AttachmentType, 1, a.DisplayName); } } catch (Exception ex) { this.Passphrase = null; if (ex.Message.ToLower().StartsWith("checksum")) { MessageBox.Show( "Incorrect passphrase possibly entered.", "Outlook Privacy Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } WriteErrorData("Application_ItemSend", ex); MessageBox.Show( ex.Message, "Outlook Privacy Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Cancel sending return; } if (mail == null) return; Cancel = false; mailItem.Body = mail; }
internal void DecryptEmail(Outlook.MailItem mailItem) { if (Regex.IsMatch(mailItem.Body, _pgpEncryptedHeader) == false) { MessageBox.Show( "Outlook Privacy Plugin cannot help here.", "Mail is not encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Sometimes messages could contain multiple message blocks. In that case just use the // very first one. string firstPgpBlock = mailItem.Body; int endMessagePosition = firstPgpBlock.IndexOf("-----END PGP MESSAGE-----") + "-----END PGP MESSAGE-----".Length; if (endMessagePosition != -1) firstPgpBlock = firstPgpBlock.Substring(0, endMessagePosition); string charset = null; try { charset = Regex.Match(firstPgpBlock, @"Charset:\s+([^\s\r\n]+)").Groups[1].Value; } catch { } // Set default encoding if charset was missing from // message. if (string.IsNullOrWhiteSpace(charset)) charset = "ISO-8859-1"; var encoding = Encoding.GetEncoding(charset); CryptoContext Context; byte[] cleardata = DecryptAndVerify(mailItem.To, ASCIIEncoding.ASCII.GetBytes(firstPgpBlock), out Context); if (cleardata != null) { mailItem.Body = DecryptAndVerifyHeaderMessage + encoding.GetString(cleardata); if (mailItem.BodyFormat == Outlook.OlBodyFormat.olFormatHTML) { // Don't HMTL encode or we will encode emails already in HTML format. // Office has a safe html module they use to prevent security issues. // Not encoding here should be no worse then reading a standard HTML // email. var html = DecryptAndVerifyHeaderMessage.Replace("<", "<").Replace(">", ">") + encoding.GetString(cleardata); html = html.Replace("\n", "<br/>"); mailItem.HTMLBody = "<html><body>" + html + "</body></html>"; } // Decrypt all attachments List<Microsoft.Office.Interop.Outlook.Attachment> mailAttachments = new List<Outlook.Attachment>(); foreach (Microsoft.Office.Interop.Outlook.Attachment attachment in mailItem.Attachments) mailAttachments.Add(attachment); List<Attachment> attachments = new List<Attachment>(); foreach (var attachment in mailAttachments) { Attachment a = new Attachment(); // content id if (attachment.FileName.StartsWith("Attachment") && attachment.FileName.EndsWith(".pgp")) { var property = attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F"); a.FileName = property.ToString(); if (a.FileName.Contains('@')) { a.FileName = a.FileName.Substring(0, a.FileName.IndexOf('@')); } a.TempFile = Path.GetTempPath(); a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); attachment.SaveAsFile(a.TempFile); // Decrypt file var cyphertext = File.ReadAllBytes(a.TempFile); File.Delete(a.TempFile); try { var plaintext = DecryptAndVerify(mailItem.To, cyphertext, out Context); File.WriteAllBytes(a.TempFile, plaintext); attachments.Add(a); } catch { // Assume attachment wasn't encrypted } } //else if (attachment.FileName == "PGPexch.htm.pgp") //{ // // This is the HTML email message. // var TempFile = Path.GetTempFileName(); // attachment.SaveAsFile(TempFile); // // Decrypt file // var cyphertext = File.ReadAllBytes(TempFile); // File.Delete(TempFile); // try // { // var plaintext = DecryptAndVerify(mailItem.To, cyphertext); // mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML; // mailItem.HTMLBody = _encoding.GetString(plaintext); // } // catch // { // // Odd! // } //} else { a.FileName = Regex.Replace(attachment.FileName, @"\.(pgp\.asc|gpg\.asc|pgp|gpg|asc)$", ""); a.DisplayName = Regex.Replace(attachment.DisplayName, @"\.(pgp\.asc|gpg\.asc|pgp|gpg|asc)$", ""); ; a.TempFile = Path.GetTempPath(); a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); attachment.SaveAsFile(a.TempFile); // Decrypt file var cyphertext = File.ReadAllBytes(a.TempFile); File.Delete(a.TempFile); try { var plaintext = DecryptAndVerify(mailItem.To, cyphertext, out Context); File.WriteAllBytes(a.TempFile, plaintext); attachments.Add(a); } catch { // Assume attachment wasn't encrypted } } } foreach (var attachment in attachments) mailItem.Attachments.Add(attachment.TempFile, attachment.AttachmentType, 1, attachment.FileName); // Warning: Saving could save the message back to the server, not just locally //mailItem.Save(); } }
private void Application_ItemSend(object Item, ref bool Cancel) { var mailItem = Item as Outlook.MailItem; if (mailItem == null) return; GnuPGRibbon currentRibbon = ribbon; 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; // DEFAULT TO CANCEL Cancel = true; try { if (mailType != Outlook.OlBodyFormat.olFormatPlain) { MessageBox.Show( Localized.ErrorInvalidFormat, "Invalid Mail Format", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } IList<string> recipients = new List<string>(); if (needToEncrypt) { // Popup UI to select the encryption targets List<string> mailRecipients = new List<string>(); foreach (Outlook.Recipient mailRecipient in mailItem.Recipients) mailRecipients.Add(GetSmtpAddressForRecipient((Outlook.Recipient)mailRecipient)); var recipientDialog = new FormKeySelection( mailRecipients, GetKeysForEncryption, needToEncrypt, needToSign); recipientDialog.TopMost = true; DialogResult recipientResult = recipientDialog.DialogResult; if(recipientDialog.DialogResult == DialogResult.Ignore) recipientResult = recipientDialog.ShowDialog(); if (recipientResult != DialogResult.OK) { // The user closed the recipient dialog, prevent sending the mail Cancel = true; return; } needToEncrypt = recipientDialog.Encrypt; needToSign = recipientDialog.Sign; foreach (var r in recipientDialog.SelectedKeys) recipients.Add(r.Key); if (needToEncrypt && recipients.Count == 0) { MessageBox.Show( Localized.ErrorInvalidRecipientKey, "Invalid Recipient Key", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } recipients.Add(GetSMTPAddress(mailItem)); } var attachments = new List<Attachment>(); // Sign and encrypt the plaintext mail if ((needToSign) && (needToEncrypt)) { mail = SignAndEncryptEmail(mail, GetSMTPAddress(mailItem), recipients); if (mail == null) return; var mailAttachments = new List<Outlook.Attachment>(); foreach (Outlook.Attachment attachment in mailItem.Attachments) mailAttachments.Add(attachment); foreach (var attachment in mailAttachments) { var a = new Attachment(); a.TempFile = Path.GetTempPath(); a.FileName = attachment.FileName; a.DisplayName = attachment.DisplayName; a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); a.TempFile = a.TempFile + ".pgp"; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file byte[] cleartext = File.ReadAllBytes(a.TempFile); string cyphertext = SignAndEncryptAttachment(cleartext, GetSMTPAddress(mailItem), recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } else if (needToSign) { // Sign the plaintext mail if needed // 1. Verify text lines are not too long var mailLines = mail.Split('\n'); var longLines = mailLines.Any(line => line.Length > 70); if(longLines) { var dialog = new FormSelectLineWrap(); var result = dialog.ShowDialog(); if (result == DialogResult.Cancel) return; if (dialog.radioButtonWrap.Checked) { var lines = new List<string>(mailLines); for(int i = 0; i<lines.Count; i++) { var line = lines[i]; if(line.Length>70) { var newLine = line.Substring(70); line = line.Substring(0, 70); lines[i] = line; lines.Insert(i + 1, newLine); } } var sb = new StringBuilder(mail.Length+20); foreach (var line in lines) sb.AppendLine(line.TrimEnd('\r','\n')); mail = sb.ToString(); } if (dialog.radioButtonMime.Checked) { // todo } if (dialog.radioButtonEdit.Checked) return; } mail = SignEmail(mail, GetSMTPAddress(mailItem)); if (mail == null) return; } else if (needToEncrypt) { // Encrypt the plaintext mail if needed mail = EncryptEmail(mail, recipients); if (mail == null) return; var mailAttachments = new List<Outlook.Attachment>(); foreach (Outlook.Attachment attachment in mailItem.Attachments) mailAttachments.Add(attachment); foreach (var attachment in mailAttachments) { var a = new Attachment(); a.TempFile = Path.GetTempPath(); a.FileName = attachment.FileName; a.DisplayName = attachment.DisplayName; a.AttachmentType = attachment.Type; a.TempFile = Path.Combine(a.TempFile, a.FileName); a.TempFile = a.TempFile + ".pgp"; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file byte[] cleartext = File.ReadAllBytes(a.TempFile); string cyphertext = EncryptEmail(cleartext, recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } foreach (var a in attachments) { mailItem.Attachments.Add(a.TempFile, a.AttachmentType, 1, a.DisplayName); } } catch (Exception ex) { if (ex.Message.ToLower().StartsWith("checksum")) { MessageBox.Show( Localized.ErrorBadPassphrase, "Outlook Privacy Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } WriteErrorData("Application_ItemSend", ex); MessageBox.Show( ex.Message, "Outlook Privacy Error", MessageBoxButtons.OK, MessageBoxIcon.Error); // Cancel sending return; } if (mail == null) return; Cancel = false; mailItem.Body = mail; currentRibbon.EncryptButton.Checked = false; currentRibbon.SignButton.Checked = false; SetProperty(mailItem, "GnuPGSetting.Sign", false); SetProperty(mailItem, "GnuPGSetting.Encrypt", false); }
private void Application_ItemSend(object Item, ref bool Cancel) { var mailItem = Item as Outlook.MailItem; if (mailItem == null) return; OppRibbon currentRibbon = _ribbon; if (currentRibbon == null) return; var mail = mailItem.Body; var mailType = mailItem.BodyFormat; var needToEncrypt = currentRibbon.EncryptButton.Checked; var needToSign = currentRibbon.SignButton.Checked; // Early out when we don't need to sign/encrypt if (!needToEncrypt && !needToSign) return; // DEFAULT TO CANCEL Cancel = true; try { if (mailType != Outlook.OlBodyFormat.olFormatPlain) { MessageBox.Show( Localized.ErrorInvalidFormat, "Invalid Mail Format", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } IList<string> recipients = new List<string>(); if (needToEncrypt) { // Popup UI to select the encryption targets var mailRecipients = (from Outlook.Recipient mailRecipient in mailItem.Recipients select GetSmtpAddressForRecipient(mailRecipient)).ToList(); var recipientDialog = new FormKeySelection( mailRecipients, GetKeysForEncryption, needToEncrypt, needToSign); recipientDialog.TopMost = true; var recipientResult = recipientDialog.DialogResult; if(recipientDialog.DialogResult == DialogResult.Ignore) recipientResult = recipientDialog.ShowDialog(); if (recipientResult != DialogResult.OK) { // The user closed the recipient dialog, prevent sending the mail Cancel = true; return; } needToEncrypt = recipientDialog.Encrypt; needToSign = recipientDialog.Sign; foreach (var r in recipientDialog.SelectedKeys) recipients.Add(r.Key); if (needToEncrypt && recipients.Count == 0) { MessageBox.Show( Localized.ErrorInvalidRecipientKey, "Invalid Recipient KeyItem", MessageBoxButtons.OK, MessageBoxIcon.Error); Cancel = true; // Prevent sending the mail return; } if(_settings.Encrypt2Self) recipients.Add(GetSMTPAddress(mailItem)); } var attachments = new List<Attachment>(); // Sign and encrypt the plaintext mail if ((needToSign) && (needToEncrypt)) { mail = SignAndEncryptEmail(mail, GetSMTPAddress(mailItem), recipients); if (mail == null) return; var mailAttachments = mailItem.Attachments.Cast<Outlook.Attachment>().ToList(); foreach (var attachment in mailAttachments) { var a = new Attachment() { TempFile = Path.Combine(Path.GetTempPath(), attachment.FileName) + ".pgp", FileName = attachment.FileName, DisplayName = attachment.DisplayName, AttachmentType = attachment.Type, }; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file var cleartext = File.ReadAllBytes(a.TempFile); var cyphertext = SignAndEncryptAttachment(cleartext, GetSMTPAddress(mailItem), recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } else if (needToSign) { // Sign the plaintext mail if needed // 1. Verify text lines are not too long var mailLines = mail.Split('\n'); var longLines = mailLines.Any(line => line.Length > 70); var wrapLines = false; if(longLines) { var dialog = new FormSelectLineWrap(); var result = dialog.ShowDialog(); if (result == DialogResult.Cancel) return; wrapLines = dialog.radioButtonWrap.Checked; if (dialog.radioButtonMime.Checked) { // todo } if (dialog.radioButtonEdit.Checked) return; } mail = SignEmail(mail, GetSMTPAddress(mailItem), wrapLines); if (mail == null) return; } else if (needToEncrypt) { // Encrypt the plaintext mail if needed mail = EncryptEmail(mail, recipients); if (mail == null) return; var mailAttachments = mailItem.Attachments.Cast<Outlook.Attachment>().ToList(); foreach (var attachment in mailAttachments) { var a = new Attachment() { TempFile = Path.Combine(Path.GetTempPath(), attachment.FileName)+ ".pgp", FileName = attachment.FileName, DisplayName = attachment.DisplayName, AttachmentType = attachment.Type }; attachment.SaveAsFile(a.TempFile); attachment.Delete(); // Encrypt file var cleartext = File.ReadAllBytes(a.TempFile); var cyphertext = EncryptEmail(cleartext, recipients); File.WriteAllText(a.TempFile, cyphertext); a.Encrypted = true; attachments.Add(a); } } foreach (var a in attachments) { mailItem.Attachments.Add(a.TempFile, a.AttachmentType, 1, a.DisplayName); } } catch (Exception ex) { if (ex.Message.ToLower().StartsWith("checksum")) { ClearLastPassword(); MessageBox.Show( Localized.ErrorBadPassphrase, Localized.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); return; } WriteErrorData("Application_ItemSend", ex); MessageBox.Show( ex.Message + "\n"+ex.StackTrace, Localized.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); // Cancel sending return; } if (mail == null) return; Cancel = false; mailItem.Body = mail; currentRibbon.EncryptButton.Checked = false; currentRibbon.SignButton.Checked = false; SetProperty(mailItem, "GnuPGSetting.Sign", false); SetProperty(mailItem, "GnuPGSetting.Encrypt", false); }
public MailModel DecryptEmail(Outlook.MailItem mailItem) { if (mailItem.Body == null || Regex.IsMatch(mailItem.Body, PgpEncryptedHeader) == false) { return HandleMailWithoutPgpBody(mailItem); } MailModel mailModel; // Sometimes messages could contain multiple message blocks. In that case just use the // very first one. var firstPgpBlock = GetFirstPgpBlock(mailItem); var encoding = GetEncoding(firstPgpBlock); CryptoContext context; var cleardata = DecryptAndVerify(mailItem.To, Encoding.ASCII.GetBytes(firstPgpBlock), out context); if (cleardata == null) return null; if (mailItem.BodyFormat == Outlook.OlBodyFormat.olFormatHTML) { // Don't HMTL encode or we will encode emails already in HTML format. // Office has a safe html module they use to prevent security issues. // Not encoding here should be no worse then reading a standard HTML // email. var html = encoding.GetString(cleardata); html = html.Replace("\n", "<br/>"); html = "<html><body>" + html + "</body></html>"; mailModel = new HtmlMailModel { Body = html }; } else { var mailText = encoding.GetString(cleardata); mailModel = new PlainMailModel { Body = mailText }; } // Decrypt all attachments var mailAttachments = CreateAttachmentListFromMailItem(mailItem); var attachments = new List<Attachment>(); foreach (var attachment in mailAttachments) { var tempAttachment = new Attachment(); // content id if (attachment.FileName.StartsWith("Attachment") && attachment.FileName.EndsWith(".pgp")) { var property = attachment.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F"); tempAttachment.FileName = property.ToString(); if (tempAttachment.FileName.Contains('@')) { tempAttachment.FileName = tempAttachment.FileName.Substring(0, tempAttachment.FileName.IndexOf('@')); } tempAttachment.TempFile = Path.GetTempPath(); tempAttachment.AttachmentType = attachment.Type; tempAttachment.TempFile = Path.Combine(tempAttachment.TempFile, tempAttachment.FileName); attachment.SaveAsFile(tempAttachment.TempFile); TryDecryptAndAddAttachment(mailItem, tempAttachment, attachments); } //else if (attachment.FileName == "PGPexch.htm.pgp") //{ // // This is the HTML email message. // var TempFile = Path.GetTempFileName(); // attachment.SaveAsFile(TempFile); // // Decrypt file // var cyphertext = File.ReadAllBytes(TempFile); // File.Delete(TempFile); // try // { // var plaintext = DecryptAndVerify(mailItem.To, cyphertext); // mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML; // mailItem.HTMLBody = _encoding.GetString(plaintext); // } // catch // { // // Odd! // } //} else { tempAttachment.FileName = Regex.Replace(attachment.FileName, EncryptionExtension, ""); tempAttachment.DisplayName = Regex.Replace(attachment.DisplayName, EncryptionExtension, ""); ; tempAttachment.TempFile = Path.GetTempPath(); tempAttachment.AttachmentType = attachment.Type; tempAttachment.TempFile = Path.Combine(tempAttachment.TempFile, tempAttachment.FileName); attachment.SaveAsFile(tempAttachment.TempFile); TryDecryptAndAddAttachment(mailItem, tempAttachment, attachments); } } mailModel.Attachments = attachments; return mailModel; }