65.9K
CodeProject 正在变化。 阅读更多。
Home

利用 Outlook 2010 加载项将电子邮件附件复制到 SharePoint

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012年3月16日

Apache

2分钟阅读

viewsIcon

21789

本文提供了一种快速方法,用于循环遍历单个电子邮件消息中的所有附件并将其上传到 SharePoint 2007 或 2010。

引言

一种将附件从 Outlook 2010 插件保存到 SharePoint 2010 的快速方法。(请注意,我正在成功地将此代码与 SharePoint 2007 一起使用,尽管它不受支持。) 

使用代码 

我的示例从 Microsoft Ribbon 示例开始。这允许您轻松地为电子邮件项目添加右键单击事件。请从 Microsoft 下载并从这个 ribbon 示例开始:http://msdn.microsoft.com/en-us/library/ee692172.aspx。您还需要 SharePoint foundation 客户端对象模型 DLL:http://www.microsoft.com/download/en/details.aspx?id=21786

这篇文章向您展示了如何从您的解决方案中正确引用它:http://msdn.microsoft.com/en-us/library/ee857094.aspx#SP2010ClientOM_Using_the_Managed_Client_Object_Model。DLL 的安装位置如下:C:\Program Files\Common Files\microsoft shared\SharePoint Client\Microsoft.SharePoint.Client.dll

现在!终于,我的内容了…

按照以下方式修改 explorer.xml 文件以启用右键单击事件。您可以添加任意数量的按钮,非常酷。我留下了一个子菜单和一个辅助按钮作为如何操作的示例。

<contextMenus>
    <contextMenu idMso="ContextMenuMailItem">
      <menuSeparator id="MySeparator" />
      <menu id="MySubMenu" label="submenu">
        <button id="MyContextMenuMailItem4"
           label="Attachment to Sharepoint" 
           onAction="LaunchAttachUp"/>
        <button id="MyContextMenuMailItem5"
           label="Meeting Invite"
           onAction="CreateMeeting"/>
     </menu>
   </contextMenu>
</contextMenus> 

现在打开 RibbonXAddin.cs 并添加 LaunchAttachUp 方法。请注意,我正在验证上下文。这实际上所做的是确定您右键单击的特定电子邮件,然后调用上传到 SharePoint 的函数。请注意,对于此示例,我有一个固定的站点。如果您在“共享文档”库中有一个子文件夹,您会将它添加到该行的末尾,如下所示:/sites/YOURSITENAME/Shared Documents/subfolder1/subsubfolder/

public void LaunchAttachUp(Office.IRibbonControl control)
{
    if (control.Context is Outlook.Selection)
    {
        Outlook.Selection selection =
            control.Context as Outlook.Selection;
        if (selection.Count == 1)
        {
            if (selection[1] is Outlook.MailItem)
            {
                Outlook.MailItem oMail = selection[1] as Outlook.MailItem;
                ShareAttach sa = new ShareAttach();
                sa.AttachmentSharepoint(oMail, "http://SITEURLFORSHAREPOINT.COM", 
                             "/sites/YOURSITENAME/Shared Documents/");
            }
        }
    }
}

现在上述代码调用以下内容

using Outlook = Microsoft.Office.Interop.Outlook;
using System.Runtime.InteropServices;
using System.Collections;
using Microsoft.SharePoint.Client;
// The following directive avoids ambiguity between the
// System.IO.File class and Microsoft.SharePoint.Client.File class.
using ClientOM = Microsoft.SharePoint.Client;
using System.IO;
using System.Net;

// below is populated when ATTACH_BY_VALUE for PR_ATTACH_METHOD
const string PR_ATTACH_DATA_BIN = "http://schemas.microsoft.com/mapi/proptag/0x37010102";

// P_LONG..  
const string PR_ATTACH_METHOD = "http://schemas.microsoft.com/mapi/proptag/0x37050003";

// below is populated when ATTACH_EMBEDDED_MSG is for PR_Attach_method
const string PR_ATTACH_DATA_OBJ = "http://schemas.microsoft.com/mapi/proptag/0x3701000D";

