// // Reader.cs // // Author: Kees van Spelde // // Copyright (c) 2013-2018 Magic-Sessions. (www.magic-sessions.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using Microsoft.WindowsAPICodePack.Shell; using Microsoft.WindowsAPICodePack.Shell.PropertySystem; using MsgReader.Outlook; namespace MsgMapper { /// /// This class can be used to read an Outlook msg file and map all the known msg properties to /// the Windows extended file properties. Windows 7 or up is needed for this /// internal class Reader { #region SetExtendedFileAttributesWithMsgProperties /// /// This function will read all the properties of an file and maps /// all the properties that are filled to the extended file attributes. /// /// The msg file public void SetExtendedFileAttributesWithMsgProperties(string inputFile) { MemoryStream memoryStream = null; try { // We need to read the msg file into memory because we otherwise can't set the extended filesystem // properties because the files is locked memoryStream = new MemoryStream(); using (var fileStream = File.OpenRead(inputFile)) fileStream.CopyTo(memoryStream); memoryStream.Position = 0; using (var shellFile = ShellFile.FromFilePath(inputFile)) { using (var propertyWriter = shellFile.Properties.GetPropertyWriter()) { using (var message = new Storage.Message(memoryStream)) { switch (message.Type) { case MessageType.Email: MapEmailPropertiesToExtendedFileAttributes(message, propertyWriter); break; case MessageType.AppointmentRequest: case MessageType.Appointment: case MessageType.AppointmentResponse: MapAppointmentPropertiesToExtendedFileAttributes(message, propertyWriter); break; case MessageType.Task: case MessageType.TaskRequestAccept: MapTaskPropertiesToExtendedFileAttributes(message, propertyWriter); break; case MessageType.Contact: MapContactPropertiesToExtendedFileAttributes(message, propertyWriter); break; case MessageType.Unknown: throw new NotSupportedException("Unsupported message type"); } } } } } finally { if (memoryStream != null) memoryStream.Dispose(); } } #endregion #region MapEmailPropertiesToExtendedFileAttributes /// /// Maps all the filled properties to the corresponding extended file attributes /// /// The object /// The object private void MapEmailPropertiesToExtendedFileAttributes(Storage.Message message, ShellPropertyWriter propertyWriter) { // From propertyWriter.WriteProperty(SystemProperties.System.Message.FromAddress, message.Sender.Email); propertyWriter.WriteProperty(SystemProperties.System.Message.FromName, message.Sender.DisplayName); // Sent on propertyWriter.WriteProperty(SystemProperties.System.Message.DateSent, message.SentOn); // To propertyWriter.WriteProperty(SystemProperties.System.Message.ToAddress, message.GetEmailRecipients(RecipientType.To, false, false)); // CC propertyWriter.WriteProperty(SystemProperties.System.Message.CcAddress, message.GetEmailRecipients(RecipientType.Cc, false, false)); // BCC propertyWriter.WriteProperty(SystemProperties.System.Message.BccAddress, message.GetEmailRecipients(RecipientType.Bcc, false, false)); // Subject propertyWriter.WriteProperty(SystemProperties.System.Subject, message.Subject); // Urgent propertyWriter.WriteProperty(SystemProperties.System.Importance, message.Importance); propertyWriter.WriteProperty(SystemProperties.System.ImportanceText, message.ImportanceText); // Attachments var attachments = message.GetAttachmentNames(); if (string.IsNullOrEmpty(attachments)) { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, false); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, null); } else { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, true); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, attachments); } // Clear properties propertyWriter.WriteProperty(SystemProperties.System.StartDate, null); propertyWriter.WriteProperty(SystemProperties.System.DueDate, null); propertyWriter.WriteProperty(SystemProperties.System.DateCompleted, null); propertyWriter.WriteProperty(SystemProperties.System.IsFlaggedComplete, null); propertyWriter.WriteProperty(SystemProperties.System.FlagStatusText, null); // Follow up if (message.Flag != null) { propertyWriter.WriteProperty(SystemProperties.System.IsFlagged, true); propertyWriter.WriteProperty(SystemProperties.System.FlagStatusText, message.Flag.Request); // Flag status text propertyWriter.WriteProperty(SystemProperties.System.FlagStatusText, message.Task.StatusText); // When complete if (message.Task.Complete != null && (bool)message.Task.Complete) { // Flagged complete propertyWriter.WriteProperty(SystemProperties.System.IsFlaggedComplete, true); // Task completed date if (message.Task.CompleteTime != null) propertyWriter.WriteProperty(SystemProperties.System.DateCompleted, (DateTime)message.Task.CompleteTime); } else { // Flagged not complete propertyWriter.WriteProperty(SystemProperties.System.IsFlaggedComplete, false); propertyWriter.WriteProperty(SystemProperties.System.DateCompleted, null); // Task startdate if (message.Task.StartDate != null) propertyWriter.WriteProperty(SystemProperties.System.StartDate, (DateTime)message.Task.StartDate); // Task duedate if (message.Task.DueDate != null) propertyWriter.WriteProperty(SystemProperties.System.DueDate, (DateTime)message.Task.DueDate); } } // Categories var categories = message.Categories; if (categories != null) propertyWriter.WriteProperty(SystemProperties.System.Category, String.Join("; ", String.Join("; ", categories))); } #endregion #region MapAppointmentPropertiesToExtendedFileAttributes /// /// Maps all the filled properties to the corresponding extended file attributes /// /// The object /// The object private void MapAppointmentPropertiesToExtendedFileAttributes(Storage.Message message, ShellPropertyWriter propertyWriter) { // From propertyWriter.WriteProperty(SystemProperties.System.Message.FromAddress, message.Sender.Email); propertyWriter.WriteProperty(SystemProperties.System.Message.FromName, message.Sender.DisplayName); // Sent on if (message.SentOn != null) propertyWriter.WriteProperty(SystemProperties.System.Message.DateSent, message.SentOn); // Subject propertyWriter.WriteProperty(SystemProperties.System.Subject, message.Subject); // Location propertyWriter.WriteProperty(SystemProperties.System.Calendar.Location, message.Appointment.Location); // Start propertyWriter.WriteProperty(SystemProperties.System.StartDate, message.Appointment.Start); // End propertyWriter.WriteProperty(SystemProperties.System.StartDate, message.Appointment.End); // Recurrence type propertyWriter.WriteProperty(SystemProperties.System.Calendar.IsRecurring, message.Appointment.ReccurrenceType != AppointmentRecurrenceType.None); // Status propertyWriter.WriteProperty(SystemProperties.System.Status, message.Appointment.ClientIntentText); // Appointment organizer (FROM) propertyWriter.WriteProperty(SystemProperties.System.Calendar.OrganizerAddress, message.Sender.Email); propertyWriter.WriteProperty(SystemProperties.System.Calendar.OrganizerName, message.Sender.DisplayName); // Mandatory participants (TO) propertyWriter.WriteProperty(SystemProperties.System.Calendar.RequiredAttendeeNames, message.Appointment.ToAttendees); // Optional participants (CC) propertyWriter.WriteProperty(SystemProperties.System.Calendar.OptionalAttendeeNames, message.Appointment.CcAttendees); // Categories var categories = message.Categories; if (categories != null) propertyWriter.WriteProperty(SystemProperties.System.Category, String.Join("; ", String.Join("; ", categories))); // Urgent propertyWriter.WriteProperty(SystemProperties.System.Importance, message.Importance); propertyWriter.WriteProperty(SystemProperties.System.ImportanceText, message.ImportanceText); // Attachments var attachments = message.GetAttachmentNames(); if (string.IsNullOrEmpty(attachments)) { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, false); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, null); } else { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, true); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, attachments); } } #endregion #region MapTaskPropertiesToExtendedFileAttributes /// /// Maps all the filled properties to the corresponding extended file attributes /// /// The object /// The object private void MapTaskPropertiesToExtendedFileAttributes(Storage.Message message, ShellPropertyWriter propertyWriter) { // From propertyWriter.WriteProperty(SystemProperties.System.Message.FromAddress, message.Sender.Email); propertyWriter.WriteProperty(SystemProperties.System.Message.FromName, message.Sender.DisplayName); // Sent on propertyWriter.WriteProperty(SystemProperties.System.Message.DateSent, message.SentOn); // Subject propertyWriter.WriteProperty(SystemProperties.System.Subject, message.Subject); // Task startdate propertyWriter.WriteProperty(SystemProperties.System.StartDate, message.Task.StartDate); // Task duedate propertyWriter.WriteProperty(SystemProperties.System.DueDate, message.Task.DueDate); // Urgent propertyWriter.WriteProperty(SystemProperties.System.Importance, message.Importance); propertyWriter.WriteProperty(SystemProperties.System.ImportanceText, message.ImportanceText); // Status propertyWriter.WriteProperty(SystemProperties.System.Status, message.Task.StatusText); // Percentage complete propertyWriter.WriteProperty(SystemProperties.System.Task.CompletionStatus, message.Task.PercentageComplete); // Owner propertyWriter.WriteProperty(SystemProperties.System.Task.Owner, message.Task.Owner); // Categories propertyWriter.WriteProperty(SystemProperties.System.Category, message.Categories != null ? String.Join("; ", message.Categories) : null); // Companies propertyWriter.WriteProperty(SystemProperties.System.Company, message.Task.Companies != null ? String.Join("; ", message.Task.Companies) : null); // Billing information propertyWriter.WriteProperty(SystemProperties.System.Task.BillingInformation, message.Task.BillingInformation); // Mileage propertyWriter.WriteProperty(SystemProperties.System.MileageInformation, message.Task.Mileage); // Attachments var attachments = message.GetAttachmentNames(); if (string.IsNullOrEmpty(attachments)) { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, false); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, null); } else { propertyWriter.WriteProperty(SystemProperties.System.Message.HasAttachments, true); propertyWriter.WriteProperty(SystemProperties.System.Message.AttachmentNames, attachments); } } #endregion #region MapContactPropertiesToExtendedFileAttributes /// /// Maps all the filled properties to the corresponding extended file attributes /// /// The object /// The object private void MapContactPropertiesToExtendedFileAttributes(Storage.Message message, ShellPropertyWriter propertyWriter) { // From propertyWriter.WriteProperty(SystemProperties.System.Message.FromAddress, message.Sender.Email); propertyWriter.WriteProperty(SystemProperties.System.Message.FromName, message.Sender.DisplayName); // Sent on propertyWriter.WriteProperty(SystemProperties.System.Message.DateSent, message.SentOn); // Full name propertyWriter.WriteProperty(SystemProperties.System.Contact.FullName, message.Contact.DisplayName); // Last name propertyWriter.WriteProperty(SystemProperties.System.Contact.LastName, message.Contact.SurName); // First name propertyWriter.WriteProperty(SystemProperties.System.Contact.FirstName, message.Contact.GivenName); // Job title propertyWriter.WriteProperty(SystemProperties.System.Contact.JobTitle, message.Contact.Function); // Department propertyWriter.WriteProperty(SystemProperties.System.Contact.Department, message.Contact.Department); // Company propertyWriter.WriteProperty(SystemProperties.System.Company, message.Contact.Company); // Business address propertyWriter.WriteProperty(SystemProperties.System.Contact.BusinessAddress, message.Contact.WorkAddress); // Home address propertyWriter.WriteProperty(SystemProperties.System.Contact.HomeAddress, message.Contact.HomeAddress); // Other address propertyWriter.WriteProperty(SystemProperties.System.Contact.OtherAddress, message.Contact.OtherAddress); // Instant messaging propertyWriter.WriteProperty(SystemProperties.System.Contact.IMAddress, message.Contact.InstantMessagingAddress); // Business telephone number propertyWriter.WriteProperty(SystemProperties.System.Contact.BusinessTelephone, message.Contact.BusinessTelephoneNumber); // Assistant's telephone number propertyWriter.WriteProperty(SystemProperties.System.Contact.AssistantTelephone, message.Contact.AssistantTelephoneNumber); // Company main phone propertyWriter.WriteProperty(SystemProperties.System.Contact.CompanyMainTelephone, message.Contact.CompanyMainTelephoneNumber); // Home telephone number propertyWriter.WriteProperty(SystemProperties.System.Contact.HomeTelephone, message.Contact.HomeTelephoneNumber); // Mobile phone propertyWriter.WriteProperty(SystemProperties.System.Contact.MobileTelephone, message.Contact.CellularTelephoneNumber); // Car phone propertyWriter.WriteProperty(SystemProperties.System.Contact.CarTelephone, message.Contact.CarTelephoneNumber); // Callback propertyWriter.WriteProperty(SystemProperties.System.Contact.CallbackTelephone, message.Contact.CallbackTelephoneNumber); // Primary telephone number propertyWriter.WriteProperty(SystemProperties.System.Contact.PrimaryTelephone, message.Contact.PrimaryTelephoneNumber); // Telex propertyWriter.WriteProperty(SystemProperties.System.Contact.TelexNumber, message.Contact.TelexNumber); // TTY/TDD phone propertyWriter.WriteProperty(SystemProperties.System.Contact.TTYTDDTelephone, message.Contact.TextTelephone); // Business fax propertyWriter.WriteProperty(SystemProperties.System.Contact.BusinessFaxNumber, message.Contact.BusinessFaxNumber); // Home fax propertyWriter.WriteProperty(SystemProperties.System.Contact.HomeFaxNumber, message.Contact.HomeFaxNumber); // E-mail propertyWriter.WriteProperty(SystemProperties.System.Contact.EmailAddress, message.Contact.Email1EmailAddress); propertyWriter.WriteProperty(SystemProperties.System.Contact.EmailName, message.Contact.Email1DisplayName); // E-mail 2 propertyWriter.WriteProperty(SystemProperties.System.Contact.EmailAddress2, message.Contact.Email2EmailAddress); // E-mail 3 propertyWriter.WriteProperty(SystemProperties.System.Contact.EmailAddress3, message.Contact.Email3EmailAddress); // Birthday propertyWriter.WriteProperty(SystemProperties.System.Contact.Birthday, message.Contact.Birthday); // Anniversary propertyWriter.WriteProperty(SystemProperties.System.Contact.Anniversary, message.Contact.WeddingAnniversary); // Spouse/Partner propertyWriter.WriteProperty(SystemProperties.System.Contact.SpouseName, message.Contact.SpouseName); // Profession propertyWriter.WriteProperty(SystemProperties.System.Contact.Profession, message.Contact.Profession); // Assistant propertyWriter.WriteProperty(SystemProperties.System.Contact.AssistantName, message.Contact.AssistantName); // Web page propertyWriter.WriteProperty(SystemProperties.System.Contact.Webpage, message.Contact.Html); // Categories var categories = message.Categories; if (categories != null) propertyWriter.WriteProperty(SystemProperties.System.Category, String.Join("; ", String.Join("; ", categories))); } #endregion } }