Sending Email with Attachments from Sharepoint Custom Workflows

By David Fekke's Blog at January 21, 2008 05:33
Filed Under:

I have been developing custom Sharepoint workflows in Visual Studio 2005 over the past year. It can be fustrating developing for Sharepoint 2007 because Microsoft has done a lousy job documenting the Sharepoint API.

The SendMail activity in the workflow tools does not allow for email attachments. I found a good work around is to use the .NET email API in a custom code activity. In the following example I send an email with an attachment.

SmtpClient client = new SmtpClient();

client.Host = smtpServer;

client.Port = 25;

client.DeliveryMethod = SmtpDeliveryMethod.Network;

MailMessage myMailMessage = new MailMessage();

myMailMessage.From = new MailAddress(this.fromEmail);

myMailMessage.Subject = "Test email subject";

myMailMessage.Body = "This is a test email message.";

myMailMessage.To.Add(new MailAddress(toEmail));

MemoryStream myMemoryStream = new MemoryStream(this.attachmentByteArray);

myMailMessage.Attachments.Add(new Attachment(myMemoryStream, this.attachmentFileName));

client.Send(myMailMessage);

>

If you need to dynamically get the name of the Smtp server, you can get this throught the parent web application. Here is an example of how to call it through the Workflow Properties.

SPSite site = this.workflowProperties.Site;

SPWebApplication webapp = site.WebApplication;

//Get the SMTP server

string smtpServer = webapp.OutboundMailServiceInstance.Server.Address;

>

I found the previous example in this

Blog post.

Update

There is a question on how I got the Byte[] array. I used a InfoPath form to collect the attachment. The InfoPath form stores this attachment in a XML node as base64 encoded string. When .NET pulls the value from the XML node, it turns the value into a byte array. I then use the following code to extract the filename and the document data;

byte[] myAttachment = myInfoPathForm.Attachment;

if (myAttachment != null)

{

int namebufferlen = myAttachment[20] * 2;

byte[] filenameBuffer = new byte[namebufferlen];

for (int i = 0; i < filenameBuffer.Length; i++)

{

filenameBuffer[i] = myAttachment[24 + i];

}

char[] asciiChars = UnicodeEncoding.Unicode.GetChars(filenameBuffer);

string filename = new string(asciiChars);

filename = filename.Substring(0, filename.Length - 1);

byte[] filecontent = new byte[myAttachment.Length - (24 + namebufferlen)];

for (int i = 0; i < filecontent.Length; i++)

{

filecontent[i] = myAttachment[24 + namebufferlen + i];

}

this.attachmentByte = filecontent;

this.attachmentFileName = filename;

}

>

This code only works if you are pulling the data from an InfoPath form.

Comments

1/17/2008 9:03:23 PM #

sapthagiri

MemoryStream myMemoryStream = new MemoryStream(this.attachmentByteArray);
myMailMessage.Attachments.Add(new Attachment(myMemoryStream, this.attachmentFileName));

in the above code what is "(this.attachmentByteArray) "  and what is  "this.attachmentFileName"    how get the valuesin "attachmentByArray"  and "attachmentFileName"

can u please explain how to get that values.

sapthagiri United States

1/18/2008 1:39:50 AM #

David Fekke

sapthagiri,

I will update the blog with how I got these values.

David.

David Fekke United States

6/4/2008 4:12:24 PM #

sddf

http://mp-3.name/

sddf United States

7/6/2008 2:37:51 AM #

Jennifer

IF anyone knows ANYONE that I can hire to create custom workflows for me, send them to me.  I assume it's called workflows.  I'm trying to automate a bunch of stuff that ties up my time
like when a new hire drops off documents, I get an alert.  All the back office crap I hate.

Jennifer Goodwin
http://www.internetGIRLfriday.com

Jennifer United States

12/27/2008 4:52:45 PM #

share point

Nice Blog! Thanks for the information

share point United States

1/26/2009 2:33:10 PM #

FG

IF anyone knows ANYONE that I can hire to create custom workflows for me, send them to me. I assume it's called workflows. I'm trying to automate a bunch of stuff that ties up my time
like when a new hire drops off documents, I get an alert. All the back office crap I hate.

FG United States

2/2/2009 6:19:56 AM #

rose

Great! Thank you!

rose United States

2/11/2009 1:08:03 AM #

Hikmer

Ok, so you are sending an attachment from Infopath...how about a document from a list or library?

Hikmer United States

2/20/2009 1:50:54 AM #

David Fekke

You run the code in Sharepoint as a SharePoint worflow.

David Fekke United States

2/21/2009 8:55:39 PM #

Dave

I was looking all over for how to retrieve the sharepoint smtp server settings in code. The code you provided helped me out a lot! Thanks!!

Dave United States

2/21/2009 9:03:49 PM #

David Fekke

I am glad I could help.

David Fekke United States

3/10/2009 2:30:34 AM #

amila abeyrathne

i have used SPUtility.SendEmail Method (Microsoft.SharePoint.Utilities)  to send emails in sharepoint custom workflows. example is shown in below link. you may try to use this method
to fulfill your need as you want.

http://www.sharepoint-amila.blogspot.com/

amila abeyrathne United States

8/26/2009 5:53:50 PM #

Avi Kumar

David

Can you please share the code for infopath attachment?

I want to create a workflow for an infopath library whenever item is created or changed?

Avi

Avi Kumar United States

9/17/2009 12:49:29 AM #

John

byte[] myAttachment = myInfoPathForm.Attachment;

I'd like to use this 'inside' InfoPath (client based form).  Assuming I'm reading your comment above this block of code correctly, I should somehow be able to get node.SelectSingleItem(path, namespace).value into that byte array.

Any help on that?  It 'seems' to be my last sticking point, at least to getting the code to compile in my code behind in the InfoPath form.

Thanks.

John United States

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading