首页 > 代码库 > 转:SharePoint2013TimerJob计时器发送邮件

转:SharePoint2013TimerJob计时器发送邮件

 

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

2 我选择“部署为场解决方案”
技术分享

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

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


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.
技术分享

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

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

8 需要override其中的两个函数
override void FeatureDeactivating(SPFeatureReceiverProperties properties) 删除timer job函数
override void FeatureActivated(SPFeatureReceiverProperties properties),部署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”,如图
 
技术分享

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

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

12 看一下我列表上存储的值
技术分享

13 我去收一下我的邮件
技术分享

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 应用程序”,如图
技术分享

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

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

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

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

19 看来它还挺任性的,那么接下来我们就去解决这个问题吧,既然不给用手去抚摸,那我们就下去命令,让它乖乖服从
stsadm -o activatefeature -id 7bff6c03-76ea-40b5-a339-b9fe6bc1c453 -url http://sharepoint2013/ -force
20 id 指的是Feature 的id,点开Feature设计器中的清单,能找到此id 如图
技术分享

21 命令一下,这个世界从此顺心了
技术分享


啦啦啦啦啦,德玛西亚

转:SharePoint2013TimerJob计时器发送邮件