ArticleMotron - Your source to search and find article content.
Search:

Home | Computer

Send a SharePoint document library file as email

This article was orignially posted to http://furuknap.blogspot.com/2008/07/send-sharepoint-document-library-file.html

Ever wanted to send a SharePoint item by email to someone? No? Well, neither have I. turns out, someone else did, though, and they did not know how, so I thought I'd help out. And you never know, it might turn out to be you next time, and what will you do then? Now you can just remember that weird Norwegian guy who wrote that thing back in the days and come here to pick up your solution. And, to save you some time, I'll actually upload the entire solution for you, ready to use with just one simple step to do.

Scope
Ok, so what is our scope. I want to have some way of sending an individual file from a SharePoint library to someone. The file should be sent as an attachment and I should just have to enter the recipients email and perhaps a message.

To accomplish this I want to add a choice to the drop-down menu that appears on a library item when you hover-and-click a library item.

Clicking on that item should open up a form that I can use to fill out recipient address and a message. When I click a Send button on that page I should return to the list.

Let's get down to business.

Solution walk-through
For this project I will use WSPBuilder that I wrote about in my Basic setup of SharePoint Visual Studio project article. Make sure you have WSPBuilder with the Visual Studio extensions installed, it will save you tons of work and make SharePoint development a joy. So much for advertising.

Our ingredients:

- One visual studio 2005 or 2008.
- WSPBuilder with Visual Studio Extensions.
- SharePoint in any v3 flavor, WSS or MOSS
- .Net Reflector
- An SMTP-server, like that of your ISP or your own

Step 1: Setup

First, start by creating a new WSPBuilder project in Visual Studio. Use whatever name you like, for example SendAsEmail as I did. Add a new empty feature to the project. With WSPBuilder extensions it is simply a matter of right-clicking the project in the solution explorer and click Add->New item. The items available to you includes an empty feature. Write a nice description and make sure the feature is web scoped.

Second, add a class file. I like to add my class files to a folder in the Project called FeatureCode. The reason for this is that WSPBuilder will also use this folder to add custom code, and I like to keep my code in one place in small projects such as this. To do so, right-click the project again and click Add->New folder. Call it FeatureCode. Then, right-click that folder and click Add->Class. Browse to the Visual C# Project items to find the Class file. Call it again whatever you like. I call mine SendAsEmail.cs.

Third, add references to your project. Right-click the References in solution explorer and add references to Windows SharePoint Services (microsoft.sharepoint.dll) and System.Web.

Finally, create a new blank ASPX page to your solution. This page will be the custom form we will use to input the recipients email and the message text. To do so, first right-click on the 12\Template folder under your project in the solution explorer. Click Add->New folder and call it Layouts. No, you cannot call this anything else, it must be named Layouts. This folder largely corresponds to the _layouts virtual directory in SharePoint and we want to put our file there to make it available everywhere. Next, right-click the layouts folder and click Add->New item. Again, browse to the Visual C# Project items and find a Text file item. There is no ASPX page item to add to a non-website project, but we can still get one by naming our new text file SendAsEmail.aspx. Or something else, the important thing is to call it [something].aspx.

Now to start the actual development.

Step 2: Create a custom action feature

Open the empty feature you created in step 1. Browse to the folder in the solution explorer and open the elements.xml file. In the elements.xml file, add the following code:

1 <?xml version="1.0" encoding="utf-8" ?>
2 <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3 <CustomAction Title="Send as email"
4 Id="SendAsEmailECB"
5 RegistrationType="List"
6 RegistrationId="101"
7 ImageUrl="/_layouts/images/MSG16.GIF"
8 Location="EditControlBlock"
9 Sequence="225">
10 <UrlAction Url="~site/_layouts/SendAsEmail.aspx?ItemId={ItemId}&ListId={ListId}" />
11 </CustomAction>
12
13 </Elements>

The customaction element allows you to modify action menus all around SharePoint. There are a few lines here that are critical to accomplish what we want. Line 5, RegistrationType, states that we want this to be linked to a list, and line 6, RegistrationId, states that the list type should be from template 101 or Document Library. If you develop your own list templates you can link a custom action to only that particular list by modifying RegistrationId to match you template type. List 8, Location, states that we want to add this to the EditControlBlock. That's the name of the hover-and-lick menu where we want our custom action to appear.

