SharePoint 2013 Timer Job 计时器发送邮件

时间:2021-04-22 20:35:49

眼下正好有一个SP项目需要用到计时器功能,本人平常忘性大,所以学一点记录一点,其中参考了不少网络上的好文章,因为怕麻烦,我就不引用看过的博客的链接了,忘各路大神莫怪。 sharepoint 计时器类似于Windows 任务计划一样,可以按分,时,天,周,月去自动执行你布置的任务,你可以到sharepoint 管理中心去查看及更改你的计时规则,值得注意的是,每当你部署一个计时器的时候,你需要到服务器中的“服务”中,有一个叫“SharePoint Timer Service”的服务,你需要重启一下,更新后的计时器才会显效,其余的话不说了,下面就跟我一起去学习此功能吧。

1 添加新项目,打开vs2013‘文件’->‘新建’->‘项目’,我建了一个“OneTimeJob”的空项目

SharePoint 2013 Timer Job 计时器发送邮件

2 我选择“部署为场解决方案”

SharePoint 2013 Timer Job 计时器发送邮件

3 创建一个计时器任务类“OneTimeJob.cs”

SharePoint 2013 Timer Job 计时器发送邮件

4 继承SPJobDefinition ,需要引用Microsoft.SharePoint.Administration; 如下图

SharePoint 2013 Timer Job 计时器发送邮件SharePoint 2013 Timer Job 计时器发送邮件
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
 
namespace OneTimeJob
{
    class OneTimeJob : SPJobDefinition
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public OneTimeJob() : base() { }
        /// <summary>
        /// 带有参数1的构造函数,适合其他的指定站点集,我是猜的,反正我没用过这个
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="service"></param>
        /// <param name="server"></param>
        /// <param name="targetType"></param>
        public OneTimeJob(string jobName, SPService service, SPServer server,  SPJobLockType targetType) : base(jobName, service, server, targetType)
        {
        }
        /// <summary>
        /// 带有参数2的构造函数,适合部署的本站点集
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="webApplication"></param>
        public OneTimeJob(string jobName, SPWebApplication webApplication) : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
        {
            this.Title = jobName;
        }
        /// <summary>
        /// 执行逻辑的方法
        /// </summary>
        /// <param name="contentDbId"></param>
        public override void Execute(Guid contentDbId)
        {
            //我把邮箱地址,和发送内容存储在"TestWeb"网站下的"TestList"的列表上
            string EmailTo = "";
            string EmailBody = "";
            SPWeb web = null;
            SPSecurity.RunWithElevatedPrivileges(delegate()//提升权限,模仿管理员权限在读取列表
            {
                SPWebApplication webApplication = this.Parent as SPWebApplication;//实例化一个应用管理,只能翻译成这样了,将就看吧,反正我都是猜的
                SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];//通过GUID找到内容数据库
                web = contentDb.Sites[0].OpenWeb("/TestWeb/");//因为我只创建了一个站点集,就用Sites[0],然后找到我要的Web
                using (web)
                {
                    SPList list = web.GetList(web.Url + "/Lists/TestList/AllItems.aspx");//找到我要的列表
                    SPQuery query = new SPQuery();
                    query.Query = "";//为空时表示搜出所有列表,caml语句不在此讲解
                    SPListItemCollection items = list.GetItems(query);
                    if (items != null && items.Count > 0)
                    {
                        foreach (SPListItem item in items)
                        {
                            if (Convert.ToString(item["Title"]) == "测试用计时器发邮件") //找到我存储字段值的地方
                            {
                                EmailTo = Convert.ToString(item["EmailTo"]);
                                EmailBody = Convert.ToString(item["EmailBody"]);
                            }
                        }
                    }
                }
                //接下来就是发送邮件了,我得先吐槽一下,sharepoint自带了一个发送邮件功能,叫"Microsoft.SharePoint.Utilities.SPUtility.SendEmail()",
                //我曾经用它发送了一个html邮件,内容多时,总有一个字符解析乱码,太NM坑了,有兄弟有解决路子的,别忘分享给我啊,所以我还是用成熟一点的技术来发送邮件。
                SendEmail(EmailTo, "测试计时器发送的邮件", EmailBody, "");
            });
        }
        /// <summary>
        /// 发送邮件
        /// </summary>
        /// <param name="mailTo">要发送的邮箱</param>
        /// <param name="mailSubject">邮箱主题</param>
        /// <param name="mailContent">邮箱内容</param>
        /// <returns>返回发送邮箱的结果</returns>
        public  bool SendEmail(string mailTO, string mailSubject, string mailContent, string _path)
        {
            // 设置发送方的邮件信息,例如使用网易的smtp
            string smtpServer = "192.168.1.1"; //SMTP服务器
            string mailFrom = "黑不到我吧"; //登陆用户名
            string userPassword = "119";//登陆密码
            // 邮件服务设置
            SmtpClient smtpClient = new SmtpClient();
            smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;//指定电子邮件发送方式
            smtpClient.Host = smtpServer; //指定SMTP服务器
            smtpClient.Credentials = new System.Net.NetworkCredential(mailFrom, userPassword);//用户名和密码
            // 发送邮件设置        
            MailMessage mailMessage = new MailMessage(); // 发送人和收件人
            mailMessage.From = new MailAddress(mailFrom, "测试站点");
            mailMessage.To.Add(new MailAddress(mailTO, mailTO));//添加发件人
            mailMessage.Subject = mailSubject;//主题
            mailMessage.Body = mailContent;//内容
            mailMessage.BodyEncoding = Encoding.UTF8;//正文编码
            mailMessage.IsBodyHtml = true;//设置为HTML格式,可以发送html内容的邮件
            mailMessage.Priority = MailPriority.High;//优先级
            //添加邮件附件
            FileInfo fi;
            if (!string.IsNullOrEmpty(_path))
            {
                fi = new FileInfo(_path);
                if (fi.Exists)
                {
                    System.Net.Mail.Attachment firstatt = new System.Net.Mail.Attachment(_path, System.Net.Mime.MediaTypeNames.Application.Octet);
                    System.Net.Mime.ContentDisposition disposion = new System.Net.Mime.ContentDisposition();
                    disposion.CreationDate = System.IO.File.GetCreationTime(_path);
                    disposion.ModificationDate = System.IO.File.GetLastWriteTime(_path);
                    disposion.ReadDate = System.IO.File.GetLastAccessTime(_path);
                    mailMessage.Attachments.Add(firstatt);
                }
            }
            try
            {
                smtpClient.Send(mailMessage); // 发送邮件
                return true;
            }
            catch (SmtpException ex)
            {
                return false;
            }
        }
    }
}
 
View Code

 

5 在Features 文件夹中添加功能,创建一个 Feature 文件,范围选择“Site”,表示你的计时器作用在部署的网站集上,在存取列表值的时候我们一般会通过Site,筛选你要的Web,再通过Web筛选到与你要交互的list.

SharePoint 2013 Timer Job 计时器发送邮件

6 给新建的Feature添加一个事件接收器,如下图:

SharePoint 2013 Timer Job 计时器发送邮件

7 添加后,会在其文件下面多出一个“Feature1.EventReceiver.cs”的类文件

SharePoint 2013 Timer Job 计时器发送邮件

8 需要override其中的两个函数

override void FeatureDeactivating(SPFeatureReceiverProperties properties) 删除timer job函数

override void FeatureActivated(SPFeatureReceiverProperties properties),部署timer job函数

SharePoint 2013 Timer Job 计时器发送邮件SharePoint 2013 Timer Job 计时器发送邮件
namespace OneTimeJob.Features.Feature1
{
    /// <summary>
    /// 此类用于处理在激活、停用、安装、卸载和升级功能的过程中引发的事件。
    /// </summary>
    /// <remarks>
    /// 附加到此类的 GUID 可能会在打包期间使用,不应进行修改。
    /// </remarks>
    [Guid("ed228c48-b397-4755-be4f-a9ffa609c177")]
    public class Feature1EventReceiver : SPFeatureReceiver
    {
        // 取消对以下方法的注释,以便处理激活某个功能后引发的事件。
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            //实例化对应的站点集
            SPSite site = properties.Feature.Parent as SPSite;
            string Job_Name = "OneTimeJobTest";//指定计时器名称
            //遍历此站点集下的所有计时器,如果发现重名的将删除,确保计时器名称的唯一性
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
                if (job.Name == Job_Name)//匹兑到部署时的计时器名称,然后删除
                {
                    job.Delete();
                }
            }
            //添加计时器
            OneTimeJob Doc = new OneTimeJob (Job_Name, site.WebApplication);//实例化任务类
            //设置计时器属性,这个可以发布后在sharepoint管理器中的"监控"中重新定义。
            SPMinuteSchedule schedule = new SPMinuteSchedule();
            schedule.BeginSecond = 0;
            schedule.EndSecond = 59;
            schedule.Interval = 5;
            Doc.Schedule = schedule;
            Doc.Update();
        }
 
        // 取消对以下方法的注释,以便处理在停用某个功能前引发的事件。
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            //实例化对应的站点集
            SPSite site = properties.Feature.Parent as SPSite;
            //遍历此站点集下的所有计时器
            foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
            {
               if (job.Name == "OneTimeJobTest")//匹兑到部署时的计时器名称,然后删除,为了方便理解,计时器名称我没用全局变量
               {
                   job.Delete();
               }
            }
        }
 
        // 取消对以下方法的注释,以便处理在安装某个功能后引发的事件。
        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}
 
        // 取消对以下方法的注释,以便处理在卸载某个功能前引发的事件。
        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}
        // 取消对以下方法的注释,以便处理在升级某个功能时引发的事件。
        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}
    }
}
View Code

