// 开始发件 public Task Run(Stack <SendItem> sendItems) { // 创建线程 Task task = Task.Run(async() => { while (sendItems.Count > 0) { // 开始并行发送 //确定smtp服务器地址 实例化一个Smtp客户端 SmtpClient smtpclient = new SmtpClient(); smtpclient.Host = _sendBox.smtp; //smtpClient.Port = "";//qq邮箱可以不用端口 //邮件发送方式 通过网络发送到smtp服务器 smtpclient.DeliveryMethod = SmtpDeliveryMethod.Network; //如果服务器支持安全连接,则将安全连接设为true smtpclient.EnableSsl = true; // 获取发件箱 var sendItem = sendItems.Pop(); var mailMessage = await GenerateMailMessage(sendItem); try { //是否使用默认凭据,若为false,则使用自定义的证书,就是下面的networkCredential实例对象 smtpclient.UseDefaultCredentials = false; //指定邮箱账号和密码,需要注意的是,这个密码是你在QQ邮箱设置里开启服务的时候给你的那个授权码 NetworkCredential networkCredential = new NetworkCredential(_sendBox.email, _sendBox.password); smtpclient.Credentials = networkCredential; //发送邮件 smtpclient.Send(mailMessage); // 发送成功后,更新数据,更新到数据库 sendItem.senderEmail = _sendBox.email; sendItem.senderName = _sendBox.userName; sendItem.isSent = true; sendItem.sendMessage = "邮件送达"; sendItem.sendDate = DateTime.Now; _liteDb.Upsert(sendItem); // 更新到当前进度中 SendCompleted?.Invoke(new SendResult() { SendBox = _sendBox, SendItem = sendItem, IsSent = true, }); // 保存成功的发件量 if (!_sendBox.IncreaseSentCount(_liteDb, _setting)) { // 直接退出 return; } } catch (Exception ex) { // 超过最大尝试次数就退出 if (sendItem.tryCount > 5) { // 此时也要更新进度 SendCompleted?.Invoke(new SendResult() { SendBox = _sendBox, SendItem = sendItem, IsSent = false }); } else if (_setting.isAutoResend) // 重新发送时,才重新推入栈中 { // 更新状态 sendItem.tryCount++; sendItem.isSent = false; // 重新推入栈中 sendItems.Push(sendItem); } // 添加失败原因 if (ex.InnerException == null) { sendItem.sendMessage = ex.Message; } else { sendItem.sendMessage = ex.InnerException.Message; } _liteDb.Upsert(sendItem); // 标记当前邮件失败次数 // 要等数据处理保存后,再更新 IncreaseFailure(); } finally { // 每次发送完成,要等待一会儿再发送 double sleep = new Random().NextDouble() * 3 + 2; if (_setting != null) { sleep = _setting.sendInterval_min + new Random().NextDouble() * (_setting.sendInterval_max - _setting.sendInterval_min); } // 线程暂停 Thread.Sleep((int)(sleep * 1000)); } } }, _cancellationTokenSource.Token); return(task); }