示例#1
0
        /// <inheritdoc/>
        public override IEnumerable <Clue> BuildClues(ExecutionContext context, IExternalSearchQuery query, IExternalSearchQueryResult result, IExternalSearchRequest request)
        {
            var organizationCode = this.GetOriginEntityCode(result.As <PermIdSocialResponse>());
            var organizationClue = new Clue(organizationCode, context.Organization);

            this.PopulateMetadata(organizationClue.Data.EntityData, result.As <PermIdSocialResponse>());

            yield return(organizationClue);

            if (result.As <PermIdSocialResponse>().Data.AdditionalInfo != null)
            {
                foreach (var person in result.As <PermIdSocialResponse>().Data.AdditionalInfo)
                {
                    var personCode = this.GetPersonEntityCode(person);
                    var personClue = new Clue(personCode, context.Organization);

                    this.PopulatePersonMetadata(personClue.Data.EntityData, person);

                    var personToOrganizationEdge = new EntityEdge(new EntityReference(personCode), new EntityReference(organizationCode), EntityEdgeType.WorksFor);
                    personClue.Data.EntityData.OutgoingEdges.Add(personToOrganizationEdge);

                    yield return(personClue);
                }
            }
        }
示例#2
0
        protected void AddEmailAddressEdge(
            Clue clue,
            EmailAddress address,
            EntityEdgeType edgeType)
        {
            if (address?.Id != null)
            {
                // TODO
                var entityCode = new EntityCode(
                    EntityType.Infrastructure.User,
                    ExchangeSharedMailboxNameConstants.CodeOrigin,
                    address.Id.UniqueId);

                var entityEdge = new EntityEdge(
                    EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                    EntityReference.CreateByKnownCode(entityCode, address.Name),
                    edgeType);

                clue.Data.EntityData.OutgoingEdges.Add(entityEdge);
            }
            else if (address?.Address != null)
            {
                var entityCode = new EntityCode(
                    EntityType.Infrastructure.User,
                    ExchangeSharedMailboxNameConstants.CodeOrigin,
                    address.Address);

                var entityEdge = new EntityEdge(
                    EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                    EntityReference.CreateByKnownCode(entityCode, address.Name),
                    edgeType);

                clue.Data.EntityData.OutgoingEdges.Add(entityEdge);
            }
        }
示例#3
0
        /// <summary>Provides the observer with new data.</summary>
        /// <param name="value">The current notification information.</param>
        public void OnNext(MailThreadModel item)
        {
            var value = item.Message;
            var clue  = this.factory.Create(item);
            var data  = clue.Data.EntityData;

            data.Name = value.ConversationTopic ?? value.Subject;

            data.ModifiedDate = value.ExGetIfAvailable(v => (DateTimeOffset?)v.DateTimeReceived, null) ??
                                value.ExGetIfAvailable(v => (DateTimeOffset?)v.DateTimeSent, null) ??
                                value.ExGetIfAvailable(v => (DateTimeOffset?)v.LastModifiedTime, null);

            if (value.Sender?.Address != null)
            {
                var personReference = new PersonReference(value.Sender.Name, new EntityCode(EntityType.Infrastructure.User, ExchangeSharedMailboxNameConstants.CodeOrigin, value.Sender.Address));
                data.LastChangedBy = personReference;
            }

            var parent = new EntityEdge(
                EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                EntityReference.CreateByKnownCode(new EntityCode(EntityType.Mail.Folder, ExchangeSharedMailboxNameConstants.CodeOrigin, value.ParentFolderId.UniqueId)),
                EntityEdgeType.Parent);

            data.OutgoingEdges.Add(parent);

            this.observer.OnNext(clue);
        }
