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

坐下来,放松一下,让Sharepoint提醒和跟进您的团队

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2014年7月7日

CPOL

4分钟阅读

viewsIcon

23489

一个.NET实用工具,它会扫描Sharepoint任务列表,并向每个分配有任务的团队成员发送每日摘要式提醒邮件。它可以省去您定期催促团队成员完成任务或提供更新的麻烦。

引言

Sharepoint任务列表是为团队成员记录任务的好地方。但是,一旦您记录并分配了任务,真正的麻烦就开始了。您需要一遍又一遍地提醒您的团队成员他们今天需要做什么,哪些任务已过期,本周有哪些任务等等。这里有一个应用程序,可以为您分担这项繁重的工作,您可以坐下来放松,而它会按照您想要的次数提醒您的团队成员。您的团队成员将收到类似这样的电子邮件,提醒他们分配给他们的任务

电子邮件模板是完全可自定义的。您可以精确定义电子邮件的外观。您还可以包含Sharepoint任务项中的自定义字段显示在电子邮件中。

如何使用

首先,您需要创建一个不错的Sharepoint任务列表。以下是如何操作:

步骤1:创建一个新的任务列表

步骤2:填充任务并分配给您的团队成员

步骤3:获取二进制文件并配置参数

运行DotBits.Configuration并按如下方式配置参数

  • SiteURL - 这是您的sharepoint站点的基础URL,而不是sharepoint列表的URL。
  • Domain - 您的活动目录域。
  • Username - 一个有权访问sharepoint列表的用户。任何用户都可以。代码只需要使用一个有权访问sharepoint列表的用户进行身份验证。
  • Password - 上述sharepoint用户的密码。
  • FromEmail - 发送电子邮件的“发件人”地址。很可能是您,幸运的项目经理。
  • CcEmail - 每封发送的电子邮件都将抄送此地址。很可能是您,幸运的项目经理。
  • ListTitle - 这是您在sharepoint上看到的列表名称。
  • MaxItems - 一次获取的项目数。
  • DueDateFieldName - 这是包含截止日期的列名。
  • AssignedToFieldName - 这是列表中的“分配给”列。
  • FilterFieldName - 这是用于检查哪些项目不需要处理的字段。例如,已完成的任务。
  • FilterFieldValue - 要排除的值。
  • EmaliSubject - 每日提醒电子邮件的主题。{0}将被替换为当前日期。
  • ErrorEmailSubject - 包含提醒应用程序产生的错误的电子邮件主题。
  • ErrorTo - 接收错误电子邮件的收件人。
  • SMTPServer - 在此处放置SMTP服务器名称。例如,smtp.yourcompany.com。Gmail的SMTP服务器将无法工作,因为它使用TLS。
  • SMTPPort - 在此处放置smtp端口。默认是25。

步骤4:安装.NET 4

您需要从这里运行.NET 4设置: http://www.microsoft.com/en-gb/download/details.aspx?id=17851 

步骤5:配置应用程序定期运行

您可以手动运行SharepointListClient.exe。或者,您可以通过Windows计划任务来安排其运行。

首先,启动计划任务并创建一个新任务

在此处,单击“更改用户或组”,然后使用NETWORK SERVICE帐户。只需键入NETWORK SERVICE,然后单击“检查名称”并单击“确定”。

在“触发器”选项卡上,指定您希望何时运行它。例如,这里显示它计划每天运行两次。

在“操作”选项卡上,添加一个运行程序的动作。首先,您需要选择SharepointListClient.exe,**然后您需要复制它前面的内容,即文件所在的文件夹,并将其放在“起始于”框中**。

就是这样!

使用代码

现在,让我们快速浏览一下代码。首先,代码连接到Sharepoint列表