Inside the CustomActions element we have a URL Action element. That simply tells SharePoint what should happen when we click that link. If you notice the Url-attribute it holds two tokens, ItemId and ListId. these tokens will be filled in for us by SharePoint. Tokens are widely used in SharePoint so I wont go into them in detail here, these two should be self-explanatory. Perhaps I will write an article on tokens one day.

Basically, that's it for the feature code. If you are using WSPBuilder you can actually build, deploy and activate this feature and the menu item will appear. Of course, we haven't actually built any code yet, so it will fail miserably. Let's move on.

Step 3: Create the asp.net page to get input from user

Open the SendAsEmail.aspx page from the Layouts folder. Now, I am extremely far from being a designer, and I believe in separating code from design in any case so I'll just make this extremely simple design-wise. There are a few things that we will need to do, though.

First, paste the following code into the aspx-file. Make sure you are in code view and not in design view:

<>
<>

<asp:Content ID="main" runat="server" ContentPlaceHolderID="PlaceHolderMain">

<table>
<tr><td><asp:label runat="server" ID="lblSendTo" Text="Send to:"/></td><td><asp:TextBox runat="server" ID="txtSendTo" /></td></tr>
<tr><td><asp:label runat="server" ID="lblMessage" Text="Message:"/></td><td><asp:TextBox runat="server" ID="txtMessage" TextMode="MultiLine" Rows="5" /></td></tr>
<tr><td><asp:button runat="server" ID="btnSend" Text="Send message" /></td></tr>
</table>

</asp:Content>

Second, get the strong name of your assembly, you need to paste that into where it says [STRONG NAME]. To do so, and I am assuming you are still using WSPBuilder, hit Build (Menu->Build->Build solution). Start up .net Reflector and open your assembly dll, often located in My documents\Visual Studio 2005\Projects\Solutionname\Projectname\bin\debug. At the bottom of reflector you will now see your strong name.

Simply copy the entire strong name, all four parts. Paste this into the code where it says [STRONG NAME].

You may also need to edit the Inherits-attribute of the Page directive. I have written NittiTre.SendAsEmail since that is the namespace and name of the class I will be writing in the next step.

The page itself is fit into the application.master of the SharePoint site. This master page has a contentplaceholder called PlaceHolderMain in which we put a simple table with a few controls with IDs of lblSendTo, lblMessage, btnSend, txtSendTo and txtMessage. You can basically hand this page over to your designer, but make sure that these IDs remain the same. This is important as we will be wiring up these controls in a code-behind file, and if the IDs do not match we get a runtime exception.

Let's move over to the code.

Step 4: Write the class to send the email

Finally it's time to do some coding.

Start by adding a few Using statements to the top to make our code a bit more readable:

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Web.UI;
5
6 using System.Net.Mail;
7 using Microsoft.SharePoint;
8 using Microsoft.SharePoint.WebControls;
9 using System.Web.UI.WebControls;

Second, make sure your class inherits from LayoutsPageBase and add some controls that will have names matching the IDs of the controls we added on the aspx page. We will also add a few variables to hold our mail server configuration:

