My firewall is blocking kusek's link but I'm sure that's the place to go. Coincidentally I was just developing this yesterday so can share the highlights.
Feature file
This custom action feature adds a menu option to all document libraries. Adjust the content type if you need to restrict this to only certain documents.
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="OpenInMailClient"
RegistrationType="ContentType"
RegistrationId="0x0101"
Location="EditControlBlock"
Sequence="500"
ImageUrl="/_layouts/images/iceml.gif"
Title="Send As Attachment">
<UrlAction Url="~site/_layouts/Custom/SendMail.aspx?ItemId={ItemId}&ListId={ListId}" />
</CustomAction>
</Elements>
Application page
I developed an application page used Karine Bosch's excellent reference of SharePoint controls to design and create the application page so it looked nice and 'SharePointy'. I also used a rich HTML box so the user could enter rich text into the body which seems to be working nicely.
Sending the message
This is pretty standard .NET. The only semi-cool part is using the outgoing mail server set in SharePoint to send the message. Note that there is a method to send mail in the SharePoint API but it doesn't seem to support attachments and I couldn't see the benefit of using it.
// Prepare message
MailMessage message = new MailMessage
{
Subject = txtSubject.Text,
Body = txtBody.Text,
IsBodyHtml = true,
From = new MailAddress(txtFromAddress.Text)
};
message.To.Add(txtToAddress.Text);
if (!String.IsNullOrEmpty(txtCCAddress.Text))
message.CC.Add(txtCCAddress.Text);
message.Bcc.Add(txtBCCAddress.Text);
// Prepare attachment
Stream stream = chosenItem.File.OpenBinaryStream();
Attachment attachment = new Attachment(stream, chosenItem.Name, "application/octet-stream");
message.Attachments.Add(attachment);
// Send message
string server = SPContext.Current.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
SmtpClient client = new SmtpClient(server);
client.Send(message);
// Clean up
stream.Dispose();
attachment.Dispose();
message.Dispose();