// Starting with ClientContext, the constructor requires a URL to the 
// server running SharePoint. 
using (ClientContext context = new ClientContext(ConfigurationManager.AppSettings["SiteUrl"]))
{
    CredentialCache cc = new CredentialCache();
    NetworkCredential nc = new NetworkCredential(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"], ConfigurationManager.AppSettings["Domain"]);

    cc.Add(new Uri(ConfigurationManager.AppSettings["SiteUrl"]), "Negotiate", nc);
    context.Credentials = cc; 

    Console.WriteLine("Connecting to Sharepoint: {0} ...", ConfigurationManager.AppSettings["SiteUrl"]);                    
    // The SharePoint web at the URL.
    Web web = context.Web;

    // We want to retrieve the web's properties.
    context.Load(web);
    // Execute the query to the server.
    context.ExecuteQuery();
    Console.WriteLine("Connected to Sharepoint...");

一旦成功连接到Sharepoint站点,它将连接到列表并从列表中获取项目

// Get the list properties. We need the EditURL
Console.WriteLine("Getting list: {0}...", ConfigurationManager.AppSettings["ListTitle"]);
var list = web.Lists.GetByTitle(ConfigurationManager.AppSettings["ListTitle"]);
context.Load(list);
context.ExecuteQuery();
var editFormUrl = list.DefaultEditFormUrl;

// Get items from the list that we will loop through and produce the email
Console.WriteLine("Getting items from list: {0}...", ConfigurationManager.AppSettings["ListTitle"]);
// This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll" 
// so that it grabs all list items, regardless of the folder they are in. 
CamlQuery query = CamlQuery.CreateAllItemsQuery(Convert.ToInt32(ConfigurationManager.AppSettings["MaxItems"]));
var items = list.GetItems(query);

// Retrieve all items in the ListItemCollection from List.GetItems(Query). 
context.Load(items);
context.ExecuteQuery();

// This is the Edit URL for each item in the list
var editFormUri = new Uri(new Uri(ConfigurationManager.AppSettings["SiteUrl"]), new Uri(editFormUrl, UriKind.Relative));

现在是时候处理每个项目并决定是将其标记为“已过期”、“今日到期”、“明日到期”还是“本周到期”。首先,我们需要获取每个项目并找到分配的人员及其电子邮件地址。

private static void SendEmailReminder(ClientContext context, ListItemCollection items, string editUrl)
{
    var emailsToSend = new Dictionary<string, Dictionary<int,List<ListItem>>>();

    foreach (var listItem in items)
    {
        // let's use the filter criteria. Eg completed tasks are ignored. 
        var filterValue = (listItem[ConfigurationManager.AppSettings["FilterFieldName"]] ?? string.Empty).ToString();
        if (filterValue != ConfigurationManager.AppSettings["FilterFieldValue"])
        {
            var dueDateString = (listItem[ConfigurationManager.AppSettings["DueDateFieldName"]] ?? string.Empty).ToString();
            var assignedTo = listItem[ConfigurationManager.AppSettings["AssignedToFieldName"]] as FieldLookupValue;
            var email = "";

            // Find the email address of the user from username
            if (assignedTo != null)
            {
                ListItem it = context.Web.SiteUserInfoList.GetItemById(assignedTo.LookupId);

                context.Load(it);
                context.ExecuteQuery();
                email = Convert.ToString(it["EMail"]);
            }

现在我们知道那个人是谁了,我们需要决定这个任务是过期的、即将到期的、未来的还是其他的。

// From the due date, see whether the task is today, tomorrow, overdue etc
DateTime dueDate;
if (DateTime.TryParse(dueDateString, out dueDate) && !string.IsNullOrEmpty(email))
{
    dueDate = dueDate.ToLocalTime();
    if (!emailsToSend.ContainsKey(email))
    {
        emailsToSend.Add(email, new Dictionary<int, List<ListItem>>());
        emailsToSend[email].Add(OVERDUE, new List<ListItem>());
        emailsToSend[email].Add(TODAY, new List<ListItem>());
        emailsToSend[email].Add(TOMORROW, new List<ListItem>());
        emailsToSend[email].Add(THIS_WEEK, new List<ListItem>());
    }

    // Today
    if (dueDate.Date == DateTime.Today.Date)
    {
        emailsToSend[email][TODAY].Add(listItem);
    }
    // Overdue
    else if (dueDate < DateTime.Today.Date)
    {
        emailsToSend[email][OVERDUE].Add(listItem);
    }
    // Tomorrow
    else if (dueDate.Date == DateTime.Today.AddDays(1).Date)
    {
        emailsToSend[email][TOMORROW].Add(listItem);
    }
    // This week
    else if (dueDate.Date <= DateTime.Today.AddDays(7 - (int)DateTime.Today.DayOfWeek).Date)
    {
        emailsToSend[email][THIS_WEEK].Add(listItem);
    }
}

现在我们知道要提醒那个人关于哪些任务了。让我们准备一封电子邮件并发送出去。

// Use the email templates and inject the task reminders inside them
var emailTemplate = System.IO.File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "email_template.html"));
var taskTemplate = System.IO.File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "task_template.html"));
            
var tokens = new Dictionary<string,string>();
tokens.Add("@{TODAY}", DateTime.Today.ToLongDateString());
tokens.Add("@{OVERDUE_TASKS}", ConvertTasksToHtml(taskTemplate, items[OVERDUE], editUrl));
tokens.Add("@{TODAY_TASKS}", ConvertTasksToHtml(taskTemplate, items[TODAY], editUrl));
tokens.Add("@{TOMORROW_TASKS}", ConvertTasksToHtml(taskTemplate, items[TOMORROW], editUrl));
tokens.Add("@{THISWEEK_TASKS}", ConvertTasksToHtml(taskTemplate, items[THIS_WEEK], editUrl));

var subject = string.Format(ConfigurationManager.AppSettings["EmailSubject"], DateTime.Today.ToLongDateString());
var body = ReplaceTokens(emailTemplate, tokens);

var filename = email.Replace('@', '_').Replace('.', '_') + ".html";
System.IO.File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filename), body);

