private void ZipAttachments(dynamic mailItem, IEnumerable<Workshare.PolicyContent.Attachment> processedAttachments, ZipAllOptions zipAll)
		{
			const string groupName = "attachments.zip";
			string filename = string.Empty;
			string attachName = string.Empty;
			string tempDir = string.Empty;
			try
			{
				Redemption.SafeMailItem safeMailItem = RedemptionLoader.new_SafeMailItem();
                using (new ComRelease(safeMailItem))
                {
                    safeMailItem.Item = mailItem.UnSafeMailItem;
                    RemoveAllAttachmentsFromMSGPreserveSignature(safeMailItem, mailItem.BodyFormat);
                    const int iRenderingPosition = 1;
                    IFile zipfile = FileFactory.Create(groupName, FileType.ZIP);

                    foreach (var attachment in processedAttachments)
                    {
                        if (!attachment.IsSignature)
                        {
                            IFile attachmentFile = FileFactory.Create(attachment.FileName, attachment.Name);
                            zipfile.Add(attachmentFile);
                        }
                    }

                    SetEncryption(zipfile, zipAll);
                    zipfile.PackContainer(zipAll.PassWord);
                    tempDir = FileToDisk(zipfile.FileName, zipfile);
                    attachName = Path.Combine(tempDir, zipfile.FileName);
                    Redemption.Attachment rdAttachment = safeMailItem.Attachments.Add(attachName,
                                                                                      OlAttachmentType.olByValue,
                                                                                      iRenderingPosition,
                                                                                      zipfile.DisplayName);
                    Encoding ansiEncoding = Encoding.GetEncoding(Encoding.Default.CodePage,
                                                                 new EncoderExceptionFallback(),
                                                                 new DecoderExceptionFallback());
                    try
                    {
                        byte[] ansiBytes = ansiEncoding.GetBytes(zipfile.FileName);
                    }
                    catch (EncoderFallbackException /*ex*/)
                    {
                        rdAttachment.set_Fields(MapiDefines.PR_ATTACH_LONG_FILENAME_W, zipfile.FileName);
                        rdAttachment.set_Fields(MapiDefines.PR_ATTACH_FILENAME_W, zipfile.FileName);
                        rdAttachment.set_Fields(MapiDefines.PR_DISPLAY_NAME_W, zipfile.DisplayName);
                    }
                }
			}
			catch (Exception ex)
			{
				Interop.Logging.Logger.LogError("RWSMailAttachmentTransform::GroupAttachmentsAsZip " + ex.ToString());
				throw;
			}
			finally
			{
				if (!string.IsNullOrEmpty(filename) && File.Exists(filename))
				{
					File.Delete(filename);
				}
				if (!string.IsNullOrEmpty(attachName) && File.Exists(attachName))
				{
					File.Delete(attachName);
				}
				if (!string.IsNullOrEmpty(tempDir) && Directory.Exists(tempDir))
				{
					Directory.Delete(tempDir);
				}
			}
		}
		private void SetEncryption(IFile file, ZipAllOptions zipAll)
		{
			if (!zipAll.AES)
			{
				return;
			}

			file.Properties["Encryption"] = "4";
			file.Properties["EncryptionKeyLength"] = "128";
		}
		public void ReplaceProcessedAttachments(dynamic mailItem, Workshare.PolicyContent.Attachment[] processedAttachments, ZipAllOptions groupedZip)
		{
			Redemption.SafeMailItem safeMailItem = RedemptionLoader.new_SafeMailItem();
            using (new ComRelease(safeMailItem))
            {
                safeMailItem.Item = mailItem.UnSafeMailItem;

                if ((groupedZip != null) && groupedZip.ZipAll && safeMailItem.Attachments.Count > 0)
                {
                    ZipAttachments(mailItem, processedAttachments, groupedZip);
                    return;
                }
                //AttachmentProperties
                Dictionary<string, AttachmentProperties> dictAttachmentProps =
                    new Dictionary<string, AttachmentProperties>(safeMailItem.Attachments.Count);
                GetAttachmentProperties(safeMailItem, dictAttachmentProps);

                Redemption.MAPIUtils redemptionMAPIUtils = RedemptionLoader.new_MAPIUtils();
                // Use .ToArray() to ensure the attachments are removed first, before any re-additions.
                var removedAttachments =
                    processedAttachments.Where(a => RemoveAttachment(safeMailItem, a)).ToArray();

                int renderingPosition = 1;
                foreach (var attachment in removedAttachments)
                {
                    string displayName = attachment.Name;
                    if (string.IsNullOrEmpty(displayName) || string.IsNullOrEmpty(displayName.Trim()))
                    {
                        displayName = UntitledAttachmentTitle;
                    }

                    string proposedFileName = GetProposedFileName(attachment);
                    string fileName = attachment.FileName;

                    DateTime creationTime = new DateTime();
                    DateTime lastModificationTime = new DateTime();

                    // For unmodified attachments we want to restore the timestamp so they appear as they were (ie unchanged!)
                    // We need to set the file creation/modification correctly, removing/adding resets the timestamp
                    if (!attachment.IsProcessed &&
                        GetAttachmentFileTimes(attachment, dictAttachmentProps, ref creationTime,
                                                ref lastModificationTime))
                    {
                        File.SetCreationTime(fileName, creationTime);
                        File.SetLastWriteTime(fileName, lastModificationTime);
                    }

                    Redemption.Attachment redemptionAttachment;

                    // [VE2711] Use the DisplayName instead of MessageItem.Subject when adding .msg items back.
                    // DMS and other programes can add msg attachments with a custom name and not the .msg Subject.
                    // [DE9621/CR00126587] implemented the seperated handler for .msg files. Previously .msg files where handled
                    // the same way as any other attachments and this used to as still is for all other attachments  
                    // the Attachment.Name property (the original DisplayName). As part of DE9621 the DisplayName was 
                    // changed to the MessageItem.Subject. This was done (a) because that is the default MS Outlook 
                    // behaviour if you add a .msg file to an email as an attachment and (b) the code that set 
                    // Attachment.Name in Workshare.Mime.Conversions.OutlookAttachmentsProxy.this[int] was changed 
                    // to use the FileName instead of the DisplayName [DE9621/CR00126587][DE9310/CR00123897], which ment the 
                    // original DisplayName was nolonger available. Related change is in OutlookAttachmentsProxy.cs

                    if (fileName.EndsWith(".msg", StringComparison.InvariantCultureIgnoreCase))
                    {
                        Redemption.MessageItem redemptionMessageItem = redemptionMAPIUtils.GetItemFromMsgFile(fileName);

                        // Need to release "msgItem" before delete the file, as it holds reference to the file.
                        using (new ComRelease(redemptionMessageItem))
                        {
                            // Attach .msg via "olEmbeddedItem" to avoid Unicode msg attachment being blocked by "Symantec anti-virus Outlook addin"
                            redemptionAttachment = safeMailItem.Attachments.Add(redemptionMessageItem,
                                                                                OlAttachmentType.olEmbeddeditem,
                                                                                renderingPosition, displayName);

                            // Redemption does not set Unicode displayname properly, need to set manually.
                            redemptionAttachment.set_Fields(MapiDefines.PR_DISPLAY_NAME_W, displayName);
                        }
                    }
                    else
                    {
                        redemptionAttachment = safeMailItem.Attachments.Add(fileName, OlAttachmentType.olByValue,
                                                                            renderingPosition, displayName);

                        try
                        {
                            // Redemption.dll (current version 4.6.0.924) didn't handle Unicode correctly for 
                            // Attachments.Add() function. It attempts to convert Unicode filename to Ansi code
                            // based on current System Locale ("Language for non-Unicode program"). 
                            // Attachment with "e.g. Chinese/Cyrillic" filename will appear as "????".
                            // Check whether filename can be encoded with current default code page.
                            Encoding ansiEncoding = Encoding.GetEncoding(Encoding.Default.CodePage,
                                                                            new EncoderExceptionFallback(),
                                                                            new DecoderExceptionFallback());
                            // If not ansi will fail with EncoderFallbackException
                            byte[] ansiBytes = ansiEncoding.GetBytes(proposedFileName);
                        }
                        catch (EncoderFallbackException)
                        {
                            // If cannot convert using current system codepage, Redemption's Attachments.add() 
                            // will not behave correctly. Have to manually set the FileName and Displayname with Unicode string.
                            redemptionAttachment.set_Fields(MapiDefines.PR_ATTACH_LONG_FILENAME_W, proposedFileName);
                            redemptionAttachment.set_Fields(MapiDefines.PR_ATTACH_FILENAME_W, proposedFileName);
                            redemptionAttachment.set_Fields(MapiDefines.PR_DISPLAY_NAME_W, displayName);
                        }
                    }

                    string recordkey = GetPropertyValue(attachment.Properties, PropertyNames.RecordKey);
                    AttachmentProperties attProps;
                    if (dictAttachmentProps.TryGetValue(recordkey, out attProps))
                    {
                        redemptionAttachment.set_Fields(MapiDefines.PR_ATTACH_CONTENT_ID, attProps.OContentId);
                        redemptionAttachment.set_Fields(MapiDefines.PR_ATTACHMENT_HIDDEN, attProps.OHidden);
                        redemptionAttachment.set_Fields(MapiDefines.PR_ATTACHMENT_FLAGS, attProps.OFlags);
                        redemptionAttachment.set_Fields(MapiDefines.PR_RENDERING_POSITION, attProps.OPosition);
                        redemptionAttachment.set_Fields(0x7FFF000B, attProps.OContactPhoto);
                    }
                    else
                    {
                        //We have an attachment that was not in the original collection.
                        //Dont have all the info but we at least know the attachment content id.
                        if (!string.IsNullOrEmpty(attachment.Id))
                        {
                            redemptionAttachment.set_Fields(MapiDefines.PR_ATTACH_CONTENT_ID, attachment.Id);
                        }
                    }

                    ++renderingPosition;
                }
                
                if (redemptionMAPIUtils != null)
                {
                    redemptionMAPIUtils.Cleanup();
                    
                    if (Marshal.IsComObject(redemptionMAPIUtils))
                    {
                        Marshal.ReleaseComObject(redemptionMAPIUtils);
                    }
                }
            }		
		}
