You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
22 KiB

//
// Reader.cs
//
// Author: Kees van Spelde <sicos2002@hotmail.com>
//
// 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
{
/// <summary>
/// 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
/// </summary>
internal class Reader
{
#region SetExtendedFileAttributesWithMsgProperties
/// <summary>
/// This function will read all the properties of an <see cref="Storage.Message"/> file and maps
/// all the properties that are filled to the extended file attributes.
/// </summary>
/// <param name="inputFile">The msg file</param>
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
/// <summary>
/// Maps all the filled <see cref="Storage.Message"/> properties to the corresponding extended file attributes
/// </summary>
/// <param name="message">The <see cref="Storage.Message"/> object</param>
/// <param name="propertyWriter">The <see cref="ShellPropertyWriter"/> object</param>
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
/// <summary>
/// Maps all the filled <see cref="Storage.Appointment"/> properties to the corresponding extended file attributes
/// </summary>
/// <param name="message">The <see cref="Storage.Message"/> object</param>
/// <param name="propertyWriter">The <see cref="ShellPropertyWriter"/> object</param>
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
/// <summary>
/// Maps all the filled <see cref="Storage.Task"/> properties to the corresponding extended file attributes
/// </summary>
/// <param name="message">The <see cref="Storage.Message"/> object</param>
/// <param name="propertyWriter">The <see cref="ShellPropertyWriter"/> object</param>
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
/// <summary>
/// Maps all the filled <see cref="Storage.Task"/> properties to the corresponding extended file attributes
/// </summary>
/// <param name="message">The <see cref="Storage.Message"/> object</param>
/// <param name="propertyWriter">The <see cref="ShellPropertyWriter"/> object</param>
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
}
}