Sanket
Sanket

Reputation: 83

Orchard work flow - Send email to multiple admin and moderator on content post/Update

I am working with Orchard CMS. I have created work flow which send mail to Super admin and user himself who create block/news as a notification.

In my CMS there more than one admin and moderator. I want to send email to all moderator and admin as soon as new blog /news/article is posted or updated. Right now it is sending to only one admin user not all.

How can I create workflow to send mail to all admin as well as moderator once content (news/blog) is posted or updated?

I am working on orchard version 1.10.0.

Upvotes: 1

Views: 321

Answers (1)

Xceno
Xceno

Reputation: 913

There are two possibilities here: A custom workflow task and a simple token.

Let's start with the task. I've created a simple demo; here's the code:

Activities/RoleMailerTask.cs

namespace My.Module
{
    using System.Collections.Generic;
    using System.Linq;
    using Orchard;
    using Orchard.ContentManagement;
    using Orchard.Data;
    using Orchard.Email.Activities;
    using Orchard.Email.Services;
    using Orchard.Environment.Extensions;
    using Orchard.Localization;
    using Orchard.Messaging.Services;
    using Orchard.Roles.Models;
    using Orchard.Roles.Services;
    using Orchard.Users.Models;
    using Orchard.Workflows.Models;
    using Orchard.Workflows.Services;

    [OrchardFeature(Statics.FeatureNames.RoleMailerTask)]
    public class RoleMailerTask : Task
    {
        private readonly IOrchardServices services;
        public const string TaskName = "RoleMailer";

        public RoleMailerTask(IOrchardServices services)
        {
            this.services = services;
            this.T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        public override string Name
        {
            get { return TaskName; }
        }

        public override string Form
        {
            get { return TaskName; }
        }

        public override LocalizedString Category
        {
            get { return this.T("Messaging"); }
        }

        public override LocalizedString Description
        {
            get { return this.T("Sends mails to all users with this chosen role"); }
        }

        public override IEnumerable<LocalizedString> GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext)
        {
            yield return this.T("Done");
        }

        public override IEnumerable<LocalizedString> Execute(WorkflowContext workflowContext, ActivityContext activityContext)
        {
            var recipientsRole = int.Parse(activityContext.GetState<string>("RecipientsRole"));
            var role = this.services.WorkContext.Resolve<IRoleService>().GetRole(recipientsRole);

            var userRolesRepo = this.services.WorkContext.Resolve<IRepository<UserRolesPartRecord>>();
            var recepientIds = userRolesRepo.Table.Where(x => x.Role.Name == role.Name).Select(x => x.UserId);

            var recipients = this.services.ContentManager.GetMany<UserPart>(recepientIds, VersionOptions.Published, QueryHints.Empty)
                .Where(x => !string.IsNullOrEmpty(x.Email))
                .Select(x => x.Email);

            var body = activityContext.GetState<string>("Body");
            var subject = activityContext.GetState<string>("Subject");

            var replyTo = activityContext.GetState<string>("ReplyTo");
            var bcc = activityContext.GetState<string>("Bcc");
            var cc = activityContext.GetState<string>("CC");

            var parameters = new Dictionary<string, object> {
                {"Subject", subject},
                {"Body", body},
                {"Recipients", string.Join(",", recipients)},
                {"ReplyTo", replyTo},
                {"Bcc", bcc},
                {"CC", cc}
            };

            var queued = activityContext.GetState<bool>("Queued");

            if ( !queued )
            {
                this.services.WorkContext.Resolve<IMessageService>().Send(SmtpMessageChannel.MessageType, parameters);
            }
            else
            {
                var priority = activityContext.GetState<int>("Priority");
                this.services.WorkContext.Resolve<IJobsQueueService>().Enqueue("IMessageService.Send", new { type = SmtpMessageChannel.MessageType, parameters = parameters }, priority);
            }

            yield return T("Done");
        }
    }
}

You might want to throw the recipients in a loop, and send a new email for each of them. With the version above, everyone will see the mail address of everyone else...

Forms/RoleMailerTaskForm.cs

namespace My.Module
{
    using System;
    using System.Linq;
    using System.Web.Mvc;
    using Activities;
    using Orchard;
    using Orchard.ContentManagement;
    using Orchard.DisplayManagement;
    using Orchard.Environment.Extensions;
    using Orchard.Forms.Services;
    using Orchard.Roles.Services;

    [OrchardFeature(Statics.FeatureNames.RoleMailerTask)]
    public class RoleMailerTaskForm : Component, IFormProvider
    {
        private readonly IRoleService roleService;

        public RoleMailerTaskForm(IShapeFactory shapeFactory, IRoleService roleService)
        {
            this.roleService = roleService;
            this.Shape = shapeFactory;
        }

        public dynamic Shape { get; set; }

        public void Describe(DescribeContext context)
        {
            Func<IShapeFactory, dynamic> formFactory = shape =>
            {
                var form = this.Shape.Form(
                    Id: RoleMailerTask.TaskName,
                    _Type: this.Shape.FieldSet(
                            Title: this.T("Send to"),
                            _RecepientsRole: this.Shape.SelectList(
                                Id: "recipientsRole",
                                Name: "RecipientsRole",
                                Title: this.T("Recepient role"),
                                Description: this.T( "The role of the users that should be notified" ),
                                Items: this.roleService.GetRoles().Select(r => new SelectListItem { Value = r.Id.ToString(), Text = r.Name })
                            ),
                            _Bcc: this.Shape.TextBox(
                                Id: "bcc",
                                Name: "Bcc",
                                Title: this.T("Bcc"),
                                Description: this.T("Specify a comma-separated list of email addresses for a blind carbon copy"),
                                Classes: new[] { "large", "text", "tokenized" }),
                            _CC: this.Shape.TextBox(
                                Id: "cc",
                                Name: "CC",
                                Title: this.T("CC"),
                                Description: this.T("Specify a comma-separated list of email addresses for a carbon copy"),
                                Classes: new[] { "large", "text", "tokenized" }),
                            _ReplyTo: this.Shape.Textbox(
                                Id: "reply-to",
                                Name: "ReplyTo",
                                Title: this.T("Reply To Address"),
                                Description: this.T("If necessary, specify an email address for replies."),
                                Classes: new[] { "large", "text", "tokenized" }),
                            _Subject: this.Shape.Textbox(
                                Id: "Subject", Name: "Subject",
                                Title: this.T("Subject"),
                                Description: this.T("The subject of the email message."),


              Classes: new[] { "large", "text", "tokenized" }),
                        _Message: this.Shape.Textarea(
                            Id: "Body", Name: "Body",
                            Title: this.T("Body"),
                            Description: this.T("The body of the email message."),
                            Classes: new[] { "tokenized" })
                        ));

            return form;
        };

        context.Form(RoleMailerTask.TaskName, formFactory);
    }
}

This is the form you'll need to configure the task. The form is a blatant rip off from Orchard.Email/Forms/EmailForm. The only thing I've changed is the select list on top of the form.

And that's all you need!

For the token approach, you would just need to define a token like {RoleRecpients:TheRoleYouWant}, parse that role name and get the users like shown in the Task above.

Upvotes: 0

Related Questions