public void AttachmentSharepoint(Outlook.MailItem mailItem, 
           string clientContextURL, string sitelibfolder)
{
    if (mailItem != null)
    {
        var attachments = mailItem.Attachments;
        foreach (Outlook.Attachment attachment in attachments)
        {
            // first look at PR_ATTACH_METHOD then determine which property to use.
            var attachtypevar = attachment.PropertyAccessor.GetProperty(PR_ATTACH_METHOD);
            int attachtype = Convert.ToInt32(attachtypevar);
            byte[] attachmentData = null;
            if (attachtype == 1)
            {
               // this is a standard object
               attachmentData = 
                 attachment.PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN) as byte[];

               // pop into memory stream, as the sharepoint object requires that.
               MemoryStream theMemStream = new MemoryStream();
               theMemStream.Write(attachmentData, 0, attachmentData.Length);
               theMemStream.Position = 0;
               try
               {
                   bool overwrite = false;

                   ClientContext clientContext = new ClientContext(clientContextURL);
                   using (theMemStream)
                       ClientOM.File.SaveBinaryDirect(clientContext, sitelibfolder + 
                       attachment.FileName, theMemStream, overwrite);
               }
               catch (Exception ex)
               {
                   MessageBox.Show("Sharepoint URL issues.  " + ex.Message);
               }
            }
            else if (attachtype == 5)
            {
                // this is embedded email , so we can't use BIN.
                // currently the below is not supported per Microsoft.
                // Work around would be to save to disk (eww)
                //  object mi = attachment.PropertyAccessor.GetProperty(PR_ATTACH_DATA_OBJ);
                //  var attachmentDatamsg = attachment.PropertyAccessor.GetProperty(PR_ATTACH_DATA_OBJ);
                MessageBox.Show(attachment.FileName + 
                  " - is not a supported attachment format for auto-upload.");
            }
        }
    }
}

因此,使用场景如下。用户打开 Outlook 并在主 Outlook 资源管理器的邮件视图中。您会右键单击一封电子邮件,并看到您的自定义按钮,您已在 XML 中添加了该按钮,它会显示“附件到 SharePoint”。然后,它会将该特定电子邮件消息上的所有附件上传到代码中指定的 SharePoint 实例。

关注点

此方法适用于所有文件类型,但嵌入式电子邮件除外,即,我有一封带有四个附件的电子邮件,其中三个是 zip、xls、doc,但第四个是 .msg.msg 不起作用。您可以围绕这个问题进行编码,但我的实现仅识别它是 .msg,它实际上不会将其弹出到 SharePoint。

这是我正在进行的一个更大项目的功能。我有一个对话扫描器、自定义分类/属性电子邮件标记功能(具有对类及其属性的完全搜索!)、基于电子邮件收件人/抄送人员的快速约会设置等。

我简化了我的实现以用于此示例。我的版本实际上会弹出一个小的 Windows 窗体,其中包含持久化的 SharePoint 站点(因此您不必每次都输入它们)。它将它们持久化到隐藏的存储项中。我将提供一个保存数据到/从该存储项的示例作为补充。但是,您不需要下面的代码来使用我的上述示例。

private void AddtoStorage(string storageIdentifier, string storageContent)
{
    if (!String.IsNullOrEmpty(storageIdentifier) && !String.IsNullOrEmpty(storageContent))
    {
        Outlook.MAPIFolder folder = Globals.ThisAddIn.Application.GetNamespace(
                "MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
        Outlook.StorageItem storageitem = folder.GetStorage(storageIdentifier, 
                Outlook.OlStorageIdentifierType.olIdentifyBySubject);
        storageitem.Body = storageContent;
        storageitem.Save();
    }
}

private string GetfromStorage(string storageIdentifier)
{
    if (!String.IsNullOrEmpty(storageIdentifier))
    {
        Outlook.MAPIFolder folder = Globals.ThisAddIn.Application.GetNamespace(
                "MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
        Outlook.StorageItem storageitem = folder.GetStorage(storageIdentifier, 
                Outlook.OlStorageIdentifierType.olIdentifyBySubject);
        try
        {
            string bodycontent = storageitem.Body.ToString();
            return bodycontent;
        }
        catch (Exception e)
        {
            return "";
        }
    }
    else
    {
        return "";
    }
}

历史 

SharePoint 上传示例,日期为 3 月 15 日。删除了此示例不需要的两个代码行,并实际上使其对于此实现不正确。清理了标题。明确了 Foundation 针对 2010 而不是 2007。

© . All rights reserved.