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





5.00/5 (2投票s)
一个.NET实用工具,它会扫描Sharepoint任务列表,并向每个分配有任务的团队成员发送每日摘要式提醒邮件。它可以省去您定期催促团队成员完成任务或提供更新的麻烦。
引言
Sharepoint任务列表是为团队成员记录任务的好地方。但是,一旦您记录并分配了任务,真正的麻烦就开始了。您需要一遍又一遍地提醒您的团队成员他们今天需要做什么,哪些任务已过期,本周有哪些任务等等。这里有一个应用程序,可以为您分担这项繁重的工作,您可以坐下来放松,而它会按照您想要的次数提醒您的团队成员。您的团队成员将收到类似这样的电子邮件,提醒他们分配给他们的任务
电子邮件模板是完全可自定义的。您可以精确定义电子邮件的外观。您还可以包含Sharepoint任务项中的自定义字段显示在电子邮件中。
- 源代码: https://github.com/oazabir/SharepointTaskReminder
- 二进制文件: https://github.com/oazabir/SharepointTaskReminder/blob/master/Binary/SharepointTaskReminder.zip?raw=true
- 先决条件: .NET 4.5
如何使用
首先,您需要创建一个不错的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,即可开始使用
尽情享用!
感谢DotBits提供的精美工具。