Wednesday, October 1, 2008

MOSS State Workflow Email Escalation Part 2

Scenario


The scenario I have is that I have a state workflow that I am building in Visual Studio and deploying to MOSS. In this human workflow I need to incorporate the concept of raising an escalation email event so when a user has not completed a task in a period of time. I was doing an early proof of concept and found issues with DelayActivity requiring me to install a hotfix. Well I thought I would have everything working and it would be really simple to just throw on an email activity after the delay activity. However I was terribly wrong.


Design


I was basically following a simple pattern where I would add two event driven activities, one that would wait for an action to be taken on the task, and another where a delay activity would wait for a period of time to pass.

Here is what I had for the escalation. Basically after a period of time the delay would end, an email would be sent and then a log would be made. Hey that should be simple?Error Message

At first, I was getting no error messages; nothing in the ULS logs and nothing in the event viewer. Then after doing some playing around I noticed if I disabled the email activity everything would work. So I something was wrong there.

After playing with it a bunch more and I started to get "The e-mail message cannot be sent. Make sure the outgoing e-mail settings for the server are configured correctly." in the workflow log. This was extremely annoying because emails are working in task lists and other places throughout the workflow the SendEmail activity was absolutely working, just not in my escalation.

Well there were numerous things going wrong with using the EmailActivity. After doing some searching I saw that many had given up and just used SPUtilities.SendEmail() or just wrote their own wrapper to use System.Net.Mail but to tell you the truth the SendEmail activity was MOCKING ME. I know that there must be a way to send an email.

Resolution

I was able to find out some of this has to do with the way DelayActivity worked with MOSS and specifically state workflows. All of the issues I was experiencing would not occur in a sequential workflow. When configuring a SendEmail activity that occurs after a DelayAcitivty you need to make sure the it is configured correctly.


A few notes:

  • The CorrelationToken must be correctly set. It is possible that you may have many tokens in your workflow. You will have on for the token for the WorkflowActivated activity and you may have a different tokens tied to the CreateTask activity (such as my case). Make sure you use the token that is from the WorkflowActivated activty. Otherwise you will get no errors and the workflow will throw an error into the log and give you no information.
  • If you are trying to set any of the properties of the SendEmail activities in code, stop as you will run into tons of problems. Check out the references below. What you will need to do is create new workflow properties and bind to them like the above screenshot. Then in an event handler you can set the values. If you create an event handler and then try to set SendEmail object directly none of the values will be set and you will get an empty email throwing errors.
  • Finally in the code of the onSendEmail event handler, you will have limited access to data. I was not able to narrow down why this is occurring (partly because I just do not care anymore). For instance, you may want to put the title of the task into the body of the email. So you may have a SPWorkflowTaskProperties object where you will want to get this data from. Well, I was getting ton null exceptions when trying to do this. I did find that I could use the SPWorkflowActivationProperties and that was good enough at this point.

The following is some code from the onSendEmail handler. Here you will see where I set the attributes I have bound to the SendEmail activity. You will see that I have an object that I use to get data from the InfoPath that is being routed around (beyond scope of this blog entry).


private void onSendEmail(object sender, EventArgs e)
{
this.EmailTo = _infoPath.ManagerEmail;
this.EmailSubject = "Reminder - New User Request Task";
this.EmailBody = "A New User Request for " + _infoPath.FirstLastName +
"was assigned to you but not completed. " +
"Please go to the following Task list to complete your assigned task: " +
NewUserRequestWorkflowProperties.WebUrl + NewUserRequestWorkflowProperties.TaskListUrl;
}

References

No comments: