/// <summary> /// Enqueues emails asynchronously. /// </summary> /// <param name="project">The project that contains the given contacts.</param> /// <param name="mailHeader">The mail header that defines contacts and filter criteria.</param> /// <param name="mailMessage">The mail message to send.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns> /// The task object representing the number of the recipients. /// </returns> public virtual async Task <ValidationResult> SendAsync(ProjectItem project, MailMessageHeader mailHeader, MailMessageItem mailMessage, CancellationToken cancellationToken) { var validationResult = await ValidateAsync(project, mailHeader, mailMessage, cancellationToken); if (!validationResult.Succeeded) { return(validationResult); } var from = await GetSenderAsync(project, mailHeader, cancellationToken); if (from == null) { throw new InvalidOperationException("The sender of the mail message is not specified."); } var to = await GetRecipientsAsync(project, mailHeader, cancellationToken); if (to.Any()) { Users = await GetUsersAsync(project, cancellationToken); _userIds = Users.Select(u => u.Id).ToImmutableArray(); await EqueueAllAsync(project, from, to, mailMessage, mailHeader.Placeholders, cancellationToken); } return(ValidationResult.Success); }
/// <summary> /// Gets all the contacts that satisfy the given criteria. /// </summary> /// <param name="project">The project that contains the given contacts.</param> /// <param name="mailHeader">The message header.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns> /// The task object representing the asynchronous operation. /// </returns> protected virtual Task <ContactItem> GetSenderAsync(ProjectItem project, MailMessageHeader mailHeader, CancellationToken cancellationToken) { Debug.Assert(project != null); Debug.Assert(mailHeader != null); if (mailHeader.From != null) { return(Task.FromResult(mailHeader.From)); } return(Task.FromResult(new ContactItem { Email = project.Sender })); }
/// <summary> /// Called by the workflow runtime to execute an activity. /// </summary> /// <param name="context">The <see cref="ActionActivityContext"/> to associate with this activity and execution.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param> /// <returns> /// The <see cref="ActionActivityResult"/> of the run task, which determines whether the activity remains in the executing state, or transitions to the closed state. /// </returns> public async Task <ActionActivityResult> ExecuteAsync(ActionActivityContext context, CancellationToken cancellationToken) { var projectManager = context.Resolve <ProjectManager>(); var mailService = context.Resolve <IMailClientService>(); if (!context.ContactExists || context.ContactState == ObjectState.Deleted) { return(context.CreateResult(ActionActivityStatusCode.Failed)); } var options = context.Action.Options?.ToObject <Options>(); if (options == null) { return(context.CreateResult(ActionActivityStatusCode.Failed)); } var message = await projectManager.GetMailMessageByIdAsync(options.Id, MailMessageField.Body, cancellationToken); if (message == null) { return(context.CreateResult(ActionActivityStatusCode.Failed)); } var project = await projectManager.FindByIdAsync(context.Project.Id, cancellationToken); if (project == null) { return(context.CreateResult(ActionActivityStatusCode.Failed)); } var header = new MailMessageHeader(); header.To.Add(context.Contact.Id); var invitation = context.Properties["Invitation"] as ProjectInvitation; if (invitation != null) { header.From = invitation.From; header.Placeholders[ActionResources.Invitation] = invitation; } await mailService.SendAsync(project, header, message, cancellationToken); return(context.CreateResult(ActionActivityStatusCode.Success)); }
/// <summary> /// Validates the specified <paramref name="mailHeader"/> and <paramref name="mailMessage"/> as an asynchronous operation. /// </summary> /// <param name="project">The project that contains the given contacts.</param> /// <param name="mailHeader">The mail header that defines contacts and filter criteria.</param> /// <param name="mailMessage">The mail message to send.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns> /// The task object representing the number of the recipients. /// </returns> public virtual Task <ValidationResult> ValidateAsync(ProjectItem project, MailMessageHeader mailHeader, MailMessageItem mailMessage, CancellationToken cancellationToken) { if (project == null) { return(Task.FromResult(ValidationResult.Failed(string.Format(CultureInfo.CurrentCulture, MailResources.MailProjectRequired)))); } if (mailHeader == null) { return(Task.FromResult(ValidationResult.Failed(string.Format(CultureInfo.CurrentCulture, MailResources.MailHeaderRequired)))); } if (mailHeader.To.Count == 0 && mailHeader.IncludeWithTags.Count == 0 && mailHeader.ExcludeWithTags.Count == 0) { return(Task.FromResult(ValidationResult.Failed(string.Format(CultureInfo.CurrentCulture, MailResources.MailFilterPredicateRequired)))); } if (mailMessage == null) { return(Task.FromResult(ValidationResult.Failed(string.Format(CultureInfo.CurrentCulture, MailResources.MailMessageRequired)))); } if (string.IsNullOrWhiteSpace(mailMessage.Subject)) { return(Task.FromResult(ValidationResult.Failed(string.Format(CultureInfo.CurrentCulture, MailResources.MailMessageSubjectRequired)))); } return(Task.FromResult(ValidationResult.Success)); }
/// <summary> /// Converts the model object to a <see cref="MailMessageHeader"/> object. /// </summary> /// <returns> /// The <see cref="MailMessageHeader"/> object. /// </returns> public MailMessageHeader ToMailMessageHeader() { var header = new MailMessageHeader { From = From }; if (To != null) { foreach (var to in To) { header.To.Add(to); } } if (IncludeWithTags != null) { foreach (var tag in IncludeWithTags) { header.IncludeWithTags.Add(tag); } } if (ExcludeWithTags != null) { foreach (var tag in ExcludeWithTags) { header.ExcludeWithTags.Add(tag); } } if (Placeholders != null) { foreach (var placeHolder in Placeholders) { header.Placeholders.Add(placeHolder); } } return(header); }
/// <summary> /// Gets all the contacts that satisfy the given criteria. /// </summary> /// <param name="project">The project that contains the given contacts.</param> /// <param name="mailHeader">The message header.</param> /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> /// <returns> /// The task object representing the asynchronous operation. /// </returns> protected virtual async Task <ImmutableArray <ContactItem> > GetRecipientsAsync(ProjectItem project, MailMessageHeader mailHeader, CancellationToken cancellationToken) { Debug.Assert(project != null); Debug.Assert(mailHeader != null); var contacts = new HashSet <ContactItem>(UniqueItemEqualityComparer.Default); if (mailHeader.To.Any()) { contacts.UnionWith( await ProjectManager.GetContactsAsync(project, mailHeader.To, ContactSortOrder.None, ContactField.None, cancellationToken)); } if (mailHeader.IncludeWithTags.Any() || mailHeader.ExcludeWithTags.Any()) { contacts.UnionWith( (await ProjectManager.GetContactsAsync(project, null, mailHeader.IncludeWithTags, mailHeader.ExcludeWithTags, ContactSortOrder.None, 0, int.MaxValue, ContactField.None, cancellationToken)).Data); } return(contacts.Where(c => c.Email?.Address != null).ToImmutableArray()); }