9 此时计时器已经写好了,我们可以部署了,部署之后,打开服务器的“服务”,重启“SharePoint Time Service”,如图

 SharePoint 2013 Timer Job 计时器发送邮件

10 “sharepoint 管理中心”的“监控”->“计时器作业”->"复查作业定义",可以看到我们的计时器

SharePoint 2013 Timer Job 计时器发送邮件

11 点击进去后,你可以重新定义计时器的属性

SharePoint 2013 Timer Job 计时器发送邮件

12 看一下我列表上存储的值

SharePoint 2013 Timer Job 计时器发送邮件

13 我去收一下我的邮件

SharePoint 2013 Timer Job 计时器发送邮件

 

14 下面我们来讲一下部署,用VS可以直接部署成功,但是我们的生产环境中,特别是客户的生产环境中,一般不会去装VS,所以我们会用选用wsp文件去部署,

通常情况,我们第一步先用命令安装wsp文件包,如:stsadm -o addsolution -filename C:\OneTimeJob.wsp

然后我们再部署此wsp,如:stsadm -o deploysolution -name OneTimeJob.wsp -immediate -url  http://sharepoint2013/ -allowGacDeployment

那么问题来了,报错啦,显示“此解决方案不包含 Web 应用程序范围的资源,无法将其部署到特
定的 Web 应用程序”,如图

SharePoint 2013 Timer Job 计时器发送邮件

 

 

15 哈哈,蛋疼了吧,它不按规则出牌了,那我们来找下原因,我们打开“sharepoint管理器”找到此wsp包,如图

SharePoint 2013 Timer Job 计时器发送邮件

16 “包含Web应用程序资源”为“否”,跟以前不一样了吧,这种情况我们只能“全局部署”,网上有很多坑,好不容易找到正确的命令:stsadm -o deploysolution -name OneTimeJob.wsp   -local -allowGacDeployment,部署后如图

SharePoint 2013 Timer Job 计时器发送邮件

 

17 因为是全局部署,所以每个网站集都包含此Feature,所以我们要去对应的网站中“网站集功能”中激活此Feature,如图

SharePoint 2013 Timer Job 计时器发送邮件

18 点击激活,发现:擦,又报错了,又掉下来一个坑,如图

SharePoint 2013 Timer Job 计时器发送邮件

19 看来它还挺任性的,那么接下来我们就去解决这个问题吧,既然不给用手去抚摸,那我们就下去命令,让它乖乖服从

stsadm -o activatefeature -id 7bff6c03-76ea-40b5-a339-b9fe6bc1c453 -url http://sharepoint2013/ -force

20 id 指的是Feature 的id,点开Feature设计器中的清单,能找到此id 如图

SharePoint 2013 Timer Job 计时器发送邮件

21 命令一下,这个世界从此顺心了

SharePoint 2013 Timer Job 计时器发送邮件

啦啦啦啦啦,德玛西亚