public void Test03SetNestingLevel()
		{
			using (MailAttachmentTransform mat = new MailAttachmentTransform(MailAttachmentTransform.DefaultNestingDepth, null))
			{
				Assert.AreEqual(MailAttachmentTransform.DefaultNestingDepth, mat.NestingDepth, "Incorrect nesting level set");
			}
		}
		public void Test04ModifiedRequestSingleEmbeddedEmail()
		{
			//setup
			Request request = GetRequest("1Doc1Msg1Doc1Xls.request");
			Assert.AreEqual(2, request.Attachments.Length, "Initial request to be set up with 2 attachments");

			//execute
			using (MailAttachmentTransform mat = new MailAttachmentTransform())
			{
				List<Attachment> flattened = new List<Attachment>(mat.Flatten(request));

				//verify

				Assert.AreEqual(3, flattened.Count, "Modified request to contain 3 attachments");
				VerifyAttachmentSanity(flattened);

				IAttachmentNode structure = mat.AttachmentStructure;
				Assert.IsNull(structure.Attachment, "Top level attachment is null - top level is children only.");
				Assert.AreEqual(2, structure.Children.Count, "Expect two attachments at first tree depth");

				Assert.AreEqual("Destructive Testing Doc.docx", structure.Children[0].Attachment.Name);
				Assert.AreEqual("Word and PPT.msg", structure.Children[1].Attachment.Name);

				Assert.AreEqual(0, structure.Children[0].Children.Count);
				Assert.AreEqual(structure.Children[1].Children.Count, 2);

				Assert.AreEqual("50pager.doc", structure.Children[1].Children[0].Attachment.Name);
				Assert.AreEqual(0, structure.Children[1].Children[0].Children.Count);

				Assert.AreEqual("Title.ppt", structure.Children[1].Children[1].Attachment.Name);
				Assert.AreEqual(0, structure.Children[1].Children[1].Children.Count);
			}
		}
		public void Test02NestingLevelLowerThanZero()
		{
			using (MailAttachmentTransform mat = new MailAttachmentTransform(-1, null))
			{
			}
		}
		public void Test10FlattenAndBuildup()
		{
			// Attachments which have been flattened and then built back up should
			// contain the same number of items.  That's what this tests :-)

			Request request = GetRequest("1Doc1Msg1Doc1Xls.request");
			// The original request contains a docx and an embedded msg containing a ppt & doc
			Assert.AreEqual(2, request.Attachments.Length, "Initial request to be set up with 2 attachments");

			using (MailAttachmentTransform mat = new MailAttachmentTransform())
			{
				List<Attachment> flattened = new List<Attachment>(mat.Flatten(request));
				Assert.IsTrue(mat.AtLeastOneEmail);

				// flattened request attachments should be docx, ppt, doc
				Assert.AreEqual(3, flattened.Count, "Expected the Request to contain 3 attachments");
				VerifyAttachmentSanity(flattened);


				List<Attachment> repacked = mat.BuildUp(flattened);
				// Once repacked we expect the docx and msg again
				Assert.AreEqual(repacked.Count, 2);

				// Assign the rebuilt attachments to the request so that
				// we can reflatten them and retest that we still have 3 in total
				request.Attachments = repacked.ToArray();

				flattened = new List<Attachment>(mat.Flatten(request));
				Assert.IsTrue(mat.AtLeastOneEmail);

				// flattened attachments should still be docx, ppt, doc
				Assert.AreEqual(3, flattened.Count, "Expected the Request to contain 3 attachments");
			}

			CleanUpFiles();
		}
		public void Test01NestingLevelTooBig()
		{
			using (MailAttachmentTransform mat = new MailAttachmentTransform(MailAttachmentTransform.AbsoluteMailNestingDepth + 1, null))
			{
			}
		}
		public void Test09NestingLimitTurnedOff()
		{
			//setup
			Request request = GetRequest("1Msg1Ppt1Doc2Msg1Doc3Msg1Doc1Ppt.request");
			Assert.AreEqual(2, request.Attachments.Length, "Initial request to be set up with 2 attachments");

			//execute
			using (MailAttachmentTransform mat = new MailAttachmentTransform(0, null))
			{
				List<Attachment> flattened = mat.Flatten(request);

				//verify
				Assert.AreEqual(2, flattened.Count, "Modified request should contain 2 attachments");
				//todo: structure and type verification
			}
		}
		public void Test07RoundtripMultipleNestingLevel()
		{
			Request request = GetRequest("1Msg1Ppt1Doc2Msg1Doc3Msg1Doc1Ppt.request");
			using (MailAttachmentTransform mat = new MailAttachmentTransform())
			{
				//flatten, then build back up.
				List<Attachment> flat = mat.Flatten(request);

				//do nothing to flattened list - it has just been unpacked and then repacked.

				List<Attachment> builtUp = mat.BuildUp(flat);

				VerifyAttachments(new List<Attachment>(request.Attachments), builtUp);
			}
		}
		public void Test05ModifiedRequestMultipleEmbeddedEmail()
		{
			//setup
			Request request = GetRequest("1Msg1Ppt1Doc2Msg1Doc3Msg1Doc1Ppt.request");

			Assert.AreEqual(2, request.Attachments.Length, "Initial request to be set up with 2 attachments");

			//execute
			using (MailAttachmentTransform mat = new MailAttachmentTransform())
			{
				List<Attachment> flattened = mat.Flatten(request);

				//verify
				Assert.AreEqual(5, flattened.Count, "Modified request should contain 5 attachments");
				VerifyAttachmentSanity(flattened);

				IAttachmentNode tree = mat.AttachmentStructure;
				Assert.IsNull(tree.Attachment);
				Assert.AreEqual(2, tree.Children.Count);

				//1st attachment - a nested .msg with two documents
				Assert.AreEqual("Word and PPT.msg", tree.Children[0].Attachment.Name);

				Assert.AreEqual("50pager.doc", tree.Children[0].Children[0].Attachment.Name);
				Assert.AreEqual(0, tree.Children[0].Children[0].Children.Count);

				Assert.AreEqual("Title.ppt",
														tree.Children[0].Children[1].Attachment.Name);
				Assert.AreEqual(0, tree.Children[0].Children[1].Children.Count);

				//2nd attachment - a nested msg with two attachments, one of which is also a msg itself
				Assert.AreEqual("1 Doc and msg.msg", tree.Children[1].Attachment.Name);

				Assert.AreEqual("smart tags toc.doc", tree.Children[1].Children[0].Attachment.Name);
				Assert.AreEqual(0, tree.Children[1].Children[0].Children.Count);

				Assert.AreEqual("Word and PPT", tree.Children[1].Children[1].Attachment.Name);
				Assert.AreEqual(2, tree.Children[1].Children[1].Children.Count);

				//2nd nesting level - just two docs
				AttachmentNode nested = tree.Children[1].Children[1] as AttachmentNode;
				Assert.AreEqual("50pager.doc", nested.Children[0].Attachment.Name);
				Assert.AreEqual(0, nested.Children[0].Children.Count);

				Assert.AreEqual("Title.ppt", nested.Children[1].Attachment.Name);
				Assert.AreEqual(0, nested.Children[1].Children.Count);
			}
		}
		private Attachment[] BuildMsgAndProcessedAttachments(MailAttachmentTransform msgHandler, Attachment[] builtup, List<Attachment> Processedbuiltup)
		{
			// Rebuild msg - we replace msg files irrespective of whether their attachments are processed
			List<Attachment> listBuiltup = msgHandler.BuildUp(builtup);

			List<Attachment> attachments = new List<Attachment>();
			// At the top level we only want files that were processed or are msg files	(zips are already in "Processedbuiltup")		
			for (int i = 0; i < listBuiltup.Count; i++)
			{
				Attachment attach = listBuiltup[i];
				string name = string.Empty;
				// Using this property since the attachment name may not have an extension
				foreach (CustomProperty cp in attach.Properties)
				{
					if (cp.Name == "LocalFileName")
					{
						name = cp.Value;
						break;
					}
				}


				// Is the attachment a message(which will have been rebuilt)? if so add it
				if (((attach.ContentType.ToLower()).Contains("application/octet-stream") &&
					((name.ToLower()).Contains(".msg"))))
				{
					attach.IsProcessed = true;// Flag it as processed as its been rebuilt.
					attachments.Add(attach);
				}
				else
				{
					// Otherwise attach, unless we have a processed copy, in which case attach that instead
					Attachment processedAttachment = Processedbuiltup.Find(x => (x.Id.CompareTo(attach.Id) == 0));
					if (processedAttachment != null)
					{
						attachments.Add(processedAttachment);
					}
					else
					{
						attachments.Add(attach);
					}
				}
			}
			return attachments.ToArray();
		}
Beispiel #10
0
		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();
			}
		}