private bool TryAddRecipientInModule(string moduleName, string meetingId, Outlook.Recipient recipient)
        {
            bool   result;
            string id = SetCrmRelationshipFromOutlook(meetingId, recipient, moduleName);

            if (!string.IsNullOrWhiteSpace(id))
            {
                string smtpAddress = recipient.GetSmtpAddress();

                this.meetingRecipientsCache[recipient.GetSmtpAddress()] =
                    new AddressResolutionData(moduleName, id, smtpAddress);

                string accountId = RestAPIWrapper.GetRelationship(ContactSyncing.CrmModule, id, "accounts");

                if (!string.IsNullOrWhiteSpace(accountId) &&
                    SetCrmRelationshipFromOutlook(meetingId, "Accounts", accountId))
                {
                    this.meetingRecipientsCache[smtpAddress] = new AddressResolutionData("Accounts", accountId, smtpAddress);
                }

                result = true;
            }
            else
            {
                result = false;
            }

            return(result);
        }
        /// <summary>
        /// Sets up a CRM relationship to mimic an Outlook relationship
        /// </summary>
        /// <param name="meetingId">The ID of the meeting</param>
        /// <param name="recipient">The outlook recipient representing the person to link with.</param>
        /// <param name="foreignModule">the name of the module we're seeking to link with.</param>
        /// <returns></returns>
        private string SetCrmRelationshipFromOutlook(string meetingId, Outlook.Recipient recipient, string foreignModule)
        {
            string foreignId = GetID(recipient.GetSmtpAddress(), foreignModule);

            return(!string.IsNullOrWhiteSpace(foreignId) &&
                   SetCrmRelationshipFromOutlook(meetingId, foreignModule, foreignId) ?
                   foreignId :
                   string.Empty);
        }
        /// <summary>
        /// Set the meeting acceptance status, in CRM, for this invitee to this meeting from
        /// their acceptance status in Outlook.
        /// </summary>
        /// <param name="meeting">The appointment item representing the meeting</param>
        /// <param name="invitee">The recipient item representing the invitee</param>
        /// <param name="acceptance">The acceptance status of this invitee of this meeting
        /// as a string recognised by CRM.</param>
        private void AddOrUpdateMeetingAcceptanceFromOutlookToCRM(Outlook.AppointmentItem meeting, Outlook.Recipient invitee, string acceptance)
        {
            // We don't know which CRM module the invitee belongs to - could be contacts, users,
            // or indirected via accounts - see AddMeetingRecipientsFromOutlookToCrm. We
            // cannot look this up every time. Therefore we use a cache.
            if (this.meetingRecipientsCache.ContainsKey(invitee.GetSmtpAddress()))
            {
                var resolution = this.meetingRecipientsCache[invitee.GetSmtpAddress()];
                var meetingId  = meeting.UserProperties[CrmIdPropertyName]?.Value;

                if (resolution != null && meetingId != null)
                {
                    RestAPIWrapper.AcceptDeclineMeeting(meetingId.ToString(), resolution.moduleName, resolution.moduleId, acceptance);
                }
            }
            else
            {
                Log.Warn($"Received {acceptance} to meeting {meeting.Subject} from {invitee.GetSmtpAddress()}, but we have no CRM record for that person");
            }
        }