/// <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)
        {
            // OK: 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. So we're going to have to have some sort of a cache.
            var resolution = this.meetingRecipientsCache[invitee.Address];
            var crmItemId  = meeting.UserProperties[CrmIdPropertyName]?.Value;

            if (resolution != null && crmItemId != null)
            {
                RestAPIWrapper.AcceptDeclineMeeting(crmItemId, resolution.moduleName, resolution.moduleId, acceptance);
            }
        }
        /// <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");
            }
        }