SendEmail(ConfigurationManager.AppSettings["FromEmail"], 
    email,
    ConfigurationManager.AppSettings["CcEmail"],
    subject,
    body);

您可以自己自定义电子邮件模板。有两个HTML文件包含电子邮件模板

第一个是email_template.html,它包含样板文本

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Your daily task reminder</title>
    <style>
        * { font-family: arial, Verdana; }
        h1, h2, h3 { color: dimgrey; margin: 5px; margin-top: 30px; }
        .warning { color: brown; font-size:80% }
        div.task { border-bottom: 1px solid lightgrey; padding: 5px; }
        div.task a { font-weight: bold; line-height: 1.5em }
        div.body { border-left: lightgrey 4px solid; padding-left: 5px; color: gray}
        small {color: gray}
    </style>
</head>
<body>
    <p><i><small>This is an automated alert to remind you of some tasks that you are assigned to. </small></i></p>
        
    <h2>Overdue Tasks</h2>
    <div class="warning">These are overdue. Very bad. Click on the task to provide new ETA.</div>
    @{OVERDUE_TASKS}

    <h2>Today's Tasks</h2>
    <div class="warning">You gotta get these done today. If not, then firstly, shame on you, secondly, provide new ETA.</div>
    @{TODAY_TASKS}

    <h2>Tomorrow's Tasks</h2>    
    @{TOMORROW_TASKS}
    
    <h2>This week's Tasks</h2>
    @{THISWEEK_TASKS}

</body>
</html>

每个任务都来自task_template.html

<div class="task">
    <a href="@{EditUrl}">@{Title}</a> <br />
    <div class="body">
        @{ShortBody}
    </div>
    <small>Due on: @{DueDate}</small>    
</div>

在此模板中,您可以指定Sharepoint列表中的哪些列需要显示在每个任务中。您可以创建自己的列并将该列的数据放在电子邮件中。

有两个特殊列@{EditUrl}和@{ShortBody}是由代码生成的。ShortBody会截取完整的Body/Description字段的前1000个字符。

获取代码

首先,您需要安装.NET 4.5。

http://www.microsoft.com/en-gb/download/details.aspx?id=30653

源代码可在GitHub上获取

https://github.com/oazabir/SharepointTaskReminder

您可以在这里获取该实用工具的二进制文件,只需解压缩,运行DotBits.Configuration,即可开始使用

https://github.com/oazabir/SharepointTaskReminder/blob/master/Binary/SharepointTaskReminder.zip?raw=true

尽情享用!

感谢DotBits提供的精美工具。

© . All rights reserved.