/// <summary> /// 获取待发邮件列表 /// </summary> private void GetWaitSendMail() { List <UserMailViewEntity> mailList; if (mailQueue.Count == 0 && !IsExistsMailCacheName()) { lock (obj) { if (mailQueue.Count == 0 && !IsExistsMailCacheName()) { LogUtilExpand.WriteLog("尝试从数据库提取待发邮件列表..."); mailList = bllMail.QueryViewWaitSendMailList(); if (mailList != null) { LogUtilExpand.WriteLog("从数据库取出" + mailList.Count + "封发邮件,成功放入邮件发送队列"); foreach (UserMailViewEntity entity in mailList) { mailQueue.Enqueue(entity); } } else { LogUtilExpand.WriteLog("从数据库取出0封邮件"); SetAbsoluteExpirationCache(cacheTimeoutName, 1, cacheTimeoutMinute); } } } } }
/// <summary> /// 停止发送邮件 /// </summary> public void Stop() { int stopThreadNum = 0; if (mailSendThread != null && cts != null) { LogUtilExpand.WriteLog("邮件服务尝试终止..."); cts.Cancel(); for (int loop = 0; loop < mailSendThread.Length; loop++) { try { mailSendThread[loop].Wait(); } catch (AggregateException ex) { ex.Handle(e => e is OperationCanceledException); LogUtilExpand.WriteLog("线程" + (loop + 1) + "成功终止"); stopThreadNum++; } catch (Exception ex) { LogUtilExpand.WriteLog("线程" + (loop + 1) + "终止失败(失败原因如下:)"); LogUtilExpand.WriteLog(ex); } } if (successMailNum > 0) { LogUtilExpand.WriteLog("邮件服务程序在终止前成功发送" + successMailNum + "封邮件"); } if (stopThreadNum == mailSendThread.Length) { mailSendThread = null; cts = null; successMailNum = 0; LogUtilExpand.WriteLog("线程已全部终止"); } else { LogUtilExpand.WriteLog("成功终止" + stopThreadNum + "个线程,但有" + (mailSendThread.Length - stopThreadNum) + "个线程终止失败"); } } }
/// <summary> /// 发送邮件方法 /// </summary> /// <param name="ct"></param> /// <param name="threadNum"></param> /// <returns></returns> private void StartSendEmail(CancellationToken ct, int threadNum) { UserMailViewEntity mailEntity; while (true) { if (ct.IsCancellationRequested) { ct.ThrowIfCancellationRequested(); } else { //如果邮件队列为空,休眠指定时间,尝试获取邮件列表 if (mailQueue.Count == 0) { if (successMailNum > 0) { int count = successMailNum; Interlocked.Add(ref successMailNum, -count); LogUtilExpand.WriteLog("邮件服务程序成功发送" + count + "封邮件"); } //写这么多,主要是终止服务时,尽可能早的检测到 if (ct.IsCancellationRequested) { ct.ThrowIfCancellationRequested(); } Thread.Sleep(sendIntervalMinute); if (ct.IsCancellationRequested) { ct.ThrowIfCancellationRequested(); } GetWaitSendMail(); } if (ct.IsCancellationRequested) { ct.ThrowIfCancellationRequested(); } if (mailQueue.TryDequeue(out mailEntity)) { SendMailMessage(mailEntity, companyEmailAccountList[threadNum]); } } } }
/// <summary> /// 开始发送邮件 /// </summary> public void Start() { try { if (mailSendThread == null && cts == null) { InitMailThread(); } for (int loop = 0; loop < mailSendThread.Length; loop++) { if (mailSendThread[loop].Status == TaskStatus.Created) { mailSendThread[loop].Start(); LogUtilExpand.WriteLog("线程" + (loop + 1) + "开始启动"); } } } catch (Exception ex) { LogUtilExpand.WriteLog("邮件服务启动失败(异常信息如下)"); LogUtilExpand.WriteLog(ex.Message); } }
/// <summary> /// 初始化邮件发送线程 /// </summary> private void InitMailThread() { List <CompanyEmailAccountEntity> emailAccountList = this.GetCompanyEmailAccountList(); companyEmailAccountList = emailAccountList; if (emailAccountList != null) { cts = new CancellationTokenSource(); int looptimes = emailAccountList.Count; mailSendThread = new Task[looptimes]; for (int loop = 0; loop < looptimes; loop++) { mailSendThread[loop] = new Task(() => StartSendEmail(cts.Token, 1), cts.Token); } LogUtilExpand.WriteLog("从数据库获取" + emailAccountList.Count + "个公司邮箱账号,接下来将开启" + emailAccountList.Count + "个邮件发送线程," + (sendIntervalMinute / 60 / 1000) + "分钟后将开始发送邮件"); } else { LogUtilExpand.WriteLog("(异常):未设置公司邮箱账号"); } }
protected override void OnStop() { mailMgt.Stop(); LogUtilExpand.WriteLog("==============================邮件服务日志终止==============================="); LogUtil.WriteLog(""); }
protected override void OnStart(string[] args) { LogUtilExpand.WriteLog("==============================邮件服务日志启动==============================="); mailMgt.Start(); }
/// <summary> /// 发送邮件 /// </summary> /// <param name="content"></param> /// <param name="attachmentPath"></param> /// <param name="email"></param> public void SendMailMessage(UserMailViewEntity mailEntity, CompanyEmailAccountEntity emailAccountEntity) { string remark = string.Empty; #region 发送前错误判断 (提前判断错误,会很大提升性能) if (string.IsNullOrEmpty(mailEntity.EMail)) { remark = "当前用户没有填写邮箱"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendFail); return; } if (!mailFormatReg.IsMatch(mailEntity.EMail)) { remark = "当前用户邮箱格式错误"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendFail); return; } if (string.IsNullOrEmpty(mailEntity.BookListPath)) { remark = "当前所属文章附件没有设置文件路径"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendFail); return; } #endregion MailMessage message = null; SmtpClient client = null; Attachment myAttachment = null; try { //设置 收件人和发件人地址 MailAddress from = new MailAddress(emailAccountEntity.EmailName, sendName); MailAddress to = new MailAddress(mailEntity.EMail, mailEntity.LoginName); message = new MailMessage(from, to); string attachPath = attachDomain + mailEntity.BookListPath; if (File.Exists(attachPath)) { FileInfo fileInfo = new FileInfo(attachPath); myAttachment = new Attachment(attachPath, MediaTypeNames.Application.Octet); //MIME协议下的一个对象,用以设置附件的创建时间,修改时间以及读取时间 System.Net.Mime.ContentDisposition disposition = myAttachment.ContentDisposition; disposition.CreationDate = File.GetCreationTime(attachPath); disposition.ModificationDate = File.GetLastWriteTime(attachPath); disposition.ReadDate = File.GetLastAccessTime(attachPath); disposition.FileName = fileInfo.Name;; } else { remark = "该附件存在"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendFail); return; } message.Attachments.Add(myAttachment); message.Subject = "开卷网络附带书单"; message.Body = "书单测试主体"; message.BodyEncoding = Encoding.GetEncoding("gb2312"); message.IsBodyHtml = true; message.Priority = MailPriority.High; client = new SmtpClient(); client.Timeout = 100000; client.Host = emailAccountEntity.EmailSMTPHost; client.UseDefaultCredentials = false; client.Credentials = new NetworkCredential(emailAccountEntity.EmailName, emailAccountEntity.EmailPassword); client.DeliveryMethod = SmtpDeliveryMethod.Network; client.Send(message); remark = "发送成功"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendSuccess); Interlocked.Increment(ref successMailNum); } catch (Exception ex) { remark = "发送失败"; bllMail.UpdateSendStatus(mailEntity.MailID, remark, UserMailStatus.SendFail); LogUtilExpand.WriteLog("邮件ID:" + mailEntity.MailID + "发送失败(异常信息如下:)"); LogUtilExpand.WriteLog(ex); if (message != null) { message.Dispose(); } if (client != null) { client.Dispose(); } } }