示例#4
0
        public Clue CreateEntityReference <T>(Clue clue, string type, string edgeType, T value, Func <T, string> selector, Func <T, string> nameSelector)
            where T : class
        {
            if (clue == null)
            {
                throw new ArgumentNullException(nameof(clue));
            }
            if (clue.OriginEntityCode == null)
            {
                throw new ArgumentNullException(nameof(clue));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (edgeType == null)
            {
                throw new ArgumentNullException(nameof(edgeType));
            }
            if (value == null)
            {
                return(clue);
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            string name = null;

            if (nameSelector != null)
            {
                name = nameSelector(value);
            }

            var from = new EntityReference(clue.OriginEntityCode);
            var to   = new EntityReference(new EntityCode(type, "ExchangeSharedMailbox", selector(value)), name);
            var edge = new EntityEdge(@from, to, edgeType);

            clue.Data.EntityData.OutgoingEdges.Add(edge);

            return(clue);
        }
示例#5
0
        public Clue CreateEntityReference <T>(Clue clue, string type, string code, string edgeType, T value, Func <T, string> selector)
        {
            if (clue == null)
            {
                throw new ArgumentNullException(nameof(clue));
            }
            if (clue.OriginEntityCode == null)
            {
                throw new ArgumentNullException(nameof(clue));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (edgeType == null)
            {
                throw new ArgumentNullException(nameof(edgeType));
            }
            if (object.Equals(value, null))
            {
                return(clue);
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            var toValue = selector(value);

            if (string.IsNullOrWhiteSpace(toValue))
            {
                return(clue);
            }

            var from = new EntityReference(clue.OriginEntityCode);
            var to   = new EntityReference(new EntityCode(type, code, toValue));
            var edge = new EntityEdge(from, to, edgeType);

            clue.Data.EntityData.OutgoingEdges.Add(edge);

            return(clue);
        }
示例#6
0
        protected PersonReference AddCreatedBy(
            Clue clue,
            EmailAddress address,
            VocabularyKey vocabularyKey)
        {
            if (address == null)
            {
                return(null);
            }

            PersonReference personReference;

            if (!string.IsNullOrEmpty(address.Address))
            {
                personReference = new PersonReference(address.Name, new EntityCode(EntityType.Infrastructure.User, ExchangeSharedMailboxNameConstants.CodeOrigin, address.Address));
            }
            else
            {
                personReference = new PersonReference(address.Name);
            }

            clue.Data.EntityData.Authors.Add(personReference);
            clue.Data.EntityData.LastChangedBy = personReference;

            this.WriteAddressProperty(clue.Data.EntityData, vocabularyKey, address);

            if (address.Address != null && !clue.Data.EntityData.OutgoingEdges.Any(e => e.EdgeType.Is(EntityEdgeType.CreatedBy)))
            {
                var fromCode = new EntityCode(EntityType.Infrastructure.User, ExchangeSharedMailboxNameConstants.CodeOrigin, address.Address);

                var fromEdge = new EntityEdge(
                    EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                    EntityReference.CreateByKnownCode(fromCode, address.Name),
                    EntityEdgeType.CreatedBy);

                clue.Data.EntityData.OutgoingEdges.Add(fromEdge);
            }

            return(personReference);
        }
示例#7
0
        protected void PopulateMeetingMessage(Clue clue, IMeetingMessageModel <MeetingMessage> message, ExchangeSharedMailboxMeetingMessageVocabulary vocabulary, ExchangeService service)
        {
            var value = message.Object;
            var data  = clue.Data.EntityData;

            this.PopulateEmailMessage(clue, message, vocabulary, service);

            if (value.ExGetIfAvailable(v => v.ICalUid, null) != null)
            {
                data.Codes.Add(new EntityCode(EntityType.Calendar.Event, CodeOrigin.CluedIn.CreateSpecific("uid"), value.ICalUid));
            }

            message.LoadSchemaProperties(this.state);

            data.Properties[vocabulary.AssociatedAppointmentId] = value.ExPrintIfAvailable(v => v.AssociatedAppointmentId);
            data.Properties[vocabulary.IsDelegated]             = value.ExPrintIfAvailable(v => v.IsDelegated);
            data.Properties[vocabulary.IsOutOfDate]             = value.ExPrintIfAvailable(v => v.IsOutOfDate);
            data.Properties[vocabulary.HasBeenProcessed]        = value.ExPrintIfAvailable(v => v.HasBeenProcessed);
            data.Properties[vocabulary.IsOrganizer]             = value.ExPrintIfAvailable(v => v.IsOrganizer);
            data.Properties[vocabulary.ResponseType]            = value.ExPrintIfAvailable(v => v.ResponseType);
            data.Properties[vocabulary.ICalUid]           = value.ExPrintIfAvailable(v => v.ICalUid);
            data.Properties[vocabulary.ICalRecurrenceId]  = value.ExPrintIfAvailable(v => v.ICalRecurrenceId);
            data.Properties[vocabulary.ICalDateTimeStamp] = value.ExPrintIfAvailable(v => v.ICalDateTimeStamp);

            if (value.ExGetIfAvailable(v => v.AssociatedAppointmentId, null) != null)
            {
                var code = new EntityCode(EntityType.Calendar.Event, ExchangeSharedMailboxNameConstants.CodeOrigin, value.AssociatedAppointmentId.UniqueId);

                var fromEdge = new EntityEdge(
                    EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                    EntityReference.CreateByKnownCode(code),
                    EntityEdgeType.Mentioned);

                clue.Data.EntityData.OutgoingEdges.Add(fromEdge);
            }
        }
示例#8
0
        protected void PopulateItem(
            Clue clue,
            IItemObjectModel <Item> item,
            ExchangeSharedMailboxItemVocabulary vocabulary,
            ExchangeService service)
        {
            var value = item.Object;
            var data  = clue.Data.EntityData;

            data.Name        = value.ExPrintIfAvailable(v => v.Subject) ?? data.Name;
            data.CreatedDate = value.ExGetIfAvailable(v => (DateTime?)v.DateTimeCreated, null)
                               ?? value.ExGetIfAvailable(v => (DateTime?)v.DateTimeReceived, null);
            data.ModifiedDate = value.ExGetIfAvailable(v => (DateTime?)v.LastModifiedTime, null)
                                ?? value.ExGetIfAvailable(v => (DateTime?)v.DateTimeSent, null);

            data.Culture = value.ExGetIfAvailable(v => !string.IsNullOrEmpty(v.Culture) ? new CultureInfo(v.Culture) : data.Culture, data.Culture);

            // LastChangedBy
            if ((item.Folder != null && item.Folder.IsFilteredFolder() && item.Object is Contact) == false)
            {
                var lastModifiedName = value.ExGetIfAvailable(v => v.LastModifiedName, null);
                if (!string.IsNullOrEmpty(lastModifiedName))
                {
                    data.LastChangedBy = new PersonReference(new EntityReference(EntityType.Infrastructure.User, lastModifiedName));
                }
            }

            // Properties
            data.Properties[vocabulary.IsAttachment] = value.ExPrintIfTrue(v => v.IsAttachment);
            //data.Properties[vocabulary.IsNew]                           = value.ExPrintIfTrue(v => v.IsNew);
            data.Properties[vocabulary.Sensitivity]      = value.ExPrintIfAvailable(v => v.Sensitivity);
            data.Properties[vocabulary.DateTimeReceived] = value.ExPrintIfAvailable(v => v.DateTimeReceived);
            data.Properties[vocabulary.Size]             = value.ExPrintIfAvailable(v => v.Size);
            data.Properties[vocabulary.Culture]          = value.ExPrintIfAvailable(v => v.Culture);
            data.Properties[vocabulary.Importance]       = value.ExPrintIfAvailable(v => v.Importance);
            data.Properties[vocabulary.InReplyTo]        = value.ExPrintIfAvailable(v => v.InReplyTo);
            data.Properties[vocabulary.IsSubmitted]      = value.ExPrintIfTrue(v => v.IsSubmitted);
            data.Properties[vocabulary.IsAssociated]     = value.ExPrintIfTrue(v => v.IsAssociated);
            data.Properties[vocabulary.IsDraft]          = value.ExPrintIfTrue(v => v.IsDraft);
            //data.Properties[vocabulary.IsFromMe]                        = value.ExPrintIfTrue(v => v.IsFromMe);
            data.Properties[vocabulary.IsResend]                   = value.ExPrintIfTrue(v => v.IsResend);
            data.Properties[vocabulary.IsUnmodified]               = value.ExPrintIfTrue(v => v.IsUnmodified);
            data.Properties[vocabulary.DateTimeSent]               = value.ExPrintIfAvailable(v => v.DateTimeSent);
            data.Properties[vocabulary.DateTimeCreated]            = value.ExPrintIfAvailable(v => v.DateTimeCreated);
            data.Properties[vocabulary.ReminderDueBy]              = value.ExPrintIfAvailable(v => v.ReminderDueBy);
            data.Properties[vocabulary.IsReminderSet]              = value.ExPrintIfTrue(v => v.IsReminderSet);
            data.Properties[vocabulary.ReminderMinutesBeforeStart] = value.ExPrintIfAvailable(v => v.ReminderMinutesBeforeStart);
            data.Properties[vocabulary.DisplayCc]                  = value.ExPrintIfAvailable(v => v.DisplayCc);
            data.Properties[vocabulary.DisplayTo]                  = value.ExPrintIfAvailable(v => v.DisplayTo);
            data.Properties[vocabulary.HasAttachments]             = value.ExPrintIfTrue(v => v.HasAttachments);
            data.Properties[vocabulary.ItemClass]                  = value.ExPrintIfAvailable(v => v.ItemClass);
            data.Properties[vocabulary.Subject] = value.ExPrintIfAvailable(v => v.Subject);
            data.Properties[vocabulary.WebClientReadFormQueryString] = value.ExPrintIfAvailable(v => v.WebClientReadFormQueryString);
            data.Properties[vocabulary.WebClientEditFormQueryString] = value.ExPrintIfAvailable(v => v.WebClientEditFormQueryString);
            //data.Properties[vocabulary.EffectiveRights]                 = value.ExPrintIfAvailable(v => v.EffectiveRights);
            data.Properties[vocabulary.LastModifiedName]       = value.ExPrintIfAvailable(v => v.LastModifiedName);
            data.Properties[vocabulary.LastModifiedTime]       = value.ExPrintIfAvailable(v => v.LastModifiedTime);
            data.Properties[vocabulary.ConversationId]         = value.ExPrintIfAvailable(v => v.ConversationId?.UniqueId);
            data.Properties[vocabulary.RetentionDate]          = value.ExPrintIfAvailable(v => v.RetentionDate);
            data.Properties[vocabulary.Preview]                = value.ExPrintIfAvailable(v => v.Preview);
            data.Properties[vocabulary.IconIndex]              = value.ExPrintIfAvailable(v => v.IconIndex);
            data.Properties[vocabulary.AllowedResponseActions] = value.ExPrintIfAvailable(v => v.AllowedResponseActions);

            if (value.ExGetIfAvailable(v => v.Flag?.FlagStatus, ItemFlagStatus.NotFlagged) != ItemFlagStatus.NotFlagged)
            {
                data.Properties[vocabulary.Flag.CompleteDate] = value.ExPrintIfAvailable(v => v.Flag?.CompleteDate);
                data.Properties[vocabulary.Flag.DueDate]      = value.ExPrintIfAvailable(v => v.Flag?.DueDate);
                data.Properties[vocabulary.Flag.FlagStatus]   = value.ExPrintIfAvailable(v => v.Flag?.FlagStatus);
                data.Properties[vocabulary.Flag.StartDate]    = value.ExPrintIfAvailable(v => v.Flag?.StartDate);
            }

            if (value.ParentFolderId != null && !this.IsFilteredFolder(item.Folder))
            {
                data.Properties[vocabulary.UniqueId]       = value.ExPrintIfAvailable(v => v.Id?.UniqueId);
                data.Properties[vocabulary.ParentFolderId] = value.ExPrintIfAvailable(v => v.ParentFolderId);
            }

            // Ignored:
            // StoreEntryId
            // InstanceKey
            // PolicyTag
            // ArchiveTag
            // MimeContent

            // Categories
            {
                foreach (var category in ((IEnumerable <string>)value.Categories ?? new string[0]).Where(c => c != null))
                {
                    var parsedCategory = this.ParseCategory(category);
                    data.Tags.Add(new Tag(parsedCategory));
                }
            }

            // InternetMessageHeaders
            {
                if (value.Id != null)
                {
                    try
                    {
                        var message = this.BindItem(value, service, new PropertySet(BasePropertySet.IdOnly, ItemSchema.InternetMessageHeaders));

                        if (message.InternetMessageHeaders != null)
                        {
                            foreach (var header in message.InternetMessageHeaders)
                            {
                                data.Properties[ExchangeSharedMailboxVocabulary.MailHeaders.KeyPrefix + ExchangeSharedMailboxVocabulary.MailHeaders.KeySeparator + header.Name] = header.ExPrintIfAvailable(v => v.Value);
                            }
                        }
                    }
                    catch (Exception exc)
                    {
                        this.state.Log.Error(() => "Failed to load item internet headers.", exc);
                    }
                }
            }

            // ExtendedProperties
            {
                foreach (var extendedProperty in (IEnumerable <ExtendedProperty>)value.ExtendedProperties ?? new ExtendedProperty[0])
                {
                    data.Properties[ExchangeSharedMailboxVocabulary.ExtendedProperties.KeyPrefix + ExchangeSharedMailboxVocabulary.ExtendedProperties.KeySeparator + extendedProperty.PropertyDefinition.Name] = extendedProperty.ExPrintIfAvailable(v => v.Value);
                }
            }

            // Body
            {
                if (value.Id != null)
                {
                    try
                    {
                        if (value.ExGetIfAvailable(v => v.Body, null) != null)
                        {
                        }

                        var version = (int)value.Service.RequestedServerVersion;

                        PropertySet itempropertyset = version > (int)ExchangeVersion.Exchange2010
                                                        ? new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.Body, ItemSchema.UniqueBody, ItemSchema.Attachments)
                                                        : new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.Body, ItemSchema.Attachments);

                        itempropertyset.RequestedBodyType = BodyType.Text;

                        if (version > (int)ExchangeVersion.Exchange2010)
                        {
                            itempropertyset.RequestedUniqueBodyType = BodyType.Text;
                        }

                        value.ExLoad(this.state, itempropertyset);

                        // TODO: Save this as HTML
                        if (value.Body != null)
                        {
                            if (value.Body.Text != null)
                            {
                                data.Properties[vocabulary.Body] = value.Body.Text;
                            }

                            data.Encoding = value.Body?.BodyType.ToString() ?? data.Encoding;

                            try
                            {
                                this.IndexContent(value.Body.Text, clue);
                            }
                            catch (Exception exc)
                            {
                                this.state.Log.Error(() => "Failed to index body", exc);
                            }
                        }

                        data.Properties[vocabulary.UniqueBody] = value.ExPrintIfAvailable(v => v.UniqueBody?.Text);

                        // Ignored
                        // data.Properties[vocabulary.NormalizedBody] = value.NormalizedBody?.Text;
                    }
                    catch (Exception exc)
                    {
                        this.state.Log.Error(() => "Failed to index body", exc);
                    }
                }
            }

            // Attachments
            {
                try
                {
                    if (item.Attachments != null)
                    {
                        foreach (var attachment in AttachmentModel.FilterAttachments(item.Attachments, this.state))
                        {
                            var from = new EntityReference(new EntityCode(EntityType.Files.File, "ExchangeSharedMailbox", attachment.Attachment.Id), attachment.Attachment.Name);
                            var to   = new EntityReference(clue.OriginEntityCode);
                            var edge = new EntityEdge(@from, to, EntityEdgeType.PartOf);

                            clue.Data.EntityData.IncomingEdges.Add(edge);
                        }
                    }
                }
                catch (Exception exception)
                {
                    this.state.Log.Warn(() => "Could not index Attachment", exception);
                }
            }

            // EntityExtractionResult
            // TODO

            // Edges
            {
                if (value.ParentFolderId != null && !this.IsFilteredFolder(item.Folder))
                {
                    var parentCode = new EntityCode(EntityType.Infrastructure.Folder, ExchangeSharedMailboxNameConstants.CodeOrigin, value.ParentFolderId.UniqueId);

                    var edge = new EntityEdge(
                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                        EntityReference.CreateByKnownCode(parentCode, item.Folder?.DisplayName),
                        EntityEdgeType.Parent);

                    data.OutgoingEdges.Add(edge);
                }
            }
        }
示例#9
0
        protected override Clue MakeClueImpl(Email input, Guid accountId)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            var clue = _factory.Create(EntityType.Mail, input.engagement.id?.ToString(), accountId);

            clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.EDGES_001_Outgoing_Edge_MustExist);
            clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.EDGES_002_Incoming_Edge_ShouldNotExist);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_001_Name_MustBeSet);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_002_Uri_MustBeSet);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_003_Author_Name_MustBeSet);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_004_Invalid_EntityType);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_005_PreviewImage_RawData_MustBeSet);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_006_Created_Modified_Date_InFuture);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_007_Created_Modified_Date_InPast);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_008_Created_Modified_Date_UnixEpoch);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_009_Created_Modified_Date_MinDate);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.METADATA_010_Created_Modified_Date_MaxDate);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.PROPERTIES_001_MustExist);
            clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.PROPERTIES_002_Unknown_VocabularyKey_Used);
            //clue.ValidationRuleSuppressions.Add(Constants.Validation.Rules.PROPERTIES_003_Value_ShouldNotBeQuoted);

            var data = clue.Data.EntityData;

            if (input.associations != null)
            {
                if (input.associations.companyIds != null)
                {
                    foreach (var companyId in input.associations.companyIds)
                    {
                        _factory.CreateIncomingEntityReference(clue, EntityType.Organization, EntityEdgeType.Parent, input, selector => companyId.ToString());
                    }
                }
                if (input.associations.contactIds != null)
                {
                    foreach (var contactId in input.associations.contactIds)
                    {
                        _factory.CreateIncomingEntityReference(clue, EntityType.Infrastructure.Contact, EntityEdgeType.Parent, input, selector => contactId.ToString());
                    }
                }
                if (input.associations.dealIds != null)
                {
                    foreach (var dealId in input.associations.dealIds)
                    {
                        _factory.CreateIncomingEntityReference(clue, EntityType.Sales.Deal, EntityEdgeType.Parent, input, selector => dealId.ToString());
                    }
                }
                if (input.associations.ownerIds != null)
                {
                    foreach (var ownerId in input.associations.ownerIds)
                    {
                        _factory.CreateIncomingEntityReference(clue, EntityType.Person, EntityEdgeType.OwnedBy, input, selector => ownerId.ToString());
                    }
                }
                if (input.associations.workflowIds != null)
                {
                    foreach (var workflowId in input.associations.workflowIds)
                    {
                        _factory.CreateIncomingEntityReference(clue, EntityType.Process, EntityEdgeType.Parent, input, selector => workflowId.ToString());
                    }
                }
            }

            if (input.engagement != null)
            {
                if (input.engagement.portalId != null && input.engagement.id != null && input.engagement.ownerId != null)
                {
                    var url =
                        $"https://app.hubspot.com/sales/{input.engagement.portalId}/tasks?taskId={input.engagement.id}&ownerId={input.engagement.ownerId}";  // TODO take from configuration
                    data.Uri = new Uri(url);
                }
                if (input.engagement.createdAt != null)
                {
                    if (long.TryParse(input.engagement.createdAt.ToString(), out long date))
                    {
                        data.CreatedDate = DateUtilities.EpochRef.AddMilliseconds(date);
                    }
                }
                if (input.engagement.lastUpdated != null)
                {
                    if (long.TryParse(input.engagement.lastUpdated.ToString(), out long date))
                    {
                        data.CreatedDate = DateUtilities.EpochRef.AddMilliseconds(date);
                    }
                }
                if (input.engagement.timestamp != null)
                {
                    if (data.CreatedDate == null)
                    {
                        if (long.TryParse(input.engagement.createdAt.ToString(), out long date))
                        {
                            data.CreatedDate = DateUtilities.EpochRef.AddMilliseconds(date);
                        }
                    }
                }
                if (input.engagement.active != null)
                {
                    data.Properties[HubSpotVocabulary.Email.Active] = input.engagement.active.ToString();
                }
                if (input.engagement.createdBy != null)
                {
                    _factory.CreateIncomingEntityReference(clue, EntityType.Person, EntityEdgeType.CreatedBy, input, selector => input.engagement.createdBy.ToString());
                }
                if (input.engagement.modifiedBy != null)
                {
                    _factory.CreateIncomingEntityReference(clue, EntityType.Person, EntityEdgeType.ModifiedBy, input, selector => input.engagement.modifiedBy.ToString());
                }
                if (input.engagement.ownerId != null)
                {
                    _factory.CreateIncomingEntityReference(clue, EntityType.Person, EntityEdgeType.OwnedBy, input, selector => input.engagement.ownerId.ToString());
                }
                if (input.engagement.portalId != null)
                {
                    _factory.CreateIncomingEntityReference(clue, EntityType.Infrastructure.Site, EntityEdgeType.Parent, input, selector => input.engagement.portalId.ToString());
                }
            }

            try
            {
                if (input.metadata != null)
                {
                    if (input.metadata.from?.email != null)
                    {
                        if (input.metadata.from.lastName != null)
                        {
                            if (input.metadata.from.firstName != null)
                            {
                                var personReference = new PersonReference(input.metadata.from.firstName + ' ' + input.metadata.from.lastName,
                                                                          new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), input.metadata.from.email));

                                data.Authors.Add(personReference);
                                data.LastChangedBy = personReference;
                            }
                            else
                            {
                                var personReference = new PersonReference(input.metadata.from.lastName,
                                                                          new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), input.metadata.from.email));

                                data.Authors.Add(personReference);
                                data.LastChangedBy = personReference;
                            }
                        }
                        else
                        {
                            var personReference = new PersonReference(new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), input.metadata.from.email));

                            data.Authors.Add(personReference);
                            data.LastChangedBy = personReference;
                        }

                        data.Properties[HubSpotVocabulary.Email.FromEmail]     = input.metadata.from.email;
                        data.Properties[HubSpotVocabulary.Email.FromFirstName] = input.metadata.from.firstName;
                        data.Properties[HubSpotVocabulary.Email.FromLastName]  = input.metadata.from.lastName;
                    }
                    if (input.metadata.to != null)
                    {
                        foreach (EmailPerson recipient in input.metadata.to)
                        {
                            if (recipient != null)
                            {
                                if (recipient.email != null && recipient.firstName != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.firstName + ' ' + recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                if (recipient.email != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                else if (recipient.email != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                            }
                        }
                    }
                    if (input.metadata?.bcc != null)
                    {
                        foreach (EmailPerson recipient in input.metadata.bcc)
                        {
                            if (recipient != null)
                            {
                                if (recipient.email != null && recipient.firstName != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.firstName + ' ' + recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                if (recipient.email != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                else if (recipient.email != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                            }
                        }
                    }
                    if (input.metadata.cc != null)
                    {
                        foreach (EmailPerson recipient in input.metadata.cc)
                        {
                            if (recipient != null)
                            {
                                if (recipient.email != null && recipient.firstName != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.firstName + ' ' + recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                if (recipient.email != null && recipient.lastName != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode, recipient.lastName),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                                else if (recipient.email != null)
                                {
                                    var entityCode = new EntityCode(EntityType.Infrastructure.User, CodeOrigin.CluedIn.CreateSpecific("email"), recipient.email);

                                    var entityEdge = new EntityEdge(
                                        EntityReference.CreateByKnownCode(clue.OriginEntityCode),
                                        EntityReference.CreateByKnownCode(entityCode),
                                        EntityEdgeType.Recipient);

                                    data.OutgoingEdges.Add(entityEdge);
                                }
                            }
                        }
                    }
                    if (input.metadata.subject != null)
                    {
                        data.Name = input.metadata.subject;
                    }
                    if (input.metadata.html != null)
                    {
                        data.Properties[HubSpotVocabulary.Email.HtmlBody] = input.metadata.html;
                    }
                    if (input.metadata.body != null)
                    {
                        data.Properties[HubSpotVocabulary.Email.Body] = input.metadata.body;
                    }
                    if (input.metadata.text != null)
                    {
                        data.Properties[HubSpotVocabulary.Email.Text] = input.metadata.text;
                    }
                    if (input.metadata.sentVia != null)
                    {
                        data.Properties[HubSpotVocabulary.Email.SentVia] = input.metadata.sentVia;
                    }
                    if (input.metadata.custom != null)
                    {
                        foreach (var p in input.metadata.custom)
                        {
                            data.Properties[string.Format("hubspot.company.custom-{0}", p.Key)] = p.Value.ToString();
                        }
                    }
                }
            }

            catch (Exception e)
            {
                _log.Error(() => "Failed to parse value.metadata for Hubspot Email", e);
            }
            if (data.Name == null)
            {
                data.Name = input.engagement.type + " at " + data.CreatedDate.Value.ToString("MM/dd/yyyy hh:mm tt", CultureInfo.InvariantCulture);
            }

            return(clue);
        }