public void CreateUpdateFromReceivedEmail(ReceivedEmailMessage message) { if (message.EmailForCorrespondence != null) { return; } if (message.OriginalMessage?.EmailForCorrespondence != null) { message.EmailForCorrespondence = message.OriginalMessage.EmailForCorrespondence; message.Save(); return; } Func <string, string> formatEntityName = (s) => s.Replace('<', '(').Replace('>', ')'); // create a new Correspondence Stream var corrStream = Entity.Create <CorrespondenceStream>(); corrStream.Name = $"Correspondence initiated from received email from {formatEntityName(message.EmFrom)}"; var corr = Entity.Create <Correspondence>(); corr.Name = $"Email Correspondence to {formatEntityName(message.EmTo)} from {formatEntityName(message.EmFrom)}"; corr.CorrFrom = message.EmFrom; corr.CorrTo = message.EmFrom; corr.CorrContent = ExtractUserResponseFromBody(message.EmBody); corr.CorrespondenceAttachments.AddRange(message.EmAttachments); corr.CorrespondenceSourceEmail = Entity.As <EmailMessage>(message); corrStream.CorrespondenceLog.Add(corr); corrStream.Save(); }
public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction) { postSaveAction = null; string sequenceString; long tenantId; long sequenceId; try { UserTaskHelper.SequenceIdGenerator.SplitSequenceId(message.EmSubject, out sequenceString, out tenantId, out sequenceId); } catch (SequenceIdGenerator.InvalidSequenceId) { return(false); // no sequence, so ignore the message } var task = UserTaskHelper.GetTaskFromEmbededSequenceId(sequenceString); if (task == null) { SendNoTaskReply(message); } else if (task.UserTaskCompletedOn != null) { SendTaskCompletedReply(message); } else { // try to complete the message var completionOptions = task.WorkflowRunForTask.PendingActivity.ForwardTransitions; var completionState = ExtractCompletionOption(completionOptions, message.EmBody); if (completionState == null) { SendInvalidStateReply(message); } else { // update the task after the save var taskId = task.Id; postSaveAction = () => { UserTaskHelper.ProcessApproval(task, completionState, (writableTask) => { writableTask.RelatedMessages.Add(message.Cast <EmailMessage>()); }); }; } } return(false); }
void RunWorkflow(Workflow workflow, string argName, ReceivedEmailMessage message) { var args = new Dictionary <string, object> { { argName, new EntityRef(message) } }; WorkflowRunner.Instance.RunWorkflow(new WorkflowStartEvent(workflow) { Arguments = args }); }
/// <summary> /// Gets the type of the event creation. /// </summary> /// <param name="message">The message.</param> /// <returns> /// An EntityRef describing the type to create. /// </returns> private static EntityRef GetEventCreationType(ReceivedEmailMessage message) { EntityRef type = null; if (message != null && message.FromInbox != null) { Inbox inbox = message.FromInbox; if (inbox.InboxCreatedEventType != null) { type = inbox.InboxCreatedEventType; } } return(type ?? new EntityRef("core:eventEmail")); }
/// <summary> /// Executed before the message is saved /// </summary> /// <param name="message"></param> /// <param name="postSaveAction">if not null an action run after the save. This happens even if the save is cancelled.</param> /// <returns> /// True if the save is to be cancelled /// </returns> public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction) { postSaveAction = null; ///// // Get the references from the received email. ///// string referencesString = message.EmReferences; if (!string.IsNullOrEmpty(referencesString)) { ///// // Parse out each reference as there may be many. ///// List <string> messageIds = EmailHelper.GetMessageIds(referencesString); foreach (string messageId in messageIds) { ///// // Get the local part of the message Id. ///// string messageIdLocalPart = EmailHelper.GetMessageIdLocalPart(messageId); if (!string.IsNullOrEmpty(messageIdLocalPart)) { ///// // Locate any Sent emails that have the same sequence number. ///// var sentEmail = Entity.GetByField <SentEmailMessage>(messageIdLocalPart, true, SentEmailMessage.SemSequenceNumber_Field).FirstOrDefault( ); if (sentEmail != null) { ///// // Link the send email to this received message. ///// message.OriginalMessage = sentEmail; break; } } } } return(false); }
/// <summary> /// Create a ReceivedEmailMessage entity from a mail message /// </summary> /// <param name="msg"></param> /// <param name="inboxReceivedMessageType"></param> /// <returns></returns> ReceivedEmailMessage CreateReceivedEmailMessage(MailMessage msg, Class inboxReceivedMessageType) { ReceivedEmailMessage returnMessage = null; if (inboxReceivedMessageType != null) { var entity = inboxReceivedMessageType.Activate <IEntity>(); if (entity != null) { returnMessage = entity.As <ReceivedEmailMessage>(); } } if (returnMessage == null) { returnMessage = new ReceivedEmailMessage(); } returnMessage.Name = msg.Subject; return(returnMessage); }
public void Test() { string messageIdLocalPart; var sentMessage = new SentEmailMessage { EmTo = "*****@*****.**", EmFrom = "*****@*****.**", EmBody = "body", EmIsHtml = false, EmSubject = "subject" }; sentMessage.Save( ); messageIdLocalPart = sentMessage.SemSequenceNumber; var receivedMessage = new ReceivedEmailMessage { EmTo = "*****@*****.**", EmFrom = "*****@*****.**", EmSubject = "Re: " + sentMessage.EmSubject, EmBody = "body", EmIsHtml = false, EmReferences = EmailHelper.GenerateMessageId(messageIdLocalPart, "localhost") }; var matchAction = new MatchSentToReceivedEmailsAction( ); Action postSaveAction; Assert.IsFalse(matchAction.BeforeSave(receivedMessage, out postSaveAction)); Assert.IsNull(postSaveAction); Assert.IsNotNull(receivedMessage.OriginalMessage, "The original message has been found."); Assert.AreEqual(sentMessage.Id, receivedMessage.OriginalMessage.Id, "The original message has been set correctly."); }
/// <summary> /// Executed before the message is saved /// </summary> /// <param name="message"></param> /// <param name="postSaveAction">if not null an action run after the save. This happens even if the save is cancelled.</param> /// <returns> /// True if the save is to be cancelled /// </returns> public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction) { postSaveAction = null; ///// // Check the message. ///// if (message == null) { return(false); } var iCalMessage = message.As <ReceivedICalEmailMessage>( ); ///// // Ensure the message is a received iCal email message. ///// if (iCalMessage == null) { return(false); } ///// // The iCalUpdate field was set by the iCalMailMesssageFormatter that was called as part // of the ProcessInboxes action. ///// if (string.IsNullOrEmpty(iCalMessage.ICalUpdate)) { return(false); } ///// // Read the iCal update. ///// using (var sr = new StringReader(iCalMessage.ICalUpdate)) { ///// // Deserialize the string into the iCal object model. ///// IICalendarCollection iCalendarCollection = iCalendar.LoadFromStream(sr); if (iCalendarCollection == null) { return(false); } ///// // Get the first calendar. ///// IICalendar calendar = iCalendarCollection.FirstOrDefault( ); if (calendar == null || calendar.Events == null) { return(false); } ///// // Get the first calendar event. ///// IEvent calendarEvent = calendar.Events.FirstOrDefault( ); if (calendarEvent == null) { return(false); } ///// // Make sure the calendar events UID is set. ///// if (string.IsNullOrEmpty(calendarEvent.Uid)) { return(false); } EventEmail eventEntity = null; Appointment appointment = null; ///// // Find all sent iCal UID containers that correlate to the received calendar events UID. ///// IEnumerable <ICalUidContainer> iCalUidContainers = Entity.GetByField <ICalUidContainer>(calendarEvent.Uid, ICalUidContainer.ICalUid_Field); if (iCalUidContainers != null) { ///// // Get the first sent message. ///// ICalUidContainer iCalUidContainer = iCalUidContainers.FirstOrDefault( ); if (iCalUidContainer != null && iCalUidContainer.CalendarEventEmail != null) { ///// // Get the original event email object that was used to create the sent iCal Email Message. ///// eventEntity = iCalUidContainer.CalendarEventEmail.AsWritable <EventEmail>( ); } } bool modificationsMade = false; if (eventEntity == null) { ///// // No existing event email so this is a new request. ///// EntityRef type = GetEventCreationType(message); eventEntity = type != null?Entity.Create(type).As <EventEmail>( ) : new EventEmail( ); appointment = Entity.Create <Appointment>(); eventEntity.EventEmailAppt = appointment; modificationsMade = true; eventEntity.Name = calendarEvent.Summary; var calUidContainer = new ICalUidContainer { ICalUid = calendarEvent.Uid }; eventEntity.CalendarId = calUidContainer; string creatorEmailAddress = GetEmailAddress(message.EmFrom); if (creatorEmailAddress != null) { EmailContact creatorEmailContact = FindEmailContact(creatorEmailAddress); if (creatorEmailContact == null) { var mailAddress = new MailAddress(message.EmFrom); creatorEmailContact = CreateEmailContact(creatorEmailAddress, mailAddress.DisplayName ?? creatorEmailAddress); } eventEntity.EventEmailCreator = creatorEmailContact; } foreach (IAttendee attendee in calendarEvent.Attendees) { string emailAddress = GetEmailAddress(attendee.Value.ToString( )); if (emailAddress != null) { EmailContact emailContact = FindEmailContact(emailAddress); if (emailContact == null) { CreateEmailContact(emailAddress, attendee.CommonName); } appointment.EventEmailAttendees.Add(emailContact.EmailContactOwner); } } CreateAndSendAcceptance(calendar, iCalMessage, eventEntity); } else { appointment = eventEntity.EventEmailAppt; if (calendar.Method == Methods.Publish || calendar.Method == Methods.Request) { ///// // A REQUEST or PUBLISH means a new event arriving in the system. ///// CreateAndSendAcceptance(calendar, iCalMessage, eventEntity); } } eventEntity.ReceivedEmailMessages.Add(iCalMessage); ///// // Start time. ///// if (calendarEvent.Start != null) { DateTime utcTime = calendarEvent.Start.Utc; if (!Equals(utcTime, appointment.EventStart)) { appointment.EventStart = utcTime; modificationsMade = true; } } ///// // End time. ///// if (calendarEvent.End != null) { DateTime utcTime = calendarEvent.End.Utc; if (!Equals(utcTime, appointment.EventEnd)) { appointment.EventEnd = utcTime; modificationsMade = true; } } ///// // All Day Event. ///// if (appointment.EventIsAllDay == null || !Equals(calendarEvent.IsAllDay, appointment.EventIsAllDay.Value)) { appointment.EventIsAllDay = calendarEvent.IsAllDay; modificationsMade = true; } ///// // Location. ///// if (calendarEvent.Location != null) { if (!Equals(calendarEvent.Location, appointment.EventLocation)) { appointment.EventLocation = calendarEvent.Location; modificationsMade = true; } } ///// // Location. ///// if (eventEntity.EventEmailAppt.EventEmailPriority == null || !Equals(calendarEvent.Priority, eventEntity.EventEmailAppt.EventEmailPriority)) { string priorityAlias; if (calendarEvent.Priority <= 0) { ///// // Undefined. ///// priorityAlias = null; } else if (calendarEvent.Priority <= 4) { ///// // High priority. ///// priorityAlias = "core:highPriority"; } else if (calendarEvent.Priority == 5) { ///// // Normal priority. ///// priorityAlias = "core:normalPriority"; } else if (calendarEvent.Priority <= 9) { ///// // Low priority. ///// priorityAlias = "core:lowPriority"; } else { ///// // Invalid priority. ///// priorityAlias = null; } eventEntity.EventEmailAppt.EventEmailPriority = priorityAlias != null?Entity.Get <EventEmailPriorityEnum>(priorityAlias) : null; modificationsMade = true; } ///// // Status. ///// string statusAlias = null; switch (calendarEvent.Status) { case EventStatus.Cancelled: statusAlias = "core:eventStatusCancelled"; break; case EventStatus.Confirmed: statusAlias = "core:eventStatusConfirmed"; break; case EventStatus.Tentative: statusAlias = "core:eventStatusTentative"; break; } if (!string.IsNullOrEmpty(statusAlias)) { if (appointment.EventStatus == null || appointment.EventStatus.Alias != statusAlias) { appointment.EventStatus = Entity.Get <EventStatusEnum>(statusAlias); modificationsMade = true; } } if (modificationsMade) { CustomContext cc = null; try { string timeZone = null; if (eventEntity != null) { ///// // Find all sent iCal Email Messages that correlate to the received calendar events UID. ///// IEnumerable <SentICalEmailMessage> sentICalEmailMessages = eventEntity.SentEmailMessages; if (sentICalEmailMessages != null) { SentICalEmailMessage sentICalEmailMessage = sentICalEmailMessages.FirstOrDefault(sent => sent.ICalTimeZone != null); if (sentICalEmailMessage != null) { timeZone = sentICalEmailMessage.ICalTimeZone; } } } if (string.IsNullOrEmpty(timeZone)) { if (calendar.TimeZones != null) { ITimeZone calendarTimeZone = calendar.TimeZones.FirstOrDefault( ); if (calendarTimeZone != null) { timeZone = calendarTimeZone.TzId; } } } if (!string.IsNullOrEmpty(timeZone)) { ///// // Set up a custom context just for the duration of this call. ///// RequestContext currentRequestContext = RequestContext.GetContext( ); var data = new RequestContextData(currentRequestContext) { TimeZone = timeZone }; cc = new CustomContext(data); } eventEntity.Save( ); } finally { ///// // Ensure the custom context is disposed. ///// if (cc != null) { cc.Dispose( ); } } } } return(false); }
private void SendInvalidStateReply(ReceivedEmailMessage message) { // TODO: Add send }
private void SendNoTaskReply(ReceivedEmailMessage message) { // TODO: add send }
private void SendTaskCompletedReply(ReceivedEmailMessage message) { // TODO: add send }
public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction) { postSaveAction = () => { CreateUpdateFromReceivedEmail(message); }; return(true); }