Пример #1
0
        /// <summary>
        ///     Writes all <see cref="Property">properties</see> either as a <see cref="CFStream"/> or as a collection in
        ///     a <see cref="PropertyTags.PropertiesStreamName"/> stream to the given <paramref name="storage"/>, this depends
        ///     on the <see cref="PropertyType"/>
        /// </summary>
        /// <remarks>
        ///     See the <see cref="Properties"/> class it's <see cref="Properties.WriteProperties"/> method for the logic
        ///     that is used to determine this
        /// </remarks>
        /// <param name="storage">The <see cref="CFStorage"/></param>
        /// <returns>
        ///     Total size of the written <see cref="Recipient"/> object and it's <see cref="Properties"/>
        /// </returns>
        internal long WriteProperties(CFStorage storage)
        {
            var propertiesStream = new RecipientProperties();

            propertiesStream.AddProperty(PropertyTags.PR_ROWID, RowId);
            propertiesStream.AddProperty(PropertyTags.PR_ENTRYID, Mapi.GenerateEntryId());
            propertiesStream.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey());
            propertiesStream.AddProperty(PropertyTags.PR_RECIPIENT_TYPE, RecipientType);
            propertiesStream.AddProperty(PropertyTags.PR_ADDRTYPE_W, AddressTypeString);
            propertiesStream.AddProperty(PropertyTags.PR_EMAIL_ADDRESS_W, Email);
            propertiesStream.AddProperty(PropertyTags.PR_OBJECT_TYPE, ObjectType);
            propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_TYPE, DisplayType);
            propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_NAME_W, DisplayName);
            propertiesStream.AddProperty(PropertyTags.PR_SEARCH_KEY, Mapi.GenerateSearchKey(AddressTypeString, Email));
            return(propertiesStream.WriteProperties(storage));
        }
Пример #2
0
        /// <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);
            }
        }
Пример #3
0
        /// <summary>
        ///     Writes all the string and binary <see cref="Property">properties</see> as a <see cref="CFStream" /> to the
        ///     given <paramref name="storage" />
        /// </summary>
        /// <param name="storage">The <see cref="CFStorage" /></param>
        /// <param name="index">The <see cref="Attachment"/> index</param>
        /// <returns>
        ///     Total size of the written <see cref="Attachment"/> object and it's <see cref="Properties"/>
        /// </returns>
        internal long WriteProperties(CFStorage storage, int index)
        {
            var propertiesStream = new AttachmentProperties();

            propertiesStream.AddProperty(PropertyTags.PR_ATTACH_NUM, index, PropertyFlags.PROPATTR_READABLE);
            propertiesStream.AddProperty(PropertyTags.PR_INSTANCE_KEY, Mapi.GenerateInstanceKey(), PropertyFlags.PROPATTR_READABLE);
            propertiesStream.AddProperty(PropertyTags.PR_RECORD_KEY, Mapi.GenerateRecordKey(), PropertyFlags.PROPATTR_READABLE);
            propertiesStream.AddProperty(PropertyTags.PR_RENDERING_POSITION, RenderingPosition, PropertyFlags.PROPATTR_READABLE);
            propertiesStream.AddProperty(PropertyTags.PR_OBJECT_TYPE, MapiObjectType.MAPI_ATTACH);

            if (!string.IsNullOrEmpty(FileName))
            {
                propertiesStream.AddProperty(PropertyTags.PR_DISPLAY_NAME_W, FileName);
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_FILENAME_W, GetShortFileName(FileName));
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_LONG_FILENAME_W, FileName);
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_EXTENSION_W, Path.GetExtension(FileName));

                if (!string.IsNullOrEmpty(ContentId))
                {
                    propertiesStream.AddProperty(PropertyTags.PR_ATTACH_CONTENT_ID_W, ContentId);
                }

                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_MIME_TAG_W, MimeTypes.GetMimeType(FileName));
            }

            propertiesStream.AddProperty(PropertyTags.PR_ATTACH_METHOD, Type);

            switch (Type)
            {
            case AttachmentType.ATTACH_BY_VALUE:
            case AttachmentType.ATTACH_EMBEDDED_MSG:
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_DATA_BIN, Stream.ToByteArray());
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_SIZE, Stream.Length);
                break;

            case AttachmentType.ATTACH_BY_REF_ONLY:
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_DATA_BIN, new byte[0]);
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_SIZE, _file.Length);
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_LONG_PATHNAME_W, _file.FullName);
                break;

            //case AttachmentType.ATTACH_EMBEDDED_MSG:
            //    var msgStorage = storage.AddStorage(PropertyTags.PR_ATTACH_DATA_BIN.Name);
            //    var cf = new CompoundFile(Stream);
            //    Storage.Copy(cf.RootStorage, msgStorage);
            //    propertiesStream.AddProperty(PropertyTags.PR_ATTACH_SIZE, Stream.Length);
            //    propertiesStream.AddProperty(PropertyTags.PR_ATTACH_ENCODING, 0);
            //    break;

            case AttachmentType.ATTACH_BY_REFERENCE:
            case AttachmentType.ATTACH_BY_REF_RESOLVE:
            case AttachmentType.NO_ATTACHMENT:
            case AttachmentType.ATTACH_OLE:
                throw new NotSupportedException("AttachByReference, AttachByRefResolve, NoAttachment and AttachOle are not supported");
            }

            if (IsInline)
            {
                propertiesStream.AddProperty(PropertyTags.PR_ATTACHMENT_HIDDEN, true);
                propertiesStream.AddProperty(PropertyTags.PR_ATTACH_FLAGS, AttachmentFlags.ATT_MHTML_REF);
            }

            var utcNow = DateTime.UtcNow;

            propertiesStream.AddProperty(PropertyTags.PR_CREATION_TIME, utcNow);
            propertiesStream.AddProperty(PropertyTags.PR_LAST_MODIFICATION_TIME, utcNow);
            propertiesStream.AddProperty(PropertyTags.PR_STORE_SUPPORT_MASK, StoreSupportMaskConst.StoreSupportMask, PropertyFlags.PROPATTR_READABLE);

            return(propertiesStream.WriteProperties(storage));
        }
Пример #4
0
        /// <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);
        }