Пример #4
0
		public void TestReplaceProcessedAttachments_3()
		{
            using (dynamic delFolder = _outlookapp.Session.GetDefaultFolder(MSOutlook.OlDefaultFolders.olFolderDeletedItems))
            {
                using (dynamic mailitem = (MSOutlook.MailItem)(_outlookapp.CreateItem(MSOutlook.OlItemType.olMailItem)))
                {
                    try
                    {
                        string testfile = Path.Combine(TestFiles, "test.doc");
                        mailitem.Attachments.Add(testfile, MSOutlook.OlAttachmentType.olByValue, 1, "Monster Truck");
                        string testfile2 = Path.Combine(TestFiles, "test2.doc");
                        mailitem.Attachments.Add(testfile2, MSOutlook.OlAttachmentType.olByValue, 2, "Monster Truck - 2");
                        mailitem.Save(); // need to save before passing to safeMailItem.Item
                        Assert.IsTrue(mailitem.Attachments.Count == 2, "Num of attachments should be 2");

                        using (
                            OOMWSMailAttachmentTransform mat =
                                _oif.CreateOOMWSMailAttachmentTransform() as OOMWSMailAttachmentTransform)
                        {
                            MSOutlook.Attachment att = mailitem.Attachments[1];
                            byte[] bytes = GetFields(att, MAPIProxy.MAPIStringDefines.PR_RECORD_KEY);

                            const string sNewName = "test3.doc";
                            string sNewFileName = Path.Combine(TestFiles, sNewName);
                            Attachment[] wsAttachments =
                                {
                                    new Attachment(sNewName, sNewFileName, "empty", null, null, false)
                                };
                            wsAttachments[0].Content = new byte[] {0};
                            string recordkey = GetStringFromBytes(mat, bytes);
                            wsAttachments[0].Properties = new CustomProperty[]
                                                              {new CustomProperty(PropertyNames.RecordKey, recordkey)};

                            ZipAllOptions groupedZipOptions = new ZipAllOptions {ZipAll = true};
                            if (mat != null)
                            {
                                mat.ReplaceProcessedAttachments(mailitem, wsAttachments, groupedZipOptions);
                            }
                        }

                        Assert.IsTrue(mailitem.Attachments.Count == 1, "Num of attachments should be 1");
                        Assert.IsTrue(mailitem.Attachments[1].FileName.ToLower() == "attachments.zip",
                                      "Single attachment should be attachments.zip");
                    }
                    finally
                    {
                        mailitem.Delete();
                    }
                }
            }
		}
		private void ZipAttachments(Attachments attachments, IEnumerable<Attachment> processedAttachments, ZipAllOptions zipAll, OlBodyFormat bodyFormat)
		{
			IFile zipfile;
			const string groupName = "attachments.zip";
			string filename = string.Empty;
			string attachName = string.Empty;
			string tempDir = string.Empty;

			try
			{
				RemoveAllAttachmentsFromMsg(attachments, bodyFormat);
				const int iRenderingPosition = 1;
				zipfile = FileFactory.Create(groupName, FileType.ZIP);

				foreach (Attachment attachment in processedAttachments)
				{
					if (!attachment.IsSignature)
					{
						IFile attachmentFile = FileFactory.Create(attachment.FileName, attachment.Name);
						zipfile.Add(attachmentFile);
					}
				}
				SetEncryption(zipfile, zipAll);
				zipfile.PackContainer(zipAll.PassWord);
				tempDir = FileToDisk(zipfile.FileName, zipfile);
				attachName = Path.Combine(tempDir, zipfile.FileName);
				Microsoft.Office.Interop.Outlook.Attachment newAttachment = attachments.Add(attachName, OlAttachmentType.olByValue, iRenderingPosition, zipfile.DisplayName);

				Encoding ansiEncoding = Encoding.GetEncoding(Encoding.Default.CodePage, new EncoderExceptionFallback(), new DecoderExceptionFallback());
				try
				{
					byte[] ansiBytes = ansiEncoding.GetBytes(zipfile.FileName);
				}
				catch (EncoderFallbackException /*ex*/)
				{
					newAttachment.PropertyAccessor.SetProperty(MAPIStringDefines.PR_ATTACH_LONG_FILENAME_W, zipfile.FileName);
					newAttachment.PropertyAccessor.SetProperty(MAPIStringDefines.PR_ATTACH_FILENAME_W, zipfile.FileName);
					newAttachment.PropertyAccessor.SetProperty(MAPIStringDefines.PR_DISPLAY_NAME_W, zipfile.DisplayName);
				}
			}
			catch (Exception ex)
			{
				Interop.Logging.Logger.LogError(ex);
				throw;
			}
			finally
			{
				if (!string.IsNullOrEmpty(filename) && File.Exists(filename))
				{
					File.Delete(filename);
				}
				if (!string.IsNullOrEmpty(attachName) && File.Exists(attachName))
				{
					File.Delete(attachName);
				}
				if (!string.IsNullOrEmpty(tempDir) && Directory.Exists(tempDir))
				{
					Directory.Delete(tempDir);
				}
			}
		}
		public void ReplaceProcessedAttachments(dynamic mailItem, Attachment[] processedAttachments, ZipAllOptions groupedZip)
		{
			Attachments attachments = mailItem.Attachments;

			if ((groupedZip != null) && groupedZip.ZipAll && attachments.Count > 0)
			{
				ZipAttachments(attachments, processedAttachments, groupedZip, mailItem.BodyFormat);
				return;
			}

			//AttachmentProperties
			Dictionary<string, AttachmentProperties> dictAttachmentProps = new Dictionary<string, AttachmentProperties>(attachments.Count);
			GetAttachmentProperties(attachments, dictAttachmentProps);

			// Use .ToArray() to ensure the attachments are removed first, before any re-additions.
			Attachment[] removedAttachments = processedAttachments.Where(a => RemoveAttachment(attachments, a)).ToArray();
			
			int renderingPosition = 1;
			foreach (Attachment attachment in removedAttachments)
			{
				string displayName = attachment.Name;
				if (string.IsNullOrEmpty(displayName) || string.IsNullOrEmpty(displayName.Trim()))
				{
					displayName = UntitledAttachmentTitle;
				}

				string fileName = attachment.FileName;

				DateTime creationTime = new DateTime();
				DateTime lastModificationTime = new DateTime();

				// For unmodified attachments we want to restore the timestamp so they appear as they were (ie unchanged!)
				// We need to set the file creation/modification correctly, removing/adding resets the timestamp
				if (!attachment.IsProcessed &&
					GetAttachmentFileTimes(attachment, dictAttachmentProps, ref creationTime, ref lastModificationTime))
				{
					File.SetCreationTime(fileName, creationTime);
					File.SetLastWriteTime(fileName, lastModificationTime);
				}

				int position = renderingPosition;
				string recordkey = GetPropertyValue(attachment.Properties, PropertyNames.RecordKey);
				AttachmentProperties attProps;
				bool bPropsAvailable = dictAttachmentProps.TryGetValue(recordkey, out attProps);
				if (bPropsAvailable)
				{
					if ((int) attProps.OPosition != -1)
					{
						position = (int) attProps.OPosition + 1;
					}
					else
					{
						position = -1;
					}
				}

				Microsoft.Office.Interop.Outlook.Attachment newAttachment;
				OlAttachmentType attachType = OlAttachmentType.olByValue;
				if (fileName.EndsWith(".msg", StringComparison.InvariantCultureIgnoreCase))
				{
					// Attach .msg via "olEmbeddedItem" to avoid Unicode msg attachment being blocked by "Symantec anti-virus Outlook addin"
					attachType = OlAttachmentType.olEmbeddeditem;
				}

				newAttachment = attachments.Add(fileName, attachType, Missing.Value, displayName);

				if (newAttachment != null)
				{
					if (bPropsAvailable)
					{
						List<string> lProperties = new List<string>();
						List<object> lValues = new List<object>();
						
						if (attProps.OHidden is bool)
						{
							lProperties.Add(MAPIStringDefines.PR_ATTACHMENT_HIDDEN);
							lValues.Add(attProps.OHidden);

							if ((attProps.OContentId is string) && (attProps.OContentId as string != string.Empty) && (bool)attProps.OHidden)
							{
								lProperties.Add(MAPIStringDefines.PR_ATTACH_CONTENT_ID);
								lValues.Add(attProps.OContentId);
							}
						}
						if ((attProps.OFlags is int) && ((int) attProps.OFlags >= 0))
						{
							lProperties.Add(MAPIStringDefines.PR_ATTACHMENT_FLAGS);
							lValues.Add(attProps.OFlags);
						}
						if ((attProps.OPosition is int) && ((int) attProps.OPosition >= -1))
						{
							lProperties.Add(MAPIStringDefines.PR_RENDERING_POSITION);
							lValues.Add(attProps.OPosition);
							if (position != -1)
								newAttachment.Position = position;
						}
						if (attProps.OContactPhoto is bool)
						{
							lProperties.Add(MAPIStringDefines.PR_ATTACHMENT_CONTACTPHOTO);
							lValues.Add(attProps.OContactPhoto);
						}

						newAttachment.PropertyAccessor.SetProperties(lProperties.ToArray(), lValues.ToArray());
					}
					else
					{
						//We have an attachment that was not in the original collection.
						//Dont have all the info but we at least know the attachment content id.
						if (!string.IsNullOrEmpty(attachment.Id))
						{
							newAttachment.PropertyAccessor.SetProperty(MAPIStringDefines.PR_ATTACH_CONTENT_ID, attachment.Id);
						}
					}
				}

				++renderingPosition;
			}
			mailItem.Save();
		}
