internal bool ExecuteSendLinkAction(IProxy mailItem, RequestManager requestManager) { throw new NotImplementedException("SendLink is not supported for Lotus Notes"); //Interop.Logging.Logger.LogInfo("Executing Send Link Process"); //try //{ // Attachment[] processedAttachments = requestManager.EnforceResponse.ModifiedRequest.Attachments; // if (processedAttachments.Length == 0) // { // Interop.Logging.Logger.LogInfo("No files to upload"); // return true; // } // string id = Guid.NewGuid().ToString(); // List<SendLinkInfo> filesToUpload = GetFilesToUpload(processedAttachments, id); // List<string> emailAddresses = GetRecipientAddressList(mailItem); // string subject = ConvertLineFeed2WhiteSpace(mailItem.GetSubject()).TrimEnd(); // // Upload to the cloud // var sendLinkAction = GetSendLinkAction(requestManager.Response); // var storageLinks = GetStorageLinks(requestManager.Response, sendLinkAction); // storageLinks.Authenticate(); // List<SendLinkInfo> filesUploaded = RetrieveLinks(storageLinks, sendLinkAction, requestManager.Response, filesToUpload, emailAddresses, subject, id); // // Update proxy for Notes extension manager // UpdateProxyForSendLink(mailItem, GetSendLinkText(), filesUploaded, id); // return true; //} //catch (StorageUnavailableException ex) //{ // // note, the class name for Notes window is SWT_Window0 however class name is not unique to notes (most SWT framework apps will have this class name) // WsMessage.ShowMessage(IntPtr.Zero, Resources.PleaseCheckYourInternetConnection, MessageButtons.WsOK, MessageBranding.WsProtect, // MessageType.WsErrorIcon, Resources.UnableToConnectToSendLink, -1); // throw new AbortSendLinkException(ex.Message); //} //catch (Exception e) //{ // Interop.Logging.Logger.LogError(e); // throw; //} }
private void RemoveNonBccWhiteListRecipientsFromDestinationItems(MailItem mailItem, RequestManager requestManager) { var bccList = BccWhiteList.GetBCCList(mailItem.BCC); var items = requestManager.EnforceResponse.ModifiedRequest.Destination.Items .Where(it => !it.Properties.Any(p => string.Equals(p.Name, "AddressType", StringComparison.InvariantCulture) && string.Equals(p.Value, "BCC", StringComparison.InvariantCulture)) || bccList.Any(adress => string.Equals(adress, it.Content))) .Select(i => i).ToArray(); requestManager.EnforceResponse.ModifiedRequest.Destination.Items = items; }
internal bool CreateListOfAttachmentsToSendLink(MailItem mailItem, PolicyContent.Attachment[] builtup, RequestManager requestManager, ref List<PolicyContent.Attachment> listAttachments) { Logger.LogInfo("Matching the original attachments with the rebuilt collection and returning a list of items to SendLink"); // ensure we have Recordkey of each non-signature attachment MessageBodyFormat bodyFormat; if (UseOutlookDOMForProcessing) { using (OutlookMailProxy outlookMailProxy = new OutlookMailProxy(mailItem)) { bodyFormat = OutlookBodyFormat.GetMessageBodyFormat(outlookMailProxy.FormattedBodyText); Logger.LogInfo("Email body format: " + bodyFormat.ToString()); } } else { using (RedemptionMailProxy redemptionMailProxy = new RedemptionMailProxy(mailItem, true, DisableAccessToDOMAttachments)) { bodyFormat = OutlookBodyFormat.GetMessageBodyFormat(redemptionMailProxy.FormattedBodyText); Logger.LogInfo("Email body format: " + bodyFormat.ToString()); } } List<string> recordKeys = new List<string>(GetListofRecordKeys(mailItem, bodyFormat)); if (recordKeys.Count <= 0) { Logger.LogDebug("The list of record keys for the email is empty. Assuming the email only contains a signature image so there's nothing to SendLink."); return true; } foreach (PolicyContent.Attachment attachment in builtup) { // .msg files are flattened before normal Protect processing, so they need to be treated as // a special case as their IDs won't match against the processed file list. // i.e. att.Id == attachment.Id will not work (see below). if (!String.IsNullOrEmpty(attachment.FileName) && attachment.FileName.EndsWith(".msg", StringComparison.InvariantCultureIgnoreCase)) { CustomProperty[] properties = attachment.Properties; bool hasRecordKey = false; // .msg files should always have a RecordKey, but check anyway for error cases foreach (CustomProperty cp in properties) { hasRecordKey = (cp.Name == "RecordKey") && (recordKeys.Contains(cp.Value)); if (hasRecordKey) { listAttachments.Add(attachment); Logger.LogInfo(".msg file added to SendLink attachments list. Backing file: " + attachment.FileName); break; } } if (!hasRecordKey) { Logger.LogError("RecordKey was not found in the attachment's custom properties when processing .msg: " + attachment.FileName); return false; } } else { foreach (PolicyContent.Attachment att in requestManager.Request.Attachments) { // Match attachment on mailItem with processed equivalent in builtup collection // and add to SendLink list if (att.Id == attachment.Id) { CustomProperty[] properties = att.Properties; bool hasRecordKey = false; foreach (CustomProperty cp in properties) { hasRecordKey = (cp.Name == "RecordKey") && (recordKeys.Contains(cp.Value)); // we don't want signature images if (hasRecordKey) { if ((attachment.Properties == null) || (attachment.Properties.Length == 0)) { attachment.Properties = new[] { cp }; } listAttachments.Add(attachment); break; } } if (!hasRecordKey) { Logger.LogDebug("Unable to find a RecordKey for attachment. Assuming this is a signature image: " + attachment.Name); } break; } } } } return true; }
internal bool ExecuteSendLinkAction(MailItem mailItem, PolicyContent.Attachment[] builtup, RequestManager requestManager) { Logger.LogInfo("Executing Secure File Transfer Process"); Workshare.Analytics.WsAnalyticsListener analyticsListener = new Workshare.Analytics.WsAnalyticsListener(); analyticsListener.SendSendLinkStatistic(); if (!requestManager.SendAndProtect && !ShowBccWarning(mailItem, requestManager)) { return false; } try { List<PolicyContent.Attachment> listAttachments = new List<PolicyContent.Attachment>(); if (!CreateListOfAttachmentsToSendLink(mailItem, builtup, requestManager, ref listAttachments)) { return false; } if (listAttachments.Count <= 0) { Logger.LogInfo("List of attachments to SendLink is empty"); return true; } string id = Guid.NewGuid().ToString(); List<SendLinkInfo> links = GetLinks(requestManager.Response, mailItem, listAttachments, id); if (links != null && links.Count > 0) { Logger.LogInfo("Secure File Transfer: removing old attachments"); //SetMessageWindowVisible(mailItem, false); //This call will change the mailItem AdjustAttachments(mailItem, links, id); if (!string.IsNullOrEmpty(GetPropertyValue(requestManager.EnforceResponse.ModifiedRequest.Properties, MailMessagePropertyKeys.MimeContent)) || !string.IsNullOrEmpty(GetPropertyValue(requestManager.EnforceResponse.ModifiedRequest.Properties, MailMessagePropertyKeys.LargeMimeContent))) { string body; // Need to create a new proxy object because mailItem was changed in AdjustAttachments() if (UseOutlookDOMForProcessing) { using (OutlookMailProxy outlookMailProxy = new OutlookMailProxy(mailItem)) { body = outlookMailProxy.FormattedBodyText; body = OutlookFormattedTextProcessor.NewFormattedBodyText(body, links, mailItem); } } else { using (RedemptionMailProxy redemptionMailProxy = new RedemptionMailProxy(mailItem, true, DisableAccessToDOMAttachments)) { body = redemptionMailProxy.FormattedBodyText; body = OutlookFormattedTextProcessor.NewFormattedBodyText(body, links, mailItem, false); //private static void InsertHtmlIntoBodyText(ref string body, MessageBodyFormat bodyformat, IEnumerable<SendLinkInfo> links, MailItem mailItem) //sets body as null. if (body != null) { redemptionMailProxy.FormattedBodyText = body; } } } if (body != null) { SetPropertyValue(requestManager.EnforceResponse.ModifiedRequest.Properties, MailMessagePropertyKeys.FormattedBody, body); } } Logger.LogInfo("End Secure File Transfer Process"); // Allow the inspector window to redraw now, so that the attachments // and altered body text are immediately updated. System.Windows.Forms.Application.DoEvents(); } else { Logger.LogInfo("No Links to process"); } StartSendLinkClient(); mailItem.UserProperties.Add("SendLink", OlUserPropertyType.olText); } catch (Exception e) { //SetMessageWindowVisible(mailItem, true); Logger.LogError(e); throw; } return true; }
public bool ShowBccWarning(MailItem mailItem, RequestManager requestManager = null) { // check that the email's BCC doesn't contain any recipients other than // those specified in the BccAddressesWhiteList option list. if (!string.IsNullOrEmpty(mailItem.BCC)) { Logger.LogInfo("Email has BCC recipients"); if (!BccWhiteList.BccContainsWhiteListAddresses(mailItem.BCC)) { if (string.IsNullOrEmpty(mailItem.To) && string.IsNullOrEmpty(mailItem.CC)) { Interop.Messaging.WsMessage.ShowMessage(IntPtr.Zero, Resources.SENDLINK_MSG_HAS_ONLY_BCC, Interop.Messaging.MessageButtons.WsOK, Interop.Messaging.MessageBranding.WsDefault, Interop.Messaging.MessageType.WsInfoIcon, Resources.SENDLINK_MSG_HAS_BCC_HEADLINE, -1); return false; } } if (!BccWhiteList.ContainsOnlyWhiteListedAddresses(mailItem.BCC)) { if (Interop.Messaging.WsMessage.ShowMessage( IntPtr.Zero, Resources.SENDLINK_MSG_HAS_BCC, Interop.Messaging.MessageButtons.WsOKCancel, Interop.Messaging.MessageBranding.WsDefault, Interop.Messaging.MessageType.WsInfoIcon, Resources.SENDLINK_MSG_HAS_BCC_HEADLINE, -1) == Interop.Messaging.MessageResult.WsResultCancel) { return false; } Logger.LogInfo("Removing all non-white list BCC recipients"); mailItem.BCC = BccWhiteList.RemoveNonBccWhiteListRecipients(mailItem.BCC); if (requestManager != null) { RemoveNonBccWhiteListRecipientsFromDestinationItems(mailItem, requestManager); } } } return true; }
private void OnItemSend(IProxy mailItem, ref bool cancelEmailSend, ref ProcessResult processResult) { RequestManager requestManager = null; try { InitClientProgress(); PolicyContent.Request request = CreateRequest(mailItem); List<PolicyContent.Attachment> attachmentsNotProcessed = new List<PolicyContent.Attachment>(); // Remove the msg top level attachments from the request. We need to add them back after processing before updating the Notes proxy. // We do this because msg files are being lost in processing (ActionExecuter.RecreateAttachments)but since they are not supported // file types in Notes we can remove them from the attachment collection to be processed and add them back later after the call to // ProcessRequest. This does not affect msg files in zip containers and those are not lost. attachmentsNotProcessed.AddRange(ExtractAttachmentsOfTypeEmail(request)); bool bInternal = true; foreach (PolicyContent.RoutingItem rItem in request.Destination.Items) { foreach (PolicyContent.CustomProperty cProperty in rItem.Properties) { if ((cProperty.Name.ToLower(CultureInfo.InvariantCulture) == "internal") && (cProperty.Value.ToLower(CultureInfo.InvariantCulture) == "false")) { bInternal = false; break; } } if (!bInternal) break; } requestManager = new RequestManager(request, new NotesUIManager()); requestManager.MailItem = mailItem; requestManager.IsLotusNotesMailClient = true; bool bApplyPolicy = true; if (bInternal) { bApplyPolicy = Interop.Options.OptionApi.GetBool("EmailApplyProtectPolicyInternally"); } else { bApplyPolicy = Interop.Options.OptionApi.GetBool("EmailApplyProtectPolicyExternally"); } if (!bApplyPolicy) { cancelEmailSend = false; } else { bool bDisplayProgress = DisplayProgressOnMailSend(request); if (OptionApi.GetBool("EnableProtectSimple")) { requestManager.ProtectSimpleProfiles = GetWorkshareProfiles(mailItem, request, true, false); processResult = requestManager.ProcessRequestForProtectSimple(bDisplayProgress, true); } else { processResult = requestManager.ProcessRequest(m_clientProgress, bDisplayProgress, IsDynamicDiscoveryEnabled(request)); } switch (processResult) { case ProcessResult.CANCELLED: { cancelEmailSend = true; break; } case ProcessResult.PROCESSED: { // If a zip does not contain any supported documents the IgnoreForWorkshareActions is set (Workshare.PolicyContent.Attachment.IgnoreForWorkshareActions) // by the encryption manager (ContentEncryptionManager.ZipNeedsProcessing). This was done to improve Protect support for large files. // If the ZipNeedsProcessing property is set the attachment is removed from the response (Workshare.Policy.Adaptors.RequestAdaptor.GetURO). // We need to extract ANY attachment that was marked as IgnoreForWorkshareAction from the Request attachments and append them to the ModifiedRequest attachments // before updating the proxy else these attachments will be removed from the Notes mail item. attachmentsNotProcessed.AddRange(GetIgnoreForWorkshareActionAttachments(requestManager.Request)); // Add the msg top level attachments or attachments excluded from processing (IgnoreForWorkshareActions) to the processed collection before updating the proxy Workshare.PolicyContent.Attachment[] processedAttachments = requestManager.EnforceResponse.ModifiedRequest.Attachments; processedAttachments = AppendMissingAttachments(attachmentsNotProcessed.ToArray(), processedAttachments); DeleteProxyAttachments(mailItem, processedAttachments); // Not supported for Lotus Notes //if (SendLinkBase.ShouldExecuteSendLinkAction(requestManager.Response)) //{ // var notesSendLink = new NotesSendLink(); // cancelEmailSend = !notesSendLink.ExecuteSendLinkAction(mailItem, requestManager); // UpdateEmailContent(mailItem, requestManager.EnforceResponse.ModifiedRequest); // break; //} UpdateProxyAttachments(mailItem, processedAttachments); UpdateEmailContent(mailItem, requestManager.EnforceResponse.ModifiedRequest); cancelEmailSend = false; break; } case ProcessResult.ERRORS: case ProcessResult.EXCEPTION: { cancelEmailSend = !HandleErrors(requestManager.Errors); break; } //case ProcessResult.SERVER_PROFILE: //case ProcessResult.ERROR_OVERRIDE_USER_SELECTED_SEND: default: { // no violations or actions for this email - continue to send it. cancelEmailSend = false; break; } } } } catch (Exception ex) { cancelEmailSend = !ShouldContinueAfterException(ex); } finally { m_clientProgress.Complete(); m_clientProgress.Close(); } }
private bool ExecuteSendLinkAction(MailItem mailItem, Attachment[] builtup, RequestManager requestManager) { try { Cursor.Current = Cursors.WaitCursor; OutlookSendLink sendLink; // For Office version prior to 2010 we need access properties and attachments via MAPI if (!UseOutlookDOMForProcessing || OutlookVersion.Convert(m_application.Version) <= OutlookVersion.Version.Outlook2007) { sendLink = new OutlookSendLinkMAPI(); } else { sendLink = new OutlookSendLinkOOM(); } if (IsDeterministicSendEnabled) { var prSearchBytes = mailItem.PropertyAccessor.GetProperty(MAPIStringDefines.PR_SEARCH_KEY); var prSearchKey = Convert.ToBase64String(prSearchBytes); DeferredSendStore.Add(prSearchKey); } bool result = sendLink.ExecuteSendLinkAction(mailItem, builtup, requestManager); if (result && IsDeterministicSendEnabled) { sendLink.SetDeterministicSendDeferedTime(mailItem); } return result; } finally { Cursor.Current = Cursors.Default; } }
private void OnItemSend(MailItem mailItem, bool hasLargeAttachments, ref bool cancelEmailSend) { MailClientHookBase.PreCacheEventWaitForCompletion(); MailAttachmentTransform msgHandler = null; Request request = null; try { InitClientProgress(); request = CreateRequest(mailItem); request.HasLargeAttachments = hasLargeAttachments; //WriteOutRequest(request); msgHandler = new MailAttachmentTransform(GetMsgNestingLevelOption(), m_application, DisableAccessToDOMAttachments); List<Attachment> allAttachments = msgHandler.Flatten(request); if (msgHandler.AtLeastOneEmail) { request.Attachments = allAttachments.ToArray(); } m_uiManager.ParentHwnd = m_parentWnd; RequestManager requestManager = new RequestManager(request, m_uiManager, msgHandler.ExpandMSG, msgHandler.PackMSG); requestManager.TotalAttachmentSize = GetTotalAttachmentSize(mailItem); requestManager.IsSimpleMapi = IsSimpleMapi; requestManager.MailItem = mailItem; using (new WsActivationContext()) { bool bDisplayProgress = DisplayProgressOnMailSend(request); requestManager.SendAndProtect = SendAndProtect; requestManager.HasLargeAttachments = request.HasLargeAttachments; ProcessResult result; if (ProtectSimple) { bool isCorporateAccount = GetAccountType(mailItem) == MsOutlook.OlAccountType.olExchange; requestManager.ProtectSimpleProfiles = GetWorkshareProfiles(mailItem.Application, request, isCorporateAccount, msgHandler.AtLeastOneEmail); // If any of the attachment is a large attachment, then just show send-link profiles, remove everything else if (request.HasLargeAttachments) { int i = 0; var profiles = new WorkshareProfileCollection(); foreach (WorkshareProfile profile in requestManager.ProtectSimpleProfiles.Values) { if (profile.Name.Contains("Secure File Transfer")) { profiles.Add(i++, profile); } } requestManager.ProtectSimpleProfiles = profiles; } result = requestManager.ProcessRequestForProtectSimple(bDisplayProgress, isCorporateAccount); } else { result = requestManager.ProcessRequest(m_clientProgress, bDisplayProgress, IsDynamicDiscoveryEnabled(request)); } switch (result) { case ProcessResult.CANCELLED: cancelEmailSend = true; break; case ProcessResult.PROCESSED: cancelEmailSend = false; ////////////////////////////////////////////////////////////////////////////////////////// // JE - 21.01.2010 // This code block ensures that for simple attachments (i.e not containers - zip,msg) // we will only replace the attachment on the email if we have processed it. // Container atachments will currently always be replaced with rebuilt versions // that contain copies of the original files that may or may not have been processed. ////////////////////////////////////////////////////////////////////////////////////////// Attachment[] builtup = requestManager.EnforceResponse.ModifiedRequest.Attachments; if (requestManager.ReplaceAllAttachments()) { // This is used for the Cryptzone Secure Email Action // We can only support one Action that has this property and still function // in a reasonable fashion since we are allowing the Action to remove all // attachments and replace then with completely new ones. JE 19.10.2011 msgHandler.ReplaceAttachments(mailItem, builtup); } else { List<Attachment> processedbuiltup = requestManager.GetTopLevelProcessedAttachments(); // VE263 Consolidate all the attachments (processed and unprocessed), so that we can recreate the email and have all the attachments in their original order. // Otherwise modified attachments would be added to the end of the attachment list, ie no longer in the original order. builtup = BuildMsgAndProcessedAttachments(msgHandler, builtup, processedbuiltup); if (SendLinkBase.ShouldExecuteSendLinkAction(requestManager.Response)) { IsSendLink = ExecuteSendLinkAction(mailItem, builtup, requestManager); cancelEmailSend = !IsSendLink; } else { msgHandler.ReplaceProcessedAttachments(mailItem, builtup, requestManager.GetGroupedZipOptions()); } } if (!cancelEmailSend) { if (IsSendLink) { SendLinkUpdateEmailContent(mailItem, requestManager.EnforceResponse.ModifiedRequest); } else { UpdateEmailContent(mailItem, requestManager.EnforceResponse.ModifiedRequest); } SetHeaderProcessingInfo(mailItem, requestManager.EnforceResponse.ModifiedRequest); SetProcessedByWorkshareProtect(mailItem); RemoveCustomProperties(mailItem); } break; //VE 4955 - Don't tag the message (XHeader). Protect Server should //process the message if Protect Client failed to process the message //and the user selected to send anyway. case ProcessResult.ERROR_OVERRIDE_USER_SELECTED_SEND: cancelEmailSend = false; break; // I presume that an Exception result is actually // handled by a catch block, but case added here // to make sure that we show an error if it isn't. case ProcessResult.ERRORS: case ProcessResult.EXCEPTION: cancelEmailSend = !HandleErrors(requestManager.Errors); break; default: //no violations or actions for this email - continue to send it. if (request.HasLargeAttachments) { // and no policy triggered (probably because they are all not-supported types) // then we need to replace the place-holder-files (for large attachments) with actual attachments msgHandler.ReplaceAttachments(mailItem, request.Attachments); } IsProtectDisabledForCurrentRouting = true; cancelEmailSend = false; SetHeaderProcessingInfo(mailItem, requestManager.Request); SetProcessedByWorkshareProtect(mailItem); RemoveCustomProperties(mailItem); break; } } } catch (Exception ex) { cancelEmailSend = !ShouldContinueAfterException(ex); } finally { if (!cancelEmailSend && request != null) { foreach (var att in request.Attachments) { ContentEncryptionManager.ClearPasswordCacheFor(att); } } if (m_clientProgress != null) { m_clientProgress.Complete(); m_clientProgress.Close(); } if (request != null) { request.Dispose(); request = null; } // Explicitly clear up Redemption in case any extended MAPI objects are left lying around IWSUtilities utils = Oif.CreateUtilities(); utils.Cleanup(); if (msgHandler != null) { msgHandler.Dispose(); } Interop.Logging.Logger.LogInfo("Shutting down application cache instance."); OfficeApplicationCache.Instance.ShutDown(); } }