前言
之前介绍的友情链接功能,只实现了友情链接的展示和管理接口。
还缺失友情链接申请、审核管理、通知,现在把这块功能补全。
Model 什么的之前那篇文章都有,本文直接补全逻辑代码~
详见: 基于.NetCore开发博客项目 StarBlog - (13) 加入友情链接功能
先看效果
友情链接申请页面
邮件通知
实现一个简单的通知功能,申请通过之后,给申请友链的邮箱发通知。
使用 MimeKit 这个库可以很方便的实现发邮件功能
为了更方便使用,我封装了一个 EmailUtils
放在 StarBlog.Share.Utils
里面
public class EmailAccountConfig {
public string Host { get; set; }
public int Port { get; set; }
public string FromUsername { get; set; }
public string FromPassword { get; set; }
public string FromAddress { get; set; }
}
public static class EmailUtils {
public static async Task SendEmailAsync(
EmailAccountConfig config,
string subject,
string htmlBody,
string toName,
string toAddress,
string fromName = "StarBlog"
) {
return await SendEmailAsync(
config,
new MimeMessage {
Subject = subject,
From = {new MailboxAddress(fromName, config.FromAddress)},
To = {new MailboxAddress(toName, toAddress)},
Body = new BodyBuilder {
HtmlBody = htmlBody
}.ToMessageBody()
}
);
}
public static async Task SendEmailAsync(EmailAccountConfig config, MimeMessage message,
HttpProxyClient? proxyClient = null) {
MessageSentEventArgs result = null;
using var client = new SmtpClient {
ServerCertificateValidationCallback = (s, c, h, e) => true,
};
if (proxyClient != null) {
client.ProxyClient = proxyClient;
}
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.MessageSent += (sender, args) => { result = args; };
await client.ConnectAsync(config.Host, config.Port, SecureSocketOptions.Auto);
await client.AuthenticateAsync(config.FromUsername, config.FromPassword);
await client.SendAsync(message);
await client.DisconnectAsync(true);
return result;
}
}
使用比较简单,传入邮箱配置和邮件主题、内容、收件地址就行。
具体的可以接着看下面的代码。
友链申请管理
管理友情链接申请记录的逻辑,同样也是有增删改查,这部分代码跟上面的一样,省略了
构造方法通过依赖注入,从配置系统里读取了邮箱配置,读者可以自行将邮箱配置添加到 appsettings.json
中,这里给出一个outlook邮箱的配置
"EmailAccountConfig": {
"Host": "smtp-mail.outlook.com",
"Port": 587,
"FromUsername": "邮箱地址@outlook.com",
"FromPassword": "邮箱密码",
"FromAddress": "邮箱地址@outlook.com"
}
下面开始是 service 的代码
这里只贴设置是否验证 和 发邮件通知 的代码
public class LinkExchangeService {
private readonly IBaseRepository _repo;
private readonly LinkService _linkService;
private readonly EmailAccountConfig _emailAccountConfig;
public LinkExchangeService(IBaseRepository repo, LinkService linkService, IOptions options) {
_repo = repo;
_linkService = linkService;
_emailAccountConfig = options.Value;
}
public async Task SetVerifyStatus(int id, bool status, string? reason = null) {
var item = await GetById(id);
if (item == null) return null;
item.Verified = status;
item.Reason = reason;
await _repo.UpdateAsync(item);
var link = await _linkService.GetByName(item.Name);
if (status) {
await SendEmailOnAccept(item);
if (link == null) {
await _linkService.AddOrUpdate(new Link {
Name = item.Name,
Description = item.Description,
Url = item.Url,
Visible = true
});
}
else {
await _linkService.SetVisibility(link.Id, true);
}
}
else {
await SendEmailOnReject(item);
if (link != null) await _linkService.DeleteById(link.Id);
}
return await GetById(id);
}
// 本文仅贴上申请通过的代码,其他的也是类似的写法
public async Task SendEmailOnAccept(LinkExchange item) {
const string starblogLink = "StarBlog";
var sb = new StringBuilder();
sb.AppendLine($"您好,友链申请已通过!感谢支持,欢迎互访哦~
");
sb.AppendLine($"");
sb.AppendLine($"以下是您申请的友链信息:
");
sb.AppendLine($"网站名称:{item.Name}
");
sb.AppendLine($"介绍:{item.Description}
");
sb.AppendLine($"网址:{item.Url}
");
sb.AppendLine($"站长:{item.WebMaster}
");
sb.AppendLine($"补充信息:{item.Reason}
");
sb.AppendLine($"");
sb.AppendLine($"");
sb.AppendLine($"");
sb.AppendLine($"本消息由 {starblogLink} 自动发送,无需回复。
");
await EmailUtils.SendEmailAsync(
_emailAccountConfig,
"[StarBlog]友链申请结果反馈",
sb.ToString(),
item.WebMaster,
item.Email
);
}
}
在设置是否验证的方法中,实现了:
- 设置一个申请为已验证,自动将该申请的链接添加到友情链接中
- 设置一个申请为未验证,则自动将对应的友情链接删除(如果存在的话)
其他地方就跟上面的友情链接一样了。
写完之后别忘了注册服务
builder.Services.AddScoped();
builder.Services.AddScoped();
友链申请
展示功能做完了,还得接着做友链申请的功能,以方便路过的站长申请互换友链~
添加 StarBlog.Web/ViewModels/LinkExchange/LinkExchangeAddViewModel.cs
文件
我们使用 AspNetCore MVC 框架提供的表单验证功能
public class LinkExchangeAddViewModel {
///
/// 网站名称
///
[Display(Name = "网站名称")]
[Required(ErrorMessage = "必须填写网站名称")]
public string Name { get; set; }
///
/// 介绍
///
[Display(Name = "介绍")]
public string? Description { get; set; }
///
/// 网址
///
[Display(Name = "网址")]
[Required(ErrorMessage = "必须填写网址")]
[DataType(DataType.Url)]
public string Url { get; set; }
///
/// 站长
///
[Display(Name = "站长名称")]
[Required(ErrorMessage = "必须填写站长名称")]
public string WebMaster { get; set; }
///
/// 联系邮箱
///
[Display(Name = "联系邮箱")]
[Required(ErrorMessage = "必须填写联系邮箱")]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
}
接着写一下页面 StarBlog.Web/Views/LinkExchange/Add.cshtml
@model StarBlog.Web.ViewModels.LinkExchange.LinkExchangeAddViewModel
@{
ViewData["Title"] = "申请友链";
}
申请友链
Link Exchange
友链信息
请输入您的网站信息,方便后续联系
注意事项
申请友情链接需符合以下几点要求
-
相互性
请先在您的网站添加本站链接,再进行友链申请
-
内容类别
本站优先招同类原创、内容相近的博客或网站
-
SEO
Baidu和Google有正常收录,有近期快照的网站优先
-
合法性
不含有违反相关国家法律内容的合法网站,不接受TB客等垃圾站的链接
-
更新及时性
不接受原创内容很少,且长期不更新的网站
-
可访问性
如您的网站无法访问,将会暂时撤销友情链接,如需恢复请联系站长处理
提交
重置
最后是Controller,添加 StarBlog.Web/Controllers/LinkExchangeController.cs
文件
代码如下
public class LinkExchangeController : Controller {
private readonly ILogger _logger;
private readonly LinkExchangeService _service;
private readonly IMapper _mapper;
private readonly Messages _messages;
public LinkExchangeController(
ILogger logger, LinkExchangeService service, IMapper mapper,
Messages messages) {
_logger = logger;
_service = service;
_mapper = mapper;
_messages = messages;
}
[HttpGet]
public IActionResult Add() {
return View();
}
[HttpPost]
public async Task Add(LinkExchangeAddViewModel vm) {
if (!ModelState.IsValid) return View();
if (await _service.HasUrl(vm.Url)) {
_messages.Error("相同网址的友链申请已提交!");
return View();
}
var item = _mapper.Map(vm);
item = await _service.AddOrUpdate(item);
// 发送邮件通知
await _service.SendEmailOnAdd(item);
_messages.Info("友链申请已提交,正在处理中,请及时关注邮件通知~");
return RedirectToAction("Index", "Home");
}
}
搞定~
一切就绪
欢迎各位站长大佬来交换友链~!