Пример #7
0
		public void TestReplaceProcessedAttachments_3()
		{
			MSOutlook.MAPIFolder delFolder = _outlookapp.Session.GetDefaultFolder(MSOutlook.OlDefaultFolders.olFolderDeletedItems);
			MSOutlook.MailItem mailitem = (MSOutlook.MailItem) (_outlookapp.CreateItem(MSOutlook.OlItemType.olMailItem));
			try
			{
				string testfile = Path.Combine(TestFiles, "test.doc");
				mailitem.Attachments.Add(testfile, MSOutlook.OlAttachmentType.olByValue, 1, "Monster Truck");
				string testfile2 = Path.Combine(TestFiles, "test2.doc");
				mailitem.Attachments.Add(testfile2, MSOutlook.OlAttachmentType.olByValue, 2, "Monster Truck - 2");
				mailitem.Save();    // need to save before passing to safeMailItem.Item
				Assert.IsTrue(mailitem.Attachments.Count == 2, "Num of attachments should be 2");
				using (IWSMail mail = _oif.CreateWSMail(mailitem))
				{
					using (IWSAttachment att = mail.Attachments.Item(1))
					{
						object[] data = (object[]) att.GetFields(MAPIProxy.MapiDefines.PR_RECORD_KEY);
						
						const string sNewName = "test3.doc";
						string sNewFileName = Path.Combine(TestFiles, sNewName);
						Attachment[] wsAttachments = { new Attachment(sNewName, sNewFileName, "empty", null, null, false) };
						wsAttachments[0].Content = new byte[] { 0 };

						using (RWSMailAttachmentTransform mat = _oif.CreateWSMailAttachmentTransform() as RWSMailAttachmentTransform)
						{
							if (mat != null)
							{
								Type t = mat.GetType();
								MethodInfo minfoGetStringFromBytes = t.GetMethod("GetStringFromBytes",
								                                                 BindingFlags.NonPublic | BindingFlags.Instance);
								string recordkey = (string) minfoGetStringFromBytes.Invoke(mat, new object[] {data});
								wsAttachments[0].Properties = new[] {new CustomProperty(PropertyNames.RecordKey, recordkey)};

								ZipAllOptions groupedZipOptions = new ZipAllOptions {ZipAll = true};
								mat.ReplaceProcessedAttachments(mailitem, wsAttachments, groupedZipOptions);
							}
						}
					}
				}

				using (IWSMail mail2 = _oif.CreateWSMail(mailitem))
				{
					Assert.IsTrue(mail2.Attachments.Count == 1, "Num of attachments should be 1");
					Assert.IsTrue(mail2.Attachments.Item(0).FileName.ToLower() == "attachments.zip", "Single attachment should be attachments.zip");
				}
			}
			finally
			{
				mailitem.Delete();
				delFolder.Items.Remove(1);
                ((IDisposable)mailitem).Dispose();
			}
		}