Custom workflow activity to send an email and specify the sendor address.

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/