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); } } } }
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(); }
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(); } }