Custom workflow activity to send an email and specify the sendor address.
November 12, 2010 1 Comment
Just a quick post here to post the code used to add the custom workflow activity that will enable you specify the sendor address in a workflow email. In SharePoint v3.0, I used the spactivities on codeplex but this doesn’t work for SharePoint Foundation or 2010. I followed a number of posts to get this code working.
SendMailActivity.cs:
using System; using System.ComponentModel; using System.ComponentModel.Design; using System.Collections; using System.Linq; using System.Workflow.ComponentModel.Compiler; using System.Workflow.ComponentModel.Serialization; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Design; using System.Workflow.Runtime; using System.Workflow.Activities; using System.Workflow.Activities.Rules; using System.Net.Mail; using Microsoft.SharePoint; using Microsoft.SharePoint.Workflow; using Microsoft.SharePoint.WorkflowActions; using System.IO; namespace SPDActivityDemo { public partial class SendMailActivity : Activity { public static DependencyProperty ToProperty = DependencyProperty.Register( "To", typeof(ArrayList), typeof(SendMailActivity)); public static DependencyProperty FromProperty = DependencyProperty.Register( "From", typeof(string), typeof(SendMailActivity)); public static DependencyProperty CCProperty = DependencyProperty.Register( "CC", typeof(ArrayList), typeof(SendMailActivity)); public static DependencyProperty SubjectProperty = DependencyProperty.Register( "Subject", typeof(string), typeof(SendMailActivity)); public static DependencyProperty BodyProperty = DependencyProperty.Register( "Body", typeof(string), typeof(SendMailActivity)); public static DependencyProperty __ContextProperty = DependencyProperty.Register( "__Context", typeof(WorkflowContext), typeof(SendMailActivity)); public SendMailActivity() { InitializeComponent(); } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] [Description("Enter any e-mail recipients, separated by semicolons")] public ArrayList To { get { return ((ArrayList)(base.GetValue(ToProperty))); } set { base.SetValue(ToProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] [Description("Enter the e-mail sender")] public string From { get { return ((string)(base.GetValue(FromProperty))); } set { base.SetValue(FromProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] [Description("Enter any carbon copy recipients, separated by semicolons")] public ArrayList CC { get { return ((ArrayList)(base.GetValue(CCProperty))); } set { base.SetValue(CCProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] [Description("Enter the e-mail subject")] public string Subject { get { return ((string)(base.GetValue(SubjectProperty))); } set { base.SetValue(SubjectProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] [Description("Enter the body text of the e-mail")] public string Body { get { return ((string)(base.GetValue(BodyProperty))); } set { base.SetValue(BodyProperty, value); } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Browsable(true)] public WorkflowContext __Context { get { return ((WorkflowContext)(base.GetValue(__ContextProperty))); } set { base.SetValue(__ContextProperty, value); } } protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { try { //Send the email //grab the Activity for the Lookup Fields to be based on Activity myActivity = executionContext.Activity; while (myActivity.Parent != null) { myActivity = myActivity.Parent; } //Send the email with attachments!! SendEmail(myActivity); } finally { //nada } //Indicate the activity has closed return ActivityExecutionStatus.Closed; } private void SendEmail(Activity parent) { //Create a new object that will send the email System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(); //Create the fromAddress variable and then determine the from email address //Create an object to specify the from address for the email System.Net.Mail.MailAddress fromAddress; try { //set the email address fromAddress = new System.Net.Mail.MailAddress(From); } catch (System.Exception Ex) { fromAddress = new System.Net.Mail.MailAddress("<a href="mailto:administrator@domain.com">administrator@domain.com</a>"); } //Set the from email address on the message object msg.From = fromAddress; //Determine who the email will be sent to, To and CC, and add those email addresses to the msg object created in STEP 1. try { //Add the email addresses stored in the To property to the email message object for (int i = 0; i < To.Count; i++) { msg.To.Add(To[i].ToString()); } } catch (System.Exception Ex) { //errored out on the To list msg.To.Add("<a href="mailto:administrator@domain.com">administrator@domain.com</a>"); } try { //Add the email addresses stored in the CC property to the email message object if (CC != null) { for (int i = 0; i < CC.Count; i++) { msg.CC.Add(CC[i].ToString()); } } } catch (System.Exception Ex) { //errored out on the CC list… odd msg.CC.Add("<a href="mailto:administrator@domain.com">administrator@domain.com</a>"); } // Create the subject line for this Email String mySubject = ""; try { //To include fields in the subject line from the List, uncomment the lines below //mySubject += Subject; //mySubject += ” (” + Helper.LookupString(this.__Context, this.ListId, this.ListItem, “My Field 1″) + “)”; mySubject = Subject; } catch (System.Exception Ex) { mySubject = "ERR: Invalid Subject Line"; } msg.Subject = mySubject; //Generate the message body //start the handling of the message body. msg.IsBodyHtml = true; String myBody = Body; //make SharePoint replace the Lookup Strings in the field try { //process the Add Lookup strings [%...%] from the Workflow configuration myBody = Helper.ProcessStringField(myBody, parent, this.__Context); } catch (System.Exception Ex) { //create a writer and open the file TextWriter tw = new StreamWriter("E:\\error.log"); //write a line of text to the file tw.WriteLine(DateTime.Now +" – " + Ex.Message + Ex.StackTrace); //close the stream tw.Close(); } msg.Body = myBody; //Set SmtpServer to default SharePoint SMTP Server **Change to your smtp ip address String SMTPServerName = "smtp server ip address"; //Create an object to represent the mail server and SEND the message try { System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(SMTPServerName); //Set the credentials used to authenticate to the email server client.UseDefaultCredentials = true; //Send the message client.Send(msg); } catch (System.Exception Ex) { //create a writer and open the file TextWriter tw = new StreamWriter("E:\\error.log"); //write a line of text to the file tw.WriteLine(DateTime.Now +" – " + Ex.Message + Ex.StackTrace + Ex.Data); //close the stream tw.Close(); } } } }
.ACTIONS file:
<?xml version="1.0" encoding="utf-8" ?> <WorkflowInfo> <Actions Sequential="then" Parallel="and"> <Action Name="Send Email Extended" ClassName="SPDActivityDemo.SendMailActivity" Assembly="SPDActivityDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d1763733beaa0777" AppliesTo="all" Category="Extended Activities"> <RuleDesigner Sentence="Send email from [%1] to [%2]"> <FieldBind Field="From" DesignerType="TextArea" Text="this person" Id="1"/> <FieldBind Field="To,CC,Subject,Body" DesignerType="Email" Text="this person" Id="2"/> </RuleDesigner> <Parameters> <Parameter Name="To" Type="System.Collections.ArrayList, mscorlib" Direction="In" Description="Recipients of the email." /> <Parameter Name="CC" Type="System.Collections.ArrayList, mscorlib" Direction="Optional" Description="Carbon copy recipients of the email." /> <Parameter Name="Subject" Type="System.String, mscorlib" Direction="In" Description="Subject line of the email." /> <Parameter Name="Body" Type="System.String, mscorlib" Direction="Optional" Description="Body text of the email." /> <Parameter Name="From" Type="System.String, mscorlib" Direction="In" Description="Sender of the email." /> <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/> </Parameters> </Action> </Actions> </WorkflowInfo>
References used:
http://www.devtrends.com/index.php/custom-workflow-actions-part-1-of-3/
http://msdn.microsoft.com/en-us/library/cc627284.aspx
http://sharepointbloggin.com/2010/02/10/walkthrough-3-sharepoint-designer-workflows-imported-to-visual-studio-2010/