/// <summary> /// Creates this object and sets all the needed properties /// </summary> /// <param name="sender">The <see cref="Sender"/> of the E-mail</param> /// <param name="representing">The <see cref="MsgKit.Representing"/> sender of the E-mail</param> /// <param name="subject">The subject of the E-mail</param> /// <param name="draft">Set to <c>true</c> to save the E-mail as a draft message</param> public Email(Sender sender, Representing representing, string subject, bool draft = false) { Sender = sender; Representing = representing; Subject = subject; IconIndex = MessageIconIndex.NewMail; Draft = draft; }
/// <summary> /// Creates this object and sets all the needed properties /// </summary> /// <param name="sender">The <see cref="Sender"/> of the E-mail</param> /// <param name="representing">The <see cref="MsgKit.Representing"/> sender of the E-mail</param> /// <param name="subject">The subject of the E-mail</param> /// <param name="draft">Set to <c>true</c> to save the E-mail as a draft message</param> public Email(Sender sender, Representing representing, string subject, bool draft = false) { Sender = sender; Representing = representing; Subject = subject; Importance = MessageImportance.IMPORTANCE_NORMAL; IconIndex = MessageIconIndex.NewMail; Draft = draft; }
/// <summary> /// Writes all the properties that are part of the <see cref="Email"/> object either as <see cref="CFStorage"/>'s /// or <see cref="CFStream"/>'s to the <see cref="CompoundFile.RootStorage"/> /// </summary> internal void WriteToStorage() { var rootStorage = CompoundFile.RootStorage; Class = MessageClass.IPM_Note; MessageSize += Recipients.WriteToStorage(rootStorage); MessageSize += Attachments.WriteToStorage(rootStorage); var recipientCount = Recipients.Count; var attachmentCount = Attachments.Count; TopLevelProperties.RecipientCount = recipientCount; TopLevelProperties.AttachmentCount = attachmentCount; TopLevelProperties.NextRecipientId = recipientCount; TopLevelProperties.NextAttachmentId = attachmentCount; if (!string.IsNullOrEmpty(InternetMessageId)) { TopLevelProperties.AddProperty(PropertyTags.PR_INTERNET_MESSAGE_ID_W, InternetMessageId); } TopLevelProperties.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId()); TopLevelProperties.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey()); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_SUPPORT_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_UNICODE_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_ALTERNATE_RECIPIENT_ALLOWED, true, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_HASATTACH, attachmentCount > 0); TopLevelProperties.AddProperty(PropertyTags.PR_TRANSPORT_MESSAGE_HEADERS_W, TransportMessageHeaders); var messageFlags = MessageFlags.MSGFLAG_UNMODIFIED; if (attachmentCount > 0) { messageFlags |= MessageFlags.MSGFLAG_HASATTACH; } TopLevelProperties.AddProperty(PropertyTags.PR_INTERNET_CPID, Encoding.UTF8.CodePage); TopLevelProperties.AddProperty(PropertyTags.PR_BODY_W, BodyText); if (!string.IsNullOrEmpty(BodyHtml)) { TopLevelProperties.AddProperty(PropertyTags.PR_HTML, BodyHtml); } if (Draft) { messageFlags |= MessageFlags.MSGFLAG_UNSENT | MessageFlags.MSGFLAG_FROMME; IconIndex = MessageIconIndex.UnsentMail; if (string.IsNullOrWhiteSpace(BodyRtf) && !string.IsNullOrWhiteSpace(BodyHtml)) { BodyRtf = Strings.GetEscapedRtf(BodyHtml); BodyRtfCompressed = true; } } if (!SentOn.HasValue) { SentOn = DateTime.UtcNow; } TopLevelProperties.AddProperty(PropertyTags.PR_CLIENT_SUBMIT_TIME, SentOn.Value.ToUniversalTime()); TopLevelProperties.AddProperty(PropertyTags.PR_MESSAGE_FLAGS, messageFlags); TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS, MapiAccess.MAPI_ACCESS_DELETE | MapiAccess.MAPI_ACCESS_MODIFY | MapiAccess.MAPI_ACCESS_READ); TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS_LEVEL, MapiAccess.MAPI_ACCESS_MODIFY); TopLevelProperties.AddProperty(PropertyTags.PR_OBJECT_TYPE, MapiObjectType.MAPI_MESSAGE); SetSubject(); TopLevelProperties.AddProperty(PropertyTags.PR_SUBJECT_W, Subject); TopLevelProperties.AddProperty(PropertyTags.PR_NORMALIZED_SUBJECT_W, SubjectNormalized); TopLevelProperties.AddProperty(PropertyTags.PR_SUBJECT_PREFIX_W, SubjectPrefix); TopLevelProperties.AddProperty(PropertyTags.PR_CONVERSATION_TOPIC_W, SubjectNormalized); // http://www.meridiandiscovery.com/how-to/e-mail-conversation-index-metadata-computer-forensics/ // http://stackoverflow.com/questions/11860540/does-outlook-embed-a-messageid-or-equivalent-in-its-email-elements //propertiesStream.AddProperty(PropertyTags.PR_CONVERSATION_INDEX, Subject); // TODO: Change modification time when this message is opened and only modified var utcNow = DateTime.UtcNow; TopLevelProperties.AddProperty(PropertyTags.PR_CREATION_TIME, utcNow); TopLevelProperties.AddProperty(PropertyTags.PR_LAST_MODIFICATION_TIME, utcNow); TopLevelProperties.AddProperty(PropertyTags.PR_PRIORITY, Priority); TopLevelProperties.AddProperty(PropertyTags.PR_IMPORTANCE, Importance); TopLevelProperties.AddProperty(PropertyTags.PR_MESSAGE_LOCALE_ID, CultureInfo.CurrentCulture.LCID); TopLevelProperties.AddProperty(PropertyTags.PR_ICON_INDEX, IconIndex); if (Sender != null) { Sender.WriteProperties(TopLevelProperties); } if (Receiving != null) { Receiving.WriteProperties(TopLevelProperties); } if (Representing != null) { Representing.WriteProperties(TopLevelProperties); } if (ReceivingRepresenting != null) { ReceivingRepresenting.WriteProperties(TopLevelProperties); } if (recipientCount > 0) { var displayTo = new List <string>(); var displayCc = new List <string>(); var displayBcc = new List <string>(); foreach (var recipient in Recipients) { switch (recipient.RecipientType) { case RecipientType.To: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayTo.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayTo.Add(recipient.Email); } break; case RecipientType.Cc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayCc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayCc.Add(recipient.Email); } break; case RecipientType.Bcc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayBcc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayBcc.Add(recipient.Email); } break; default: throw new ArgumentOutOfRangeException(); } } TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_TO_W, string.Join(";", displayTo), PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_CC_W, string.Join(";", displayCc), PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_BCC_W, string.Join(";", displayBcc), PropertyFlags.PROPATTR_READABLE); } if (!string.IsNullOrEmpty(BodyRtf) && BodyRtfCompressed) { TopLevelProperties.AddProperty(PropertyTags.PR_RTF_COMPRESSED, RtfCompressor.Compress(Encoding.ASCII.GetBytes(BodyRtf))); TopLevelProperties.AddProperty(PropertyTags.PR_RTF_IN_SYNC, true); } }
/// <summary> /// Sends an appointment with sender, representing, subject, draft. /// </summary> /// <param name="sender"> Contains sender name and email. </param> /// <param name="representing">Contains who this appointment is representing. </param> /// <param name="subject"> Contains the subject for this appointment. </param> /// <param name="draft"> Is this a draft?</param> public Appointment(Sender sender, Representing representing, string subject, bool draft = false) : base(sender, representing, subject, draft) { }
/// <summary> /// Converts an EML file to MSG format /// </summary> /// <param name="emlFileName">The EML (MIME) file</param> /// <param name="msgFileName">The MSG file</param> public static void ConvertEmlToMsg(string emlFileName, string msgFileName) { var eml = MimeMessage.Load(emlFileName); var sender = new Sender(string.Empty, string.Empty); if (eml.From.Count > 0) { var mailAddress = ((MailboxAddress)eml.From[0]); sender = new Sender(mailAddress.Address, mailAddress.Name); } var representing = new Representing(string.Empty, string.Empty); if (eml.ResentSender != null) { representing = new Representing(eml.ResentSender.Address, eml.ResentSender.Name); } var msg = new Email(sender, representing, eml.Subject) { SentOn = eml.Date.UtcDateTime, InternetMessageId = eml.MessageId }; using (var memoryStream = new MemoryStream()) { eml.Headers.WriteTo(memoryStream); msg.TransportMessageHeadersText = Encoding.ASCII.GetString(memoryStream.ToArray()); } switch (eml.Priority) { case MessagePriority.NonUrgent: msg.Priority = Enums.MessagePriority.PRIO_NONURGENT; break; case MessagePriority.Normal: msg.Priority = Enums.MessagePriority.PRIO_NORMAL; break; case MessagePriority.Urgent: msg.Priority = Enums.MessagePriority.PRIO_URGENT; break; } switch (eml.Importance) { case MessageImportance.Low: msg.Importance = Enums.MessageImportance.IMPORTANCE_LOW; break; case MessageImportance.Normal: msg.Importance = Enums.MessageImportance.IMPORTANCE_NORMAL; break; case MessageImportance.High: msg.Importance = Enums.MessageImportance.IMPORTANCE_HIGH; break; } foreach (var to in eml.To) { var mailAddress = (MailboxAddress)to; msg.Recipients.AddTo(mailAddress.Address, mailAddress.Name); } foreach (var cc in eml.Cc) { var mailAddress = (MailboxAddress)cc; msg.Recipients.AddCc(mailAddress.Address, mailAddress.Name); } foreach (var bcc in eml.Bcc) { var mailAddress = (MailboxAddress)bcc; msg.Recipients.AddBcc(mailAddress.Address, mailAddress.Name); } using (var headerStream = new MemoryStream()) { eml.Headers.WriteTo(headerStream); headerStream.Position = 0; msg.TransportMessageHeadersText = Encoding.ASCII.GetString(headerStream.ToArray()); } msg.BodyHtml = eml.HtmlBody; msg.BodyText = eml.TextBody; var skipFirst = true; foreach (var bodyPart in eml.BodyParts) { // We always skip the first bodypart because that is normaly the html, text or rtf body if (skipFirst) { skipFirst = false; continue; } var attachmentStream = new MemoryStream(); var fileName = bodyPart.ContentType.Name; var extension = string.Empty; if (bodyPart is MessagePart messagePart) { messagePart.Message.WriteTo(attachmentStream); if (messagePart.Message != null) { fileName = messagePart.Message.Subject; } extension = ".eml"; } else if (bodyPart is MessageDispositionNotification) { var part = (MessageDispositionNotification)bodyPart; fileName = part.FileName; } else if (bodyPart is MessageDeliveryStatus) { var part = (MessageDeliveryStatus)bodyPart; fileName = "details"; extension = ".txt"; part.WriteTo(FormatOptions.Default, attachmentStream, true); } else { var part = (MimePart)bodyPart; part.Content.DecodeTo(attachmentStream); fileName = part.FileName; bodyPart.WriteTo(attachmentStream); } fileName = string.IsNullOrWhiteSpace(fileName) ? "Nameless" : FileManager.RemoveInvalidFileNameChars(fileName); if (!string.IsNullOrEmpty(extension)) { fileName += extension; } var inline = bodyPart.ContentDisposition != null && bodyPart.ContentDisposition.Disposition.Equals("inline", StringComparison.InvariantCultureIgnoreCase); attachmentStream.Position = 0; msg.Attachments.Add(attachmentStream, fileName, -1, inline, bodyPart.ContentId); } msg.Save(msgFileName); }
/// <summary> /// Converts an EML file to MSG format /// </summary> /// <param name="emlFileName">The EML (MIME) file</param> private static Email ConvertEmlToMsgLib(string emlFileName) { var eml = MimeMessage.Load(emlFileName); var sender = new Sender(string.Empty, string.Empty); var FromAddress = ((MailboxAddress)eml.From[0]); if (eml.From.Count > 0) { sender = new Sender(FromAddress.Address, FromAddress.Name); } var representing = new Representing(FromAddress.Address, FromAddress.Name); //Default to from address if (eml.ResentSender != null) { representing = new Representing(eml.ResentSender.Address, eml.ResentSender.Name); } var msg = new Email(sender, representing, eml.Subject) { SentOn = eml.Date.UtcDateTime, InternetMessageId = eml.MessageId }; switch (eml.Priority) { case MessagePriority.NonUrgent: msg.Priority = Enums.MessagePriority.PRIO_NONURGENT; break; case MessagePriority.Normal: msg.Priority = Enums.MessagePriority.PRIO_NORMAL; break; case MessagePriority.Urgent: msg.Priority = Enums.MessagePriority.PRIO_URGENT; break; } switch (eml.Importance) { case MessageImportance.Low: msg.Importance = Enums.MessageImportance.IMPORTANCE_LOW; break; case MessageImportance.Normal: msg.Importance = Enums.MessageImportance.IMPORTANCE_NORMAL; break; case MessageImportance.High: msg.Importance = Enums.MessageImportance.IMPORTANCE_HIGH; break; } foreach (var to in eml.To) { var mailAddress = (MailboxAddress)to; msg.Recipients.AddTo(mailAddress.Address, mailAddress.Name); } foreach (var cc in eml.Cc) { var mailAddress = (MailboxAddress)cc; msg.Recipients.AddCc(mailAddress.Address, mailAddress.Name); } foreach (var bcc in eml.Bcc) { var mailAddress = (MailboxAddress)bcc; msg.Recipients.AddBcc(mailAddress.Address, mailAddress.Name); } using (var headerStream = new MemoryStream()) { eml.Headers.WriteTo(headerStream); headerStream.Position = 0; msg.TransportMessageHeaders = Encoding.ASCII.GetString(headerStream.ToArray()); } msg.BodyHtml = eml.HtmlBody; msg.BodyText = eml.TextBody; try { var NamelessCount = 0; foreach (var bodyPart in eml.BodyParts) { var type = bodyPart.GetType(); if (type.Equals(typeof(TextPart))) //Make sure the TextPart isnt TextBody or HtmlBody { var part = (TextPart)bodyPart; if (new[] { eml.TextBody, eml.HtmlBody }.Contains(part.Text)) { continue; //Break conversion } else if (part.ContentDisposition?.Disposition == ContentDisposition.Inline && string.IsNullOrEmpty(bodyPart.ContentId)) //If TextPart is inline but doesnt have content defined { msg.BodyText += Environment.NewLine + part.Text; //Append text to the body of the email msg.BodyHtml += part.Text.Replace(Environment.NewLine, "<br>"); continue; } } //Get the body part and convert as needed var attachmentStream = new MemoryStream(); var fileName = bodyPart.ContentType.Name; var extension = string.Empty; if (type.Equals(typeof(MessagePart))) { var part = (MessagePart)bodyPart; part.Message.WriteTo(attachmentStream); if (part.Message != null) { fileName = part.Message.Subject; } extension = ".eml"; } else if (type.Equals(typeof(MessageDispositionNotification))) { var part = (MessageDispositionNotification)bodyPart; fileName = part.FileName; } else if (type.Equals(typeof(MessageDeliveryStatus))) { var part = (MessageDeliveryStatus)bodyPart; fileName = "details"; extension = ".txt"; part.WriteTo(FormatOptions.Default, attachmentStream, true); } else { var part = (MimePart)bodyPart; part.Content.DecodeTo(attachmentStream); fileName = part.FileName; bodyPart.WriteTo(attachmentStream); } fileName = string.IsNullOrWhiteSpace(fileName) ? "Nameless" + (NamelessCount++ > 0 ? NamelessCount.ToString() : "") : FileManager.RemoveInvalidFileNameChars(fileName); if (!string.IsNullOrEmpty(extension)) { fileName += extension; } var inline = bodyPart.ContentDisposition?.Disposition.Equals( ContentDisposition.Inline, StringComparison.InvariantCultureIgnoreCase) ?? false; if (inline && string.IsNullOrEmpty(bodyPart.ContentId)) { inline = false; } attachmentStream.Position = 0; msg.Attachments.Add(attachmentStream, fileName, -1, inline, bodyPart.ContentId); } } catch { throw; } return(msg); }
/// <summary> /// Converts an EML file to MSG format /// </summary> /// <param name="emlFile">The EML (MIME) input stream</param> /// <param name="msgFile">The MSG file output stream</param> public static void ConvertEmlToMsg(Stream emlFile, Stream msgFile) { var eml = MimeMessage.Load(emlFile); var sender = new Sender(string.Empty, string.Empty); if (eml.From.Count > 0) { var mailAddress = ((MailboxAddress)eml.From[0]); sender = new Sender(mailAddress.Address, mailAddress.Name); } var representing = new Representing(string.Empty, string.Empty); if (eml.ResentSender != null) { representing = new Representing(eml.ResentSender.Address, eml.ResentSender.Name); } var msg = new Email(sender, representing, eml.Subject) { SentOn = eml.Date.UtcDateTime, InternetMessageId = eml.MessageId }; using (var memoryStream = new MemoryStream()) { eml.Headers.WriteTo(memoryStream); msg.TransportMessageHeadersText = Encoding.ASCII.GetString(memoryStream.ToArray()); } switch (eml.Priority) { case MessagePriority.NonUrgent: msg.Priority = Enums.MessagePriority.PRIO_NONURGENT; break; case MessagePriority.Normal: msg.Priority = Enums.MessagePriority.PRIO_NORMAL; break; case MessagePriority.Urgent: msg.Priority = Enums.MessagePriority.PRIO_URGENT; break; } switch (eml.Importance) { case MessageImportance.Low: msg.Importance = Enums.MessageImportance.IMPORTANCE_LOW; break; case MessageImportance.Normal: msg.Importance = Enums.MessageImportance.IMPORTANCE_NORMAL; break; case MessageImportance.High: msg.Importance = Enums.MessageImportance.IMPORTANCE_HIGH; break; } foreach (var to in eml.To) { var mailAddress = (MailboxAddress)to; msg.Recipients.AddTo(mailAddress.Address, mailAddress.Name); } foreach (var cc in eml.Cc) { var mailAddress = (MailboxAddress)cc; msg.Recipients.AddCc(mailAddress.Address, mailAddress.Name); } foreach (var bcc in eml.Bcc) { var mailAddress = (MailboxAddress)bcc; msg.Recipients.AddBcc(mailAddress.Address, mailAddress.Name); } using (var headerStream = new MemoryStream()) { eml.Headers.WriteTo(headerStream); headerStream.Position = 0; msg.TransportMessageHeadersText = Encoding.ASCII.GetString(headerStream.ToArray()); } int namelessCount = 0; // This loops through the top-level parts (i.e. it doesn't open up attachments and continue to traverse). // As such, any included messages are just attachments here. foreach (var bodyPart in eml.BodyParts) { var handled = false; // The first text/plain part (that's not an attachment) is the body part. if (!bodyPart.IsAttachment && bodyPart is TextPart text) { // Sets the first matching inline content type for body parts. if (msg.BodyText == null && text.IsPlain) { msg.BodyText = text.Text; handled = true; } if (msg.BodyHtml == null && text.IsHtml) { msg.BodyHtml = text.Text; handled = true; } if (msg.BodyRtf == null && text.IsRichText) { msg.BodyRtf = text.Text; handled = true; } } // If the part hasn't previously been handled by "body" part handling if (!handled) { var attachmentStream = new MemoryStream(); var fileName = bodyPart.ContentType.Name; var extension = string.Empty; if (bodyPart is MessagePart messagePart) { messagePart.Message.WriteTo(attachmentStream); if (messagePart.Message != null) { fileName = messagePart.Message.Subject; } extension = ".eml"; } else if (bodyPart is MessageDispositionNotification) { var part = (MessageDispositionNotification)bodyPart; fileName = part.FileName; } else if (bodyPart is MessageDeliveryStatus) { var part = (MessageDeliveryStatus)bodyPart; fileName = "details"; extension = ".txt"; part.WriteTo(FormatOptions.Default, attachmentStream, true); } else { var part = (MimePart)bodyPart; part.Content.DecodeTo(attachmentStream); fileName = part.FileName; bodyPart.WriteTo(attachmentStream); } fileName = string.IsNullOrWhiteSpace(fileName) ? $"part_{++namelessCount:00}" : FileManager.RemoveInvalidFileNameChars(fileName); if (!string.IsNullOrEmpty(extension)) { fileName += extension; } var inline = bodyPart.ContentDisposition != null && bodyPart.ContentDisposition.Disposition.Equals("inline", StringComparison.InvariantCultureIgnoreCase); attachmentStream.Position = 0; msg.Attachments.Add(attachmentStream, fileName, -1, inline, bodyPart.ContentId); } } msg.Save(msgFile); }
/// <summary> /// Writes all the properties that are part of the <see cref="Email"/> object either as <see cref="CFStorage"/>'s /// or <see cref="CFStream"/>'s to the <see cref="CompoundFile.RootStorage"/> /// </summary> internal new void WriteToStorage() { base.WriteToStorage(); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_SUPPORT_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); var rootStorage = CompoundFile.RootStorage; Class = MessageClass.IPM_Note; MessageSize += Recipients.WriteToStorage(rootStorage); var recipientCount = Recipients.Count; TopLevelProperties.RecipientCount = recipientCount; TopLevelProperties.NextRecipientId = recipientCount; //TopLevelProperties.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId()); //TopLevelProperties.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey()); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_UNICODE_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_ALTERNATE_RECIPIENT_ALLOWED, true, PropertyFlags.PROPATTR_READABLE); if (!string.IsNullOrWhiteSpace(InternetMessageId)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_INTERNET_MESSAGE_ID_W, InternetMessageId); } if (!string.IsNullOrWhiteSpace(InternetReferences)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_INTERNET_REFERENCES_W, InternetReferences); } if (!string.IsNullOrWhiteSpace(InReplyToId)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_IN_REPLY_TO_ID_W, InReplyToId); } _messageFlags = MessageFlags.MSGFLAG_UNMODIFIED; TopLevelProperties.AddProperty(PropertyTags.PR_INTERNET_CPID, Encoding.UTF8.CodePage); if (MessageEditorFormat != MessageEditorFormat.EDITOR_FORMAT_DONTKNOW) { TopLevelProperties.AddProperty(PropertyTags.PR_MSG_EDITOR_FORMAT, MessageEditorFormat); } if (ReceivedOn.HasValue) { TopLevelProperties.AddProperty(PropertyTags.PR_MESSAGE_DELIVERY_TIME, ReceivedOn.Value.ToUniversalTime()); TopLevelProperties.AddProperty(PropertyTags.PR_DELIVER_TIME, ReceivedOn.Value.ToUniversalTime()); TopLevelProperties.AddProperty(PropertyTags.PR_LATEST_DELIVERY_TIME, ReceivedOn.Value.ToUniversalTime()); TopLevelProperties.AddProperty(PropertyTags.PR_RECEIPT_TIME, ReceivedOn.Value.ToUniversalTime()); } TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS, MapiAccess.MAPI_ACCESS_DELETE | MapiAccess.MAPI_ACCESS_MODIFY | MapiAccess.MAPI_ACCESS_READ); TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS_LEVEL, MapiAccess.MAPI_ACCESS_MODIFY); TopLevelProperties.AddProperty(PropertyTags.PR_OBJECT_TYPE, MapiObjectType.MAPI_MESSAGE); // http://www.meridiandiscovery.com/how-to/e-mail-conversation-index-metadata-computer-forensics/ // http://stackoverflow.com/questions/11860540/does-outlook-embed-a-messageid-or-equivalent-in-its-email-elements //propertiesStream.AddProperty(PropertyTags.PR_CONVERSATION_INDEX, Subject); // TODO: Change modification time when this message is opened and only modified var utcNow = DateTime.UtcNow; if (Draft) { _messageFlags |= MessageFlags.MSGFLAG_UNSENT; IconIndex = MessageIconIndex.UnsentMail; } TopLevelProperties.AddProperty(PropertyTags.PR_MESSAGE_FLAGS, _messageFlags); Sender?.WriteProperties(TopLevelProperties); Receiving?.WriteProperties(TopLevelProperties); Representing?.WriteProperties(TopLevelProperties); ReceivingRepresenting?.WriteProperties(TopLevelProperties); if (recipientCount > 0) { var displayTo = new List <string>(); var displayCc = new List <string>(); var displayBcc = new List <string>(); foreach (var recipient in Recipients) { switch (recipient.RecipientType) { case RecipientType.To: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayTo.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayTo.Add(recipient.Email); } break; case RecipientType.Cc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayCc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayCc.Add(recipient.Email); } break; case RecipientType.Bcc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayBcc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayBcc.Add(recipient.Email); } break; default: throw new ArgumentOutOfRangeException(); } } TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_TO_W, string.Join(";", displayTo), PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_CC_W, string.Join(";", displayCc), PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_DISPLAY_BCC_W, string.Join(";", displayBcc), PropertyFlags.PROPATTR_READABLE); AddExtendedProperties(); } }
/// <summary> /// Writes all the properties that are part of the <see cref="Email"/> object either as <see cref="CFStorage"/>'s /// or <see cref="CFStream"/>'s to the <see cref="CompoundFile.RootStorage"/> /// </summary> internal new void WriteToStorage() { var rootStorage = CompoundFile.RootStorage; Class = MessageClass.IPM_Post; base.WriteToStorage(); var attachmentCount = Attachments.Count; TopLevelProperties.AttachmentCount = attachmentCount; TopLevelProperties.NextAttachmentId = attachmentCount; //TopLevelProperties.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId()); //TopLevelProperties.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey()); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_SUPPORT_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_STORE_UNICODE_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_ALTERNATE_RECIPIENT_ALLOWED, true, PropertyFlags.PROPATTR_READABLE); TopLevelProperties.AddProperty(PropertyTags.PR_HASATTACH, attachmentCount > 0); TopLevelProperties.AddProperty(PropertyTags.PR_PARENT_DISPLAY_W, PostedTo); if (!string.IsNullOrWhiteSpace(InternetMessageId)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_INTERNET_MESSAGE_ID_W, InternetMessageId); } if (!string.IsNullOrWhiteSpace(InternetReferences)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_INTERNET_REFERENCES_W, InternetReferences); } if (!string.IsNullOrWhiteSpace(InReplyToId)) { TopLevelProperties.AddOrReplaceProperty(PropertyTags.PR_IN_REPLY_TO_ID_W, InReplyToId); } var messageFlags = MessageFlags.MSGFLAG_UNMODIFIED; if (attachmentCount > 0) { messageFlags |= MessageFlags.MSGFLAG_HASATTACH; } TopLevelProperties.AddProperty(PropertyTags.PR_INTERNET_CPID, Encoding.UTF8.CodePage); if (MessageEditorFormat != MessageEditorFormat.EDITOR_FORMAT_DONTKNOW) { TopLevelProperties.AddProperty(PropertyTags.PR_MSG_EDITOR_FORMAT, MessageEditorFormat); } if (!SentOn.HasValue) { SentOn = DateTime.UtcNow; } TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS, MapiAccess.MAPI_ACCESS_DELETE | MapiAccess.MAPI_ACCESS_MODIFY | MapiAccess.MAPI_ACCESS_READ); TopLevelProperties.AddProperty(PropertyTags.PR_ACCESS_LEVEL, MapiAccess.MAPI_ACCESS_MODIFY); TopLevelProperties.AddProperty(PropertyTags.PR_OBJECT_TYPE, MapiObjectType.MAPI_MESSAGE); // http://www.meridiandiscovery.com/how-to/e-mail-conversation-index-metadata-computer-forensics/ // http://stackoverflow.com/questions/11860540/does-outlook-embed-a-messageid-or-equivalent-in-its-email-elements //propertiesStream.AddProperty(PropertyTags.PR_CONVERSATION_INDEX, Subject); // TODO: Change modification time when this message is opened and only modified TopLevelProperties.AddProperty(PropertyTags.PR_PRIORITY, Priority); if (Draft) { messageFlags |= MessageFlags.MSGFLAG_UNSENT; } IconIndex = MessageIconIndex.Post; TopLevelProperties.AddProperty(PropertyTags.PR_MESSAGE_FLAGS, messageFlags); Sender?.WriteProperties(TopLevelProperties); Representing?.WriteProperties(TopLevelProperties); }
/// <summary> /// Writes all the properties that are part of the <see cref="Appointment"/> object either as <see cref="CFStorage"/>'s /// or <see cref="CFStream"/>'s to the <see cref="CompoundFile.RootStorage"/> /// </summary> private void WriteToStorage() { var rootStorage = CompoundFile.RootStorage; long messageSize = 0; messageSize += Recipients.WriteToStorage(rootStorage); messageSize += Attachments.WriteToStorage(rootStorage); var recipientCount = Recipients.Count; var attachmentCount = Attachments.Count; var propertiesStream = new TopLevelProperties(recipientCount, attachmentCount, recipientCount, attachmentCount); if (!string.IsNullOrEmpty(InternetMessageId)) { propertiesStream.AddProperty(PropertyTags.PR_INTERNET_MESSAGE_ID_W, InternetMessageId); } propertiesStream.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId()); propertiesStream.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey()); propertiesStream.AddProperty(PropertyTags.PR_STORE_SUPPORT_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); propertiesStream.AddProperty(PropertyTags.PR_STORE_UNICODE_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE); propertiesStream.AddProperty(PropertyTags.PR_ALTERNATE_RECIPIENT_ALLOWED, true, PropertyFlags.PROPATTR_READABLE); propertiesStream.AddProperty(PropertyTags.PR_HASATTACH, attachmentCount > 0); var messageFlags = MessageFlags.MSGFLAG_UNMODIFIED; if (Draft) { messageFlags |= MessageFlags.MSGFLAG_UNSENT | MessageFlags.MSGFLAG_FROMME; IconIndex = MessageIconIndex.UnsentMail; } if (attachmentCount > 0) { messageFlags |= MessageFlags.MSGFLAG_HASATTACH; } if (!SentOn.HasValue) { SentOn = DateTime.UtcNow; } propertiesStream.AddProperty(PropertyTags.PR_CLIENT_SUBMIT_TIME, SentOn); propertiesStream.AddProperty(PropertyTags.PR_MESSAGE_FLAGS, messageFlags); propertiesStream.AddProperty(PropertyTags.PR_ACCESS, MapiAccess.MAPI_ACCESS_DELETE | MapiAccess.MAPI_ACCESS_MODIFY | MapiAccess.MAPI_ACCESS_READ); propertiesStream.AddProperty(PropertyTags.PR_ACCESS_LEVEL, MapiAccess.MAPI_ACCESS_MODIFY); propertiesStream.AddProperty(PropertyTags.PR_OBJECT_TYPE, MapiObjectType.MAPI_MESSAGE); SetSubject(); propertiesStream.AddProperty(PropertyTags.PR_SUBJECT_W, Subject); propertiesStream.AddProperty(PropertyTags.PR_NORMALIZED_SUBJECT_W, SubjectNormalized); propertiesStream.AddProperty(PropertyTags.PR_SUBJECT_PREFIX_W, SubjectPrefix); propertiesStream.AddProperty(PropertyTags.PR_CONVERSATION_TOPIC_W, SubjectNormalized); // http://www.meridiandiscovery.com/how-to/e-mail-conversation-index-metadata-computer-forensics/ // http://stackoverflow.com/questions/11860540/does-outlook-embed-a-messageid-or-equivalent-in-its-email-elements //propertiesStream.AddProperty(PropertyTags.PR_CONVERSATION_INDEX, Subject); // TODO: Change modification time when this message is opened and only modified var utcNow = DateTime.UtcNow; propertiesStream.AddProperty(PropertyTags.PR_CREATION_TIME, utcNow); propertiesStream.AddProperty(PropertyTags.PR_LAST_MODIFICATION_TIME, utcNow); propertiesStream.AddProperty(PropertyTags.PR_MESSAGE_CLASS_W, "IPM.Appointment"); propertiesStream.AddProperty(PropertyTags.PR_PRIORITY, Priority); propertiesStream.AddProperty(PropertyTags.PR_IMPORTANCE, Importance); propertiesStream.AddProperty(PropertyTags.PR_MESSAGE_LOCALE_ID, CultureInfo.CurrentCulture.LCID); propertiesStream.AddProperty(PropertyTags.PR_ICON_INDEX, IconIndex); if (Sender != null) { Sender.WriteProperties(propertiesStream); } if (Receiving != null) { Receiving.WriteProperties(propertiesStream); } if (Representing != null) { Representing.WriteProperties(propertiesStream); } if (ReceivingRepresenting != null) { ReceivingRepresenting.WriteProperties(propertiesStream); } if (recipientCount > 0) { var displayTo = new List <string>(); var displayCc = new List <string>(); var displayBcc = new List <string>(); foreach (var recipient in Recipients) { switch (recipient.RecipientType) { case RecipientType.To: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayTo.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayTo.Add(recipient.Email); } break; case RecipientType.Cc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayCc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayCc.Add(recipient.Email); } break; case RecipientType.Bcc: if (!string.IsNullOrWhiteSpace(recipient.DisplayName)) { displayBcc.Add(recipient.DisplayName); } else if (!string.IsNullOrWhiteSpace(recipient.Email)) { displayBcc.Add(recipient.Email); } break; default: throw new ArgumentOutOfRangeException(); } } propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_TO_W, string.Join(";", displayTo), PropertyFlags.PROPATTR_READABLE); propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_CC_W, string.Join(";", displayCc), PropertyFlags.PROPATTR_READABLE); propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_BCC_W, string.Join(";", displayBcc), PropertyFlags.PROPATTR_READABLE); } propertiesStream.AddProperty(PropertyTags.PR_INTERNET_CPID, Encoding.UTF8.CodePage); if (BodyRtfCompressed) { propertiesStream.AddProperty(PropertyTags.PR_RTF_COMPRESSED, RTFCompressor.Compress(Encoding.ASCII.GetBytes(BodyRtf))); propertiesStream.AddProperty(PropertyTags.PR_RTF_IN_SYNC, true); } var namedProperties = new NamedProperties(propertiesStream); //Uses the top level properties. namedProperties.AddProperty(NamedPropertyTags.PidLidLocation, Location); namedProperties.AddProperty(NamedPropertyTags.PidLidAppointmentStartWhole, MeetingStart); namedProperties.AddProperty(NamedPropertyTags.PidLidAppointmentEndWhole, MeetingEnd); namedProperties.AddProperty(NamedPropertyTags.PidLidMeetingType, MeetingType.mtgRequest); namedProperties.AddProperty(NamedPropertyTags.PidLidAppointmentSubType, AllDay); namedProperties.AddProperty(NamedPropertyTags.PidLidAppointmentStateFlags, AppointmentState.asfMeeting); namedProperties.WriteProperties(rootStorage); propertiesStream.WriteProperties(rootStorage, messageSize); }