I came across a very interesting requirement with respect to “Tasks” in SharePoint but before we get into the requirement lets get into few details first.
As most us are aware of the fact that when a task item is created, either directly in the task list or through a Workflow an alert email would be sent saying a task has been assigned to you (provided alerts are enabled). When we look at that email in Outlook we see an additional control in the ribbon “Open this Task” under the group “Open” as shown in the figure
Now let me explain the requirement: We have a custom workflow built using sequential workflow template in Visual studio 2010. The customer is not convinced with the details in the email body generated by SharePoint.
- we have to customize the body and subject as per their request
- Retain that Ribbon control “Open this Task” when the email is sent
- If possible, have the “From Address” in the email to be the person who initiated this workflow
That is all what was requested, looks very reasonable, simple and straight forward. When I started implementing it my first impression was it is not as simple as it looks. Later on when I went through different approaches I felt I wasn’t very wrong about this requirement and eventually it turned out be a very simple solution. As they often say “All things are difficult before they are easy”. So I thought I would post my approaches and the final solution.
- I have used “SPWorkflowTaskProperties” class in the Task Created Event and sent it two properties “SPWorkflowTaskProperties.HasCustomEmailBody = true” and “SPWorkflowTaskProperties.EmailBody= <My Custom HTML Email Body> ” With this I can satisfy requirement 1 & 2 but not 3 (listed above). Also if I were to create a task and if I want to send an email using Event Handler on item created I may not be able to use this. So for the generic purposes this would not fit in.
- Next I thought of modifying the alert template but then it would have an impact on all task lists which is not a recommended option.
- So, I have decided that I have to disable the alerts for that Task list and use “SmtpClient or SPUtility” class instead to send email which can be used at different requirements such as “event handlers/workflows or any other for that matter. With this class we do have control over all the aspects “From, To, Subject, Email Body, etc”. The only problem with this to achieve the requirement # 2 (Ribbon control in outlook). I always wondered how would outlook recognize that an email is for Task, how is this ribbon control activated as soon as it sees an email.
I believed that the alert email sent has some headers which mark this as Task which is understood by outlook and displays the controls accordingly. So now the question is what are those headers. After some research I figured out the Mail message headers. Below is the code for sending an email which also includes those headers and satisfies all the above mentioned requirements (1, 2 & 3)
/// <summary>
/// Send Email with a control “Open this Task” in Outlook ribbon
/// </summary>
/// <param name=”web”>SharePoint Web Object (SPWeb)</param>
/// <param name=”HtmlBody”>Body of the Email (string)</param>
/// <param name=”ToEmailId”>Email Id of the recipient (string)</param>
/// <param name=”listItem”>SharePoint List item Object (SPListItem)</param>
/// <param name=”EmailSubject”>Subject of the Email (string)</param>
/// <returns></returns>
public object[] SendMail(SPWeb web, string HtmlBody, string ToEmailId, SPListItem listItem, string EmailSubject)
{
try
{
SPWebApplication webApp = web.Site.WebApplication;
MailMessage message = new MailMessage();
//Have a dynamic email address if you wish to change the From Address message.From = new MailAddress(webApp.OutboundMailSenderAddress, web.Title);
message.BodyEncoding = Encoding.UTF8;
message.IsBodyHtml = true;
message.Body = HtmlBody;
message.To.Add(ToEmailId);
message.SubjectEncoding = Encoding.UTF8;
message.Subject = EmailSubject;
string domain = webApp.OutboundMailSenderAddress.Remove(0, webApp.OutboundMailSenderAddress.LastIndexOf(‘@‘));
message.Headers.Add(“Message-Id“, “<3BD50098E401463AA228377848493927” + Guid.NewGuid().ToString(“D“) + domain + “>“);
message.Headers.Add(“X-Sharing-Title“, this.ConvertToBase64String(listItem[“Body“].ToString()));
message.Headers.Add(“X-AlertTitle“, this.ConvertToBase64String(“System“));
message.Headers.Add(“Content-Class“, “MSWorkflowTask“);
message.Headers.Add(“X-AlertWebUrl“, this.ConvertToBase64String(web.Url));
message.Headers.Add(“X-AlertServerType“, “STS“);
message.Headers.Add(“X-AlertWebSoap“, this.ConvertToBase64String(web.Url + “/_vti_bin/alerts.asmx“));
message.Headers.Add(“X-Sharing-Config-Url“, “stssync://sts/?ver=1.1&type=tasks&cmd=add-folder&base-url=” + Uri.EscapeDataString(web.Url) + “&list-url=” + Uri.EscapeDataString(listItem.ParentList.RootFolder.ServerRelativeUrl) + “&guid=” + Uri.EscapeDataString(listItem.ParentList.ID.ToString(“D“)));
message.Headers.Add(“X-Sharing-Remote-Uid“, listItem.ParentList.ID.ToString(“D“));
message.Headers.Add(“X-Sharing-WssBaseUrl“, this.ConvertToBase64String(web.Url));
message.Headers.Add(“X-Sharing-ItemId“, this.ConvertToBase64String(listItem.ID.ToString()));
SmtpClient client = new SmtpClient(webApp.OutboundMailServiceInstance.Server.Address);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
client.Send(message);
return new object[] { true };
}
catch (Exception error)
{
return new object[] { false, error.Message }; }
}
string ConvertToBase64String(string InputString)
{
return “=?utf-8?B?” + System.Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(InputString)) + “?=“;
}
Note:
- Any of the above mentioned solutions can be used based on the requirement. I have therefore listed out different approaches and I would leave it to your best judgement to decide on the selection of approach.
- Above code is not a completely cleaned up code, you can remove unnecessary headers.
Hope this helps! Thank you for visiting my blog.
hi,
if i want to remove the “open this task” button. what should we do ?
Hi Meena,
Do not use message headers (that is, remove all the message.Headers.Add() code blocks), if you do not wish to have the ribbon control “open this task”
Regards,
Venkat
THanks venkat.. I have another doubt. without using the custom email body , with using the default mail notification , can we hide the open this task option. ? I have an issue, where after submitting the form from outlook, i get an error as :Invalid context for close the form action”
Hi Meena,
Do you have a custom form for task? If yes, then what are the rules defined on submission? For the out-of-the-box form there is no such error.
Regards,
Venkat
Update to the previous comment:
Have you created the workflow using SharePoint Designer? If yes, you can disable the assignment emails on the task list and have an additional action “Send an Email” to notify the users of item assignment.
To disable the assignment emails: Go to your task list -> List settings -> Advanced Settings : In the E-Mail Notification section, set “Send e-mail when ownership is assigned?” to “No”
Hope this helps!
Regards,
Venkat
Hi Venkat,
Pardon my ignorance, but how exactly do you insert this code into the Send an Email action? I tried advanced properties and inserted it into the body, but that just emails me the text of the code, it doesn’t seem to render that way.
Regards,
Adam
Hi Adam,
You’ll have to an event for each activity, inside that event you can paste the code (maybe just double click on the activity and it would take you to the appropriate code block). But if you are saying the text of the email is just a plain text and not the rich text then you’ll have to set the “IsBodyHtml” attribute to “true;” as below:
message.IsBodyHtml = true;
Regards,
Venkat
Hi Venkat,
Thanks for sharing this, exactly what I am after. However its not working 😦 below are the headers from the email but the Edit Task button is not visible in outlook. Do you see any problem with the headers? i have omited X-Sharing-Title, rest of them are all present.
X-Sender: No-Reply
X-Receiver: santosh@xyz.com
X-Sharing-Config-Url: stssync://sts/?ver=1.1&type=tasks&cmd=add-folder&base-url=http%3A%2F%2Fsukcw-vwi-sps02%3A2010%2Fsites%2Fusops&list-url=%2Fsites%2Fusops%2FProjectDocuments&guid=67e6c850-744d-488f-acf4-09b411916f21
Message-ID:
X-AlertTitle: U3lzdGVt
Content-Class: TVNXb3JrZmxvd1Rhc2s=
X-AlertWebUrl: aHR0cDovL3N1a2N3LXZ3aS1zcHMwMjoyMDEwL3NpdGVzL3Vzb3Bz
X-AlertServerType: STS
X-AlertWebSoap: aHR0cDovL3N1a2N3LXZ3aS1zcHMwMjoyMDEwL3NpdGVzL3Vzb3BzL19WdGlfYmluL2FsZXJ0cy5hc214
MIME-Version: 1.0
From: No-Reply
To: santosh@xyz.com
Date: 18 Sep 2014 16:28:18 +0100
Subject: =?utf-8?B?ICAgICAgICAgICAgICBSZXZpZXcgUmVxdWVzdCA6IDA1bGl2ZS1lZ28gICAgICAgICAgICA=?=
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
Hi Santhosh,
Apologies for delayed response. I would recommend you to include all the headers I have listed. After you see that working then start removing few headers to see if that still works.
Regards,
Venkat