10
11 namespace NittiTre
12 {
13 public class SendAsEmail : LayoutsPageBase
14 {
15
16 protected Label lblSendTo;
17 protected Label lblMessage;
18 protected Button btnSend;
19
20 protected TextBox txtSendTo;
21 protected TextBox txtMessage;
22
23 private string mailServer = ""; // YOU NEED TO ADD SOMETHING HERE!
24 private int mailPort = 25;
25

Ensure that you add the host name of your SMTP server in line 23.

See line 11 and 13? The namespace and the name of the class makes up what we should put in the aspx file Page inherits directive.

Since we want to have a button with an event handler we need to make sure that all our controls are created before the event handler wireup completes. A good place to do this is in the OnLoad method, so lets override that:

26 protected override void OnLoad(EventArgs e)
27 {
28 EnsureChildControls();
29 }
30

The EnsureChildControls makes sure that CreateChildControls() are called once and only once. If you happen to call EnsureChildControls again later in the code it will not create new child controls thus saving us the trouble of finding out if the controls have been added or not.

If you have ever experience adding event handlers to your controls and having them not fire it is often because you hooked up the event handler too late in the page life cycle. Often, an event handler not firing is because of just that. Simple fix, just call EnsureChildControls in your onload overridden method.

Of course, for CreateChildControls to actually, well, create child controls we need to override that method and make sure we hook up our event handler. I've also added a default text to the message box:

31 protected override void CreateChildControls()
32 {
33 btnSend.Click += new EventHandler(btnSend_Click);
34
35 txtMessage.Text = "Hello, this file is sent from SharePoint";
36 }
37

Now for the bulk of our code, the btnSend_Click method that will fire when someone clicks that button. Notice line 33? That is where we hook it up. Now for the code. I've written inline comments to describe what is going on rather than commenting afterwards.

38 void btnSend_Click(object sender, EventArgs e)
39 {
40 EnsureChildControls(); // Has been called already, but let's make sure...
41
42 // Find the list and item ids from the querystring
43 try
44 {
45 Guid listId = new Guid(Server.UrlDecode(Request.QueryString["ListId"]));
46 int itemId = int.Parse(Request.QueryString["ItemId"]);
47
48 // Find our item from the current web
49 SPWeb web = this.Web;
50 SPListItem item = web.Lists[listId].GetItemById(itemId);
51
52 // Start building our mail message
53 string senderMail = web.CurrentUser.Email;
54 string recipientMail = txtSendTo.Text;
55 MailMessage message = new MailMessage(senderMail, recipientMail);
56 message.Body = txtMessage.Text;
57 message.Subject = item.DisplayName;
58
59 // Add the file as an attachment
60 SPFile file = item.File;
61 Attachment attachment = new Attachment(file.OpenBinaryStream(), file.Name);
62 message.Attachments.Add(attachment);
63
64 // ...and finally try sending
65 SmtpClient smtp = new SmtpClient(mailServer, mailPort);
66 smtp.Send(message);
67 Response.Clear();
68 Response.Redirect(web.Lists[listId].DefaultViewUrl);
69 }
70 catch
71 {
72 throw;
73 }
74 }
75 }
76 }

Most of this code consists of finding information about the item selected and then start building the mail message from that information along with the input from the form.

Note that I have not added much error handling. This is bad and you should add better error handling code, especially around the SmtpClient.Send method call. A lot of things can go wrong when attempting to send an email to another server. Make sure you at least throw any exceptions up to the user so that they get an error message.

If everything goes according to plan, we send the user back to the list in line 68.

That is it. Nothing more. Let's build, deploy and activate. I've uploaded a zipped solution containing everything as written here. You can download that from http://furuknap.googlepages.com/SendAsEmail.zip. Do remember to edit your SMTP Server, that should be the only thing you need to do.

Step 4: Deploy

If you have been wise and paid attention you are using WSPBuilder. If so, right click you project in the Solution Explorer, click WSPBuilder->Build WSP. Next, do the same again, and note that now that you've built the WSP, more options become available in the menu. Click Deploy. Hang around for a while and your solution will be deployed.

Next, you need to activate your feature. Open your SharePoint site and go to Site Settings. Under web features you will find your SendAsEmail feature. Click activate and your document libraries now gets the new feature of sending a document library item as an attachment.

Finally!
Congratulations, you have created a hopefully useful feature. Go ahead, play around with it. Suggestions for improvements may be:

- Implement sending all documents in a folder at once (hint: folders are simply content types and you can limit the edit control box to only apply to certain content types)

- Look up recipients names in an existing contact list to avoid misspelling names

- Send to multiple recipients

- Add more mail related parameters such as Cc, Bcc, encryption, etc.

- Save user preferences for these parameters

Good luck, and let me know how it turns out.

Article Source: http://www.articlemotron.com

Ever wanted to send a SharePoint item by email to someone? No? Well, neither have I. Turns out, someone else did, though, and they did not know how, so I thought I'd help out. And you never know, it might turn out to be you next time, and what will you do then? Now you can just remember that weird Norwegian guy who wrote that thing back in the days and come here to pick up your solution. And, to save you some time, I'll actually upload the entire solution for you, ready to use with just one simple step to do.

Bjørn Furuknap of Norway holds more than 10 MCP titles, including every SharePoint certification from Microsoft. He has worked on SharePoint projects for all the largest companies in Norway as well as having been hired by Microsoft to develop SharePoint solutions. He also writes regularly for SharePoint Magazine and in his SharePoint blog at http://furuknap.blogspot.com/.

Tags:

Please Rate this Article

 

Not yet Rated

Click the XML Icon Above to Receive Computer Articles Via RSS!

© 2006 ArticleMotron All Rights Reserved.
Use of our service is protected by our Privacy Policy and Terms of Service
Hosting by DD&C