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.
709 lines
29 KiB
709 lines
29 KiB
//
|
|
// UnsendableRecipients.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.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using MsgReader.Helpers;
|
|
|
|
namespace MsgReader.Outlook
|
|
{
|
|
#region Enum AddressType
|
|
/// <summary>
|
|
/// The <see cref="RecipientRow.DisplayType" />
|
|
/// </summary>
|
|
public enum AddressType
|
|
{
|
|
/// <summary>
|
|
/// No type is set
|
|
/// </summary>
|
|
NoType = 0x0,
|
|
|
|
/// <summary>
|
|
/// X500DN
|
|
/// </summary>
|
|
X500Dn = 0x1,
|
|
|
|
/// <summary>
|
|
/// Ms mail
|
|
/// </summary>
|
|
MsMail = 0x2,
|
|
|
|
/// <summary>
|
|
/// SMTP
|
|
/// </summary>
|
|
Smtp = 0x3,
|
|
|
|
/// <summary>
|
|
/// Fax
|
|
/// </summary>
|
|
Fax = 0x4,
|
|
|
|
/// <summary>
|
|
/// Professional office system
|
|
/// </summary>
|
|
ProfessionalOfficeSystem = 0x5,
|
|
|
|
/// <summary>
|
|
/// Personal distribution list 1
|
|
/// </summary>
|
|
PersonalDistributionList1 = 0x6,
|
|
|
|
/// <summary>
|
|
/// Personal distribution list 2
|
|
/// </summary>
|
|
PersonalDistributionList2 = 0x7
|
|
}
|
|
#endregion
|
|
|
|
#region Enum DisplayType
|
|
/// <summary>
|
|
/// An enumeration. This field MUST be present when the Type field
|
|
/// of the RecipientFlags field is set to X500DN(0x1) and MUST NOT be present otherwise.This
|
|
/// value specifies the display type of this address.Valid values for this field are specified in the
|
|
/// following table.
|
|
/// </summary>
|
|
public enum DisplayType
|
|
{
|
|
/// <summary>
|
|
/// A messaging user
|
|
/// </summary>
|
|
MessagingUser = 0x00,
|
|
|
|
/// <summary>
|
|
/// A distribution list
|
|
/// </summary>
|
|
DistributionList = 0x01,
|
|
|
|
/// <summary>
|
|
/// A forum, such as a bulletin board service or a public or shared folder
|
|
/// </summary>
|
|
Forum = 0x02,
|
|
|
|
/// <summary>
|
|
/// An automated agent
|
|
/// </summary>
|
|
AutomatedAgent = 0x03,
|
|
|
|
/// <summary>
|
|
/// An Address Book object defined for a large group, such as helpdesk, accounting, coordinator, or
|
|
/// department
|
|
/// </summary>
|
|
AddressBook = 0x04,
|
|
|
|
/// <summary>
|
|
/// A private, personally administered distribution list
|
|
/// </summary>
|
|
PrivateDistributionList = 0x05,
|
|
|
|
/// <summary>
|
|
/// An Address Book object known to be from a foreign or remote messaging system
|
|
/// </summary>
|
|
RemoteAddressBook = 0x06
|
|
}
|
|
#endregion
|
|
|
|
#region Enum AddressBookEntryId
|
|
/// <summary>
|
|
/// An integer representing the type of the object. It MUST be one of the values from the following table.
|
|
/// </summary>
|
|
public enum AddressBookEntryIdType
|
|
{
|
|
/// <summary>
|
|
/// A local mail user
|
|
/// </summary>
|
|
LocalMailUser = 0x00000000,
|
|
|
|
/// <summary>
|
|
/// A distribution list
|
|
/// </summary>
|
|
DistributionList = 0x00000001,
|
|
|
|
/// <summary>
|
|
/// A bulletinboard or public folder
|
|
/// </summary>
|
|
BulletinBoardOrPublicFolder = 0x00000002,
|
|
|
|
/// <summary>
|
|
/// An automated mailbox
|
|
/// </summary>
|
|
AutomatedMailBox = 0x00000003,
|
|
|
|
/// <summary>
|
|
/// An organiztional mailbox
|
|
/// </summary>
|
|
OrganizationalMailBox = 0x00000004,
|
|
|
|
/// <summary>
|
|
/// A private distribtion list
|
|
/// </summary>
|
|
PrivateDistributionList = 0x00000005,
|
|
|
|
/// <summary>
|
|
/// A remote mail user
|
|
/// </summary>
|
|
RemoteMailUser = 0x00000006,
|
|
|
|
/// <summary>
|
|
/// A container
|
|
/// </summary>
|
|
Container = 0x00000100,
|
|
|
|
/// <summary>
|
|
/// A template
|
|
/// </summary>
|
|
Template = 0x00000101,
|
|
|
|
/// <summary>
|
|
/// One off user
|
|
/// </summary>
|
|
OneOffUser = 0x00000102,
|
|
|
|
/// <summary>
|
|
/// Search
|
|
/// </summary>
|
|
Search = 0x00000200
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// The PidLidAppointmentUnsendableRecipients property ([MS-OXPROPS] section 2.35) contains a list of
|
|
/// unsendable attendees. This property is not required but SHOULD be set
|
|
/// </summary>
|
|
public class UnsendableRecipients : List<RecipientRow>
|
|
{
|
|
#region Properties
|
|
/// <summary>
|
|
/// An integer that specifies the number of structures in the RecipientRow field
|
|
/// </summary>
|
|
public uint RowCount { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', a different transport is responsible for delivery to this recipient(1).
|
|
/// </summary>
|
|
public bool DifferentTransportDelivery { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the DisplayName (section 2.8.3.2) field is included
|
|
/// </summary>
|
|
public bool DisplayNameIncluded { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the EmailAddress (section 2.8.3.2) field is included.
|
|
/// </summary>
|
|
public bool EmailAddressIncluded { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', this recipient (1) has a non-standard address type and the AddressType field is included.
|
|
/// </summary>
|
|
public bool AddressTypeIncluded { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the SimpleDisplayName field is included.
|
|
/// </summary>
|
|
public bool SimpleDisplayNameIncluded { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the value of the TransmittableDisplayName field is the same as the value of the DisplayName
|
|
/// field.
|
|
/// </summary>
|
|
public bool TransmittableDisplayNameSameAsDisplayName { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the TransmittableDisplayName (section 2.8.3.2) field is included.
|
|
/// </summary>
|
|
public bool TransmittableDisplayNameIncluded { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// If this flag is b'1', the associated string properties are in Unicode with a 2-
|
|
/// byte terminating null character; if this flag is b'0', string properties are MBCS with a single
|
|
/// terminating null character, in the code page sent to the server in the EcDoConnectEx method,
|
|
/// as specified in [MS-OXCRPC] section 3.1.4.1, or the Connect request type 6, as specified in
|
|
/// [MS-OXCMAPIHTTP] section 2.2.4.1.
|
|
/// </summary>
|
|
public bool StringsInUnicode { get; internal set; }
|
|
#endregion
|
|
|
|
#region Constructor
|
|
internal UnsendableRecipients(byte[] data)
|
|
{
|
|
var binaryReader = new BinaryReader(new MemoryStream(data));
|
|
RowCount = binaryReader.ReadUInt32();
|
|
|
|
// RecipientFlags https://msdn.microsoft.com/en-us/library/ee201786(v=exchg.80).aspx
|
|
var b = new BitArray(binaryReader.ReadBytes(4));
|
|
DifferentTransportDelivery = b[0];
|
|
TransmittableDisplayNameSameAsDisplayName = b[1];
|
|
TransmittableDisplayNameIncluded = b[2];
|
|
DisplayNameIncluded = b[3];
|
|
EmailAddressIncluded = b[4];
|
|
// This enumeration specifies the type of address.
|
|
var bt = new BitArray(3);
|
|
bt.Set(0, b[5]);
|
|
bt.Set(1, b[6]);
|
|
bt.Set(2, b[7]);
|
|
var array = new int[1];
|
|
bt.CopyTo(array, 0);
|
|
var recipientType = (AddressType) array[0];
|
|
AddressTypeIncluded = b[8];
|
|
SimpleDisplayNameIncluded = b[13];
|
|
StringsInUnicode = b[14];
|
|
var supportsRtf = !b[15];
|
|
|
|
while (!binaryReader.Eos())
|
|
Add(new RecipientRow(binaryReader,
|
|
recipientType,
|
|
supportsRtf,
|
|
DisplayNameIncluded,
|
|
EmailAddressIncluded,
|
|
AddressTypeIncluded,
|
|
SimpleDisplayNameIncluded,
|
|
TransmittableDisplayNameSameAsDisplayName,
|
|
TransmittableDisplayNameIncluded, StringsInUnicode));
|
|
}
|
|
#endregion
|
|
|
|
#region GetEmailRecipients
|
|
/// <summary>
|
|
/// Returns all the recipient for the given <paramref name="type"/>
|
|
/// </summary>
|
|
/// <param name="type">The <see cref="RecipientType"/> to return</param>
|
|
/// <returns></returns>
|
|
public List<RecipientPlaceHolder> GetEmailRecipients(RecipientType type)
|
|
{
|
|
var recipients = new List<RecipientPlaceHolder>();
|
|
|
|
// ReSharper disable once LoopCanBeConvertedToQuery
|
|
foreach (var recipientRow in this)
|
|
{
|
|
// First we filter for the correct recipient type
|
|
if (recipientRow.RecipientType == type)
|
|
recipients.Add(new RecipientPlaceHolder(recipientRow.EmailAddress, recipientRow.DisplayName, recipientRow.AddresType));
|
|
}
|
|
|
|
return recipients;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// An array of RecipientRow structures, as specified in [MS-OXCDATA] section 2.8.3.
|
|
/// Each structure specifies an unsendable attendee. The RowCount field specifies the
|
|
/// number of structures contained in this field. For details about properties that can
|
|
/// be set on RecipientRow structures for Calendar objects and meeting-related objects,
|
|
/// see section 2.2.4.10.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// See https://msdn.microsoft.com/en-us/library/ee179606(v=exchg.80).aspx
|
|
/// </remarks>
|
|
public class RecipientRow
|
|
{
|
|
#region Properties
|
|
/// <summary>
|
|
/// The <see cref="RecipientType"/> or null when not available
|
|
/// </summary>
|
|
public RecipientType? RecipientType { get; }
|
|
|
|
/// <summary>
|
|
/// The <see cref="AddressType" />
|
|
/// </summary>
|
|
public AddressType AddressType { get; }
|
|
|
|
/// <summary>
|
|
/// The address prefix used
|
|
/// </summary>
|
|
public uint AddressPrefixUsed { get; }
|
|
|
|
/// <summary>
|
|
/// The <see cref="DisplayType" />
|
|
/// </summary>
|
|
public DisplayType DisplayType { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the <see cref="AddressType" /> field of the RecipientFlags
|
|
/// field is set to X500DN (0x1) and MUST NOT be present otherwise. This value specifies the X500 DN of
|
|
/// this recipient (1).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A distinguished name (DN), in Teletex form, of an object that is in an address book. An X500 DN can be more limited
|
|
/// in the size and number of relative distinguished names (RDNs) than a full DN.
|
|
/// </remarks>
|
|
public string X500Dn { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the <see cref="AddressType" /> field of the RecipientFlags field is set to
|
|
/// PersonalDistributionList1 (0x6) or PersonalDistributionList2 (0x7). This field MUST
|
|
/// NOT be present otherwise. This value specifies the size of the EntryID field.
|
|
/// </summary>
|
|
public uint EntryIdSize { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the <see cref="AddressType" /> field of the RecipientFlags field is set to
|
|
/// PersonalDistributionList1 (0x6) or PersonalDistributionList2 (0x7). This field MUST NOT be present otherwise. The
|
|
/// number of bytes in this field MUST be the same as specified in the EntryIdSize field. This array specifies the
|
|
/// address book EntryID structure, as specified in section 2.2.5.2, of the distribution list.
|
|
/// </summary>
|
|
public AddressBookEntryId EntryId { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the <see cref="AddressType" /> field of the RecipientFlags field is set to
|
|
/// PersonalDistributionList1 (0x6) or PersonalDistributionList2 (0x7). This field MUST
|
|
/// NOT be present otherwise. This value specifies the size of the SearchKey field.
|
|
/// </summary>
|
|
public uint SearchKeySize { get; }
|
|
|
|
/// <summary>
|
|
/// This field is used when the <see cref="AddressType" /> field of the RecipientFlags field is set to
|
|
/// PersonalDistributionList1 (0x6) or PersonalDistributionList2 (0x7). This field MUST
|
|
/// NOT be present otherwise. The number of bytes in this field MUST be the same as what
|
|
/// is specified in the SearchKeySize field and can be 0. This array specifies the search
|
|
/// key of the distribution list.
|
|
/// </summary>
|
|
public byte[] SearchKey { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the <see cref="AddressType" /> field of the
|
|
/// RecipientsFlags field is set to NoType (0x0) and the O flag of the RecipientsFlags field
|
|
/// is set. This field MUST NOT be present otherwise. This string specifies the address type
|
|
/// of the recipient (1).
|
|
/// </summary>
|
|
public string AddresType { get; }
|
|
|
|
/// <summary>
|
|
/// A null-terminated string. This field MUST be present when the E flag of the RecipientsFlags
|
|
/// field is set and MUST NOT be present otherwise. This field MUST be specified in Unicode
|
|
/// characters if the U flag of the RecipientsFlags field is set and in the 8-bit character set
|
|
/// otherwise. This string specifies the email address of the recipient (1).
|
|
/// </summary>
|
|
public string EmailAddress { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the D flag of the RecipientsFlags
|
|
/// field is set and MUST NOT be present otherwise. This field MUST be specified in Unicode characters if the U flag of
|
|
/// the RecipientsFlags field is set and in the 8-bit character set otherwise. This string specifies the email address
|
|
/// of the recipient (1).
|
|
/// </summary>
|
|
public string DisplayName { get; }
|
|
|
|
/// <summary>
|
|
/// A null-terminated string. This field MUST be present when the I flag of the RecipientsFlags field is set and MUST
|
|
/// NOT be present otherwise. This field MUST be specified in Unicode characters if the U flag of the RecipientsFlags
|
|
/// field is set and in the 8-bit character set otherwise. This string specifies the email address of the recipient
|
|
/// (1).
|
|
/// </summary>
|
|
public string SimpleDisplayName { get; }
|
|
|
|
/// <summary>
|
|
/// This field MUST be present when the T flag of the RecipientsFlags field is set and MUST NOT be present otherwise.
|
|
/// This field MUST be specified in Unicode characters if the U flag of the RecipientsFlags field is set and in the
|
|
/// 8-bit character set otherwise. This string specifies the email address of the recipient (1).
|
|
/// </summary>
|
|
public string TransmittableDisplayName { get; }
|
|
|
|
/// <summary>
|
|
/// PropertyRow structures, as specified in section 2.8.1. The columns used for this row are those specified in
|
|
/// RecipientProperties.
|
|
/// </summary>
|
|
public List<Property> RecipientProperties { get; }
|
|
|
|
/// <summary>
|
|
/// Specifies that the recipient does support receiving rich text messages.
|
|
/// </summary>
|
|
public bool SupportsRtf { get; }
|
|
#endregion
|
|
|
|
#region Constructor
|
|
/// <summary>
|
|
/// Creates this object and sets all it's properties
|
|
/// </summary>
|
|
/// <param name="binaryReader">The <see cref="BinaryReader" /></param>
|
|
/// <param name="addressType">The <see cref="AddressType" /></param>
|
|
/// <param name="supportsRtf">
|
|
/// Set to <c>true</c> when the recipient in the <see cref="RecipientRow" />
|
|
/// supports RTF
|
|
/// </param>
|
|
/// <param name="displayNameIncluded">If this flag is b'1', the DisplayName (section 2.8.3.2) field is included</param>
|
|
/// <param name="emailAddressIncluded">If this flag is b'1', the EmailAddress (section 2.8.3.2) field is included.</param>
|
|
/// <param name="addressTypeIncluded">
|
|
/// If this flag is b'1', this recipient (1) has a non-standard address type and the
|
|
/// AddressType field is included.
|
|
/// </param>
|
|
/// <param name="simpleDisplayNameIncluded">If this flag is b'1', the SimpleDisplayName field is included.</param>
|
|
/// <param name="transmittableDisplayNameSameAsDisplayName">
|
|
/// If this flag is b'1', the value of the TransmittableDisplayName
|
|
/// field is the same as the value of the DisplayName field.
|
|
/// </param>
|
|
/// <param name="transmittableDisplayNameIncluded">
|
|
/// If this flag is b'1', the TransmittableDisplayName (section 2.8.3.2)
|
|
/// field is included.
|
|
/// </param>
|
|
/// <param name="stringsInUnicode">
|
|
/// If this flag is b'1', the associated string properties are in Unicode with a 2-
|
|
/// byte terminating null character; if this flag is b'0', string properties are MBCS with a single
|
|
/// terminating null character, in the code page sent to the server in the EcDoConnectEx method,
|
|
/// as specified in [MS-OXCRPC] section 3.1.4.1, or the Connect request type 6, as specified in
|
|
/// [MS-OXCMAPIHTTP] section 2.2.4.1.
|
|
/// </param>
|
|
internal RecipientRow(BinaryReader binaryReader,
|
|
AddressType addressType,
|
|
bool supportsRtf,
|
|
bool displayNameIncluded,
|
|
bool emailAddressIncluded,
|
|
bool addressTypeIncluded,
|
|
bool simpleDisplayNameIncluded,
|
|
bool transmittableDisplayNameSameAsDisplayName,
|
|
bool transmittableDisplayNameIncluded,
|
|
bool stringsInUnicode)
|
|
{
|
|
AddressType = addressType;
|
|
SupportsRtf = supportsRtf;
|
|
|
|
switch (AddressType)
|
|
{
|
|
case AddressType.X500Dn:
|
|
AddressPrefixUsed = binaryReader.ReadByte();
|
|
DisplayType = (DisplayType) binaryReader.ReadByte();
|
|
X500Dn = Strings.ReadNullTerminatedAsciiString(binaryReader);
|
|
break;
|
|
|
|
case AddressType.PersonalDistributionList1:
|
|
case AddressType.PersonalDistributionList2:
|
|
EntryIdSize = binaryReader.ReadUInt16();
|
|
EntryId = new AddressBookEntryId(binaryReader);
|
|
SearchKeySize = binaryReader.ReadUInt16();
|
|
if (SearchKeySize > 0)
|
|
SearchKey = binaryReader.ReadBytes((int) SearchKeySize);
|
|
break;
|
|
|
|
case AddressType.NoType:
|
|
if (addressTypeIncluded) AddresType = Strings.ReadNullTerminatedAsciiString(binaryReader);
|
|
break;
|
|
}
|
|
|
|
// MUST be specified in Unicode characters if the U flag of the RecipientsFlags field is set
|
|
if (emailAddressIncluded) EmailAddress = Strings.ReadNullTerminatedString(binaryReader, stringsInUnicode);
|
|
if (displayNameIncluded) DisplayName = Strings.ReadNullTerminatedString(binaryReader, stringsInUnicode);
|
|
if (simpleDisplayNameIncluded)
|
|
SimpleDisplayName = Strings.ReadNullTerminatedString(binaryReader, stringsInUnicode);
|
|
if (transmittableDisplayNameSameAsDisplayName) TransmittableDisplayName = DisplayName;
|
|
else if (transmittableDisplayNameIncluded)
|
|
TransmittableDisplayName = Strings.ReadNullTerminatedString(binaryReader, stringsInUnicode);
|
|
|
|
// This value specifies the number of columns from the RecipientColumns field that are included in
|
|
// the RecipientProperties field.
|
|
var columns = binaryReader.ReadInt16();
|
|
|
|
// Skip the next 6 bytes
|
|
binaryReader.ReadBytes(6);
|
|
|
|
RecipientProperties = new List<Property>();
|
|
for (var column = 0; column < columns; column++)
|
|
{
|
|
var type = (PropertyType) binaryReader.ReadUInt16();
|
|
var id = binaryReader.ReadUInt16();
|
|
byte[] data;
|
|
|
|
switch (type)
|
|
{
|
|
case PropertyType.PT_NULL:
|
|
{
|
|
data = new byte[0];
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_BOOLEAN:
|
|
{
|
|
data = binaryReader.ReadBytes(1);
|
|
binaryReader.ReadByte();
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_SHORT:
|
|
{
|
|
data = binaryReader.ReadBytes(2);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_LONG:
|
|
case PropertyType.PT_FLOAT:
|
|
case PropertyType.PT_ERROR:
|
|
{
|
|
data = binaryReader.ReadBytes(4);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_DOUBLE:
|
|
case PropertyType.PT_APPTIME:
|
|
case PropertyType.PT_I8:
|
|
case PropertyType.PT_SYSTIME:
|
|
{
|
|
data = binaryReader.ReadBytes(8);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_CLSID:
|
|
{
|
|
data = binaryReader.ReadBytes(16);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_OBJECT:
|
|
throw new NotSupportedException("The PT_OBJECT type is not supported");
|
|
|
|
case PropertyType.PT_STRING8:
|
|
case PropertyType.PT_UNICODE:
|
|
case PropertyType.PT_BINARY:
|
|
{
|
|
var length = binaryReader.ReadInt16();
|
|
data = binaryReader.ReadBytes(length);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_MV_SHORT:
|
|
{
|
|
var count = binaryReader.ReadInt16();
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
data = binaryReader.ReadBytes(2);
|
|
RecipientProperties.Add(new Property(id, type, data, true));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_MV_LONG:
|
|
case PropertyType.PT_MV_FLOAT:
|
|
{
|
|
var count = binaryReader.ReadInt16();
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
data = binaryReader.ReadBytes(4);
|
|
RecipientProperties.Add(new Property(id, type, data, true));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_MV_DOUBLE:
|
|
case PropertyType.PT_MV_APPTIME:
|
|
case PropertyType.PT_MV_LONGLONG:
|
|
case PropertyType.PT_MV_SYSTIME:
|
|
{
|
|
var count = binaryReader.ReadInt16();
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
data = binaryReader.ReadBytes(8);
|
|
RecipientProperties.Add(new Property(id, type, data, true));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_MV_TSTRING:
|
|
case PropertyType.PT_MV_STRING8:
|
|
case PropertyType.PT_MV_BINARY:
|
|
{
|
|
var count = binaryReader.ReadInt16();
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
var length = binaryReader.ReadInt16();
|
|
data = binaryReader.ReadBytes(length);
|
|
RecipientProperties.Add(new Property(id, type, data, true));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case PropertyType.PT_MV_CLSID:
|
|
{
|
|
var count = binaryReader.ReadInt16();
|
|
for (var j = 0; j < count; j++)
|
|
{
|
|
data = binaryReader.ReadBytes(16);
|
|
RecipientProperties.Add(new Property(id, type, data));
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(EmailAddress))
|
|
{
|
|
var addressTypeProperty = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_ADDRTYPE);
|
|
var emailAddressProperty = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_EMAIL_ADDRESS);
|
|
var smtpAddressProperty = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_SMTP_ADDRESS);
|
|
|
|
if (addressTypeProperty != null &&
|
|
addressTypeProperty.ToString == "EX" &&
|
|
smtpAddressProperty != null)
|
|
{
|
|
EmailAddress = Helpers.EmailAddress.RemoveSingleQuotes(smtpAddressProperty.ToString);
|
|
}
|
|
else if (emailAddressProperty != null)
|
|
EmailAddress = Helpers.EmailAddress.RemoveSingleQuotes(emailAddressProperty.ToString);
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(DisplayName))
|
|
{
|
|
var value = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_DISPLAY_NAME);
|
|
if (value != null)
|
|
DisplayName = value.ToString;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(SimpleDisplayName))
|
|
{
|
|
var value = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_7BIT_DISPLAY_NAME);
|
|
if (value != null)
|
|
SimpleDisplayName = value.ToString;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(TransmittableDisplayName))
|
|
{
|
|
var value = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_TRANSMITABLE_DISPLAY_NAME);
|
|
if (value != null)
|
|
TransmittableDisplayName = value.ToString;
|
|
}
|
|
|
|
if (transmittableDisplayNameSameAsDisplayName) TransmittableDisplayName = DisplayName;
|
|
|
|
var recipientTypeProperty = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_RECIPIENT_TYPE);
|
|
if (recipientTypeProperty != null)
|
|
RecipientType = (RecipientType) recipientTypeProperty.ToInt;
|
|
|
|
var displayTypeProperty = RecipientProperties.Find(m => m.ShortName == MapiTags.PR_DISPLAY_TYPE);
|
|
if (displayTypeProperty != null)
|
|
DisplayType = (DisplayType) displayTypeProperty.ToInt;
|
|
}
|
|
#endregion
|
|
}
|
|
} |