xiaoandx / Common.Notice (public) (License: MIT) (since 2025-06-17) (hash sha1)
.Net统一消息通知组件,包含了邮件通知、钉钉群机器人、飞书群机器人、企业微信群机器人通知,帮助我们更容易地发送程序异常通知
Date (UTC) User Event
2025-06-17 05:59 xiaoandx Annotated tag refs/tags/1.0.1 created (7f538f3d28e3f5dddf3b6d32fafebeb5db6b0a5d)
2025-06-17 05:59 xiaoandx Reference refs/heads/main created (e7a799b0f447466ba16b13cc6e7237cbfc2bfe39)
2025-06-17 05:55 xiaoandx Repository has been created

README.md:

项目概述

  • 项目名称: Common.Notzice (net472 || net48 || netstandard2.0)

  • 版本: 1.0.1

  • 作者: WEI.ZHOU (Willis)

  • 描述: .Net统一消息通知组件,包含了邮件通知、钉钉群机器人、飞书群机器人、企业微信群机器人通知,帮助我们更容易地发送程序异常通知

  • 版权: © WEI.ZHOU (Willis). All rights reserved.

  • 开源协议: MIT License

功能介绍

  • 组件支持 [邮件]、[钉钉群组机器人]、[飞书群组机器人]、[企业微信群组机器人] 方式发送
  • 组件支持@用户发送警告提示(部分平台消息类型不支持@)
  • 支持消息发送间隔时间设置,避免异常消息频繁通知,影响用户使用
  • 群机器人消息类型,可以参考对应平台的对接文档(部分消息类型有实现)
  • 发送消息方法支持异步执行与同步执行,方便用户在不同的执行环境中,使用不同的方式发送消息

平台支持

  • [x] 企业微信群机器人

项目接入

> 项目接入提供了以下发送方式的Demo:邮件通知、钉钉通知、飞书、企业微信通知

1. 邮件通知

> 邮件通知支持同时发送给多个收件人 ### Step 1 : 添加组件库Dll (已有的部分不需要安装)

Copy dll Common.Notice.dll ==> bin
Install-Package MailKit -version 2.11.1 
Install-Package Newtonsoft.Json
Install-Package Microsoft.Extensions.Dependencyinjection -version 3.1.23
Install-Package Microsoft.Extensions.Configuration -version 3.1.23

Step 2 : 方式一: 依赖注入,配置 Startup 启动类 (Asp.Net Core Web)

public class Startup
{[Feishu](Common.Notice/Feishu)
    //...
    
    public void ConfigureServices(IServiceCollection services)
    {
        //configuration
        services.AddCommonNotice(config =>
        {
            config.IntervalSeconds = 10;//同一标题的消息,10秒内只能发一条,避免短时间内大量发送重复消息
            config.UseEmail(option =>
            {
                option.Host = "smtp.163.com";//SMTP地址
                option.Port = 465;//SMTP端口
                option.FromName = "WEI.ZHOU";//发送人名字(自定义)
                option.FromAddress = "xandxiao@163.com";//发送邮箱
                option.Password = "LM4im32sPe5WillisYhvUK";//秘钥
                option.ToAddress = new List<string>()//收件人集合
                {
                    "12345@qq.com"
                };
            });
        });
    }    
}

Step 3 : 方式一: 依赖注入,IEmailProvider服务接口使用

[ApiController]
[Route("[controller]/[action]")]
public class CommonNoticeController : ControllerBase
{
    private readonly IEmailProvider _mailProvider;
    public CommonNoticeController(IEmailProvider provider)
    {
        _mailProvider = provider;
    }

    [HttpGet]
    public async Task SendMail([FromQuery] string str)
    {
        await _mailProvider.SendAsync(str, new Exception(str));
    }
}

Step 4 : 方式二: 在代码中直接使用

public class CommonService
{
    private readonly ICommonNotice? _emailNotice;
    
    public CommonService()
    {
        _emailNotice = new NoticeFactory().UseEmailNotice(
        new EmailOptions()
        {
          Host = "smtp.163.com",
          Port = 465,
          FromName = "WEI.ZHOU",
          FromAddress = "xandxiao@163.com",
          Password = "LM4im32sPe5WillisYhvUK",
          ToAddress = new List<string>()
          {
            "12345@qq.com"
          }
        },
        new NoticeOptions()
        {
          IntervalSeconds = 1
        });
    }

    // 异步调用
    public async Task SendMail()
    {
        string str = "测试邮件内容";
        await _emailNotice.SendAsync(str, new Exception(str));
    }
    
    // 同步调用
    public void SendMail()
    {
        string str = "测试邮件内容";
        _emailNotice.Send(str, new Exception(str));
    }
}

Step 5 : 基础用法


// 异步发送邮件方法测试
[Fact]
public async Task Email_Send_Should_Be_SucceedByAsync()
{
  // 支持Exception对象
  //var response = await _emailProvider!.SendAsync("Common.Notice email Async test", new Exception("custom exception"));
  
  // 支持Message文本
  var response = await _emailProvider!.SendAsync("Common.Notice email Async test", "custom exception");
  
  Assert.True(response.IsSuccess);
}

// 同步发送邮件方法测试
[Fact]
public void Email_Send_Should_Be_Succeed()
{
  // 支持Exception对象
  //var response = _emailProvider!.Send("Common.Notice email test", new Exception("custom exception"));
  
  // 支持Message文本
  var response = _emailProvider!.Send("Common.Notice email test", "custom exception");
  
  Assert.True(response.IsSuccess);
}

// 邮件收件人传入,发送邮件测试
[Fact]
public void Email_Send_Should_Be_SucceedByAt()
{
  // 邮件收件人作为参数传入,发送邮件
  //var response = _emailProvider!.Send("Common.Notice email test", new Exception("custom exception"), new CommonNoticeAtUser(){IsAtAll = false, UserId = new[]{"wei.zhou@ccssttcn.com"}});
  
  // 邮件收件人作为参数传入,发送邮件
  var response = _emailProvider!.Send("Common.Notice email test", "custom exception", new CommonNoticeAtUser(){IsAtAll = false, UserId = new[]{"wei.zhou@ccssttcn.com"}});
  
  Assert.True(response.IsSuccess);
}

2. 钉钉通知

> 配置钉钉群机器人官方文档

Step 1 : 添加组件库Dll (已有的部分不需要安装)

Copy dll Common.Notice.dll ==> bin
Install-Package Newtonsoft.Json
Install-Package Microsoft.Extensions.Dependencyinjection -version 3.1.23
Install-Package Microsoft.Extensions.Configuration -version 3.1.23

Step 2 : 方式一: 依赖注入,配置 Startup 启动类 (Asp.Net Core Web)

public class Startup
{
    //...
    
    public void ConfigureServices(IServiceCollection services)
    {
        //configuration
        services.AddCommonNotice(config =>
        {
            config.IntervalSeconds = 10;//同一标题的消息,10秒内只能发一条,避免短时间内大量发送重复消息
            config.UseDingTalk(option =>
            {
                option.WebHook = "https://oapi.dingtalk.com/robot/send?access_token=xxxxx";//通知地址
                option.Secret = "secret";//签名校验
            });
        });
    }    
}

Step 3 : 方式一: 依赖注入,IDingtalkProvider服务接口使用

[ApiController]
[Route("[controller]/[action]")]
public class CommonNoticeController : ControllerBase
{
    private readonly IDingtalkProvider _dingtalkProvider;
    public CommonNoticeController(IDingtalkProvider dingtalkProvider)
    {
        _dingtalkProvider = dingtalkProvider;
    }

    [HttpGet]
    public async Task SendDingTalk([FromQuery] string str)
    {
        await _dingtalkProvider.SendAsync(str, new Exception(str));
    }
}

Step 4 : 方式二: 在代码中直接使用

public class CommonService
{
    private readonly ICommonNotice? _dingtalkNotice;
    
    public CommonService()
    {
        _dingtalkNotice = new NoticeFactory().UseDingtalkNotice(
        new DingtalkOptions()
        {
          WebHook = "https://oapi.dingtalk.com/robot/send?access_token=xxxxx", //通知地址
          Secret = "secret"
        },
        new NoticeOptions()
        {
          IntervalSeconds = 1
        });
    }

    // 异步调用
    public async Task SendDingTalk()
    {
        string str = "测试钉钉群机器人消息";
        await _dingtalkNotice.SendAsync(str, new Exception(str));
    }
    
    // 同步调用
    public void SendDingTalk()
    {
        string str = "测试钉钉群机器人消息";
        _dingtalkNotice.Send(str, new Exception(str));
    }
}

Step 5 : 基础用法

// 异步发送钉钉群机器人消息测试
[Fact]
public async Task DingTalk_Send_Should_Be_SucceedByAsync()
{
  // 支持Exception对象
  //var response = await _dingtalkNotice!.SendAsync("通知标题", new Exception("custom exception"));
  
  // 支持Message文本
  var response = await _dingtalkNotice!.SendAsync("通知标题", "custom exception");
  Assert.True(response.IsSuccess);
}

// 同步发送钉钉群机器人消息测试
[Fact]
public void DingTalk_Send_Should_Be_Succeed()
{
  // 支持Exception对象
  //var response = _dingtalkNotice!.Send("通知标题", new Exception("同步消息"));
  
  // 支持Message文本
  var response = _dingtalkNotice!.Send("通知标题", "同步消息");
  Assert.True(response.IsSuccess);
}

// 钉钉群机器人支持@用户消息
[Fact]
public void DingTalk_Send_Should_Be_SucceedByAt()
{
  // 钉钉群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  //var response = _dingtalkNotice!.Send("通知标题", new Exception("同步消息"),  new CommonNoticeAtUser(){IsAtAll = false, Mobile = new[]{"159XXXXXX44"}});
  
  // 钉钉群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  var response = _dingtalkNotice!.Send("通知标题", "同步消息",  new CommonNoticeAtUser(){IsAtAll = false, Mobile = new[]{"159XXXXXX44"}});
  Assert.True(response.IsSuccess);
}

3. 飞书通知

> 配置飞书群机器人官方文档

Step 1 : 添加组件库Dll (已有的部分不需要安装)

Copy dll Common.Notice.dll ==> bin
Install-Package Newtonsoft.Json
Install-Package Microsoft.Extensions.Dependencyinjection -version 3.1.23
Install-Package Microsoft.Extensions.Configuration -version 3.1.23

Step 2 : 方式一: 依赖注入,配置 Startup 启动类

public class Startup
{
    //...
    
    public void ConfigureServices(IServiceCollection services)
    {
        //configuration
        services.AddCommonNotice(config =>
        {
            config.IntervalSeconds = 10;//同一标题的消息,10秒内只能发一条,避免短时间内大量发送重复消息
            config.UseFeishu(option =>
            {
                option.WebHook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxx";//通知地址
                option.Secret = "secret";//签名校验
            });
        });
    }    
}

Step 3 : 方式一: 依赖注入,IFeishuProvider服务接口使用

[ApiController]
[Route("[controller]/[action]")]
public class CommonNoticeController : ControllerBase
{
    private readonly IFeishuProvider _feishuProvider;
    public CommonNoticeController(IFeishuProvider feishuProvider)
    {
        _feishuProvider = feishuProvider;
    }

    [HttpGet]
    public async Task SendFeishu([FromQuery] string str)
    {
        await _feishuProvider.SendAsync(str, new Exception(str));
    }
}

Step 4 : 方式二: 在代码中直接使用

public class CommonService
{
    private readonly ICommonNotice? _feishuProvider;
    
    public CommonService()
    {
        _feishuProvider = new NoticeFactory().UseFeishuNotice(
        new FeishuOptions()
        {
          WebHook = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxx", //通知地址
          Secret = "secret"
        },
        new NoticeOptions()
        {
          IntervalSeconds = 1
        });
    }

    // 异步调用
    public async Task SendFeishu()
    {
        string str = "测试飞书群机器人消息";
        await _feishuProvider.SendAsync(str, new Exception(str));
    }
    
    // 同步调用
    public void SendFeishu()
    {
        string str = "测试飞书群机器人消息";
        _feishuProvider.Send(str, new Exception(str));
    }
}

Step 5 : 基础用法

// 异步发送飞书群机器人消息测试
[Fact]
public async Task Feishu_Send_Should_Be_SucceedByAsync()
{
  // 支持Exception对象
  //var response =  await _feishuProvider!.SendAsync("通知标题", new Exception("异步Hello"));
  
  // 支持Message文本
  var response =  await _feishuProvider!.SendAsync("通知标题", "异步Hello");
  Assert.True(response.IsSuccess);
}

// 同步发送飞书群机器人消息测试
[Fact]
public void Feishu_Send_Should_Be_Succeed()
{
  // 支持Exception对象
  var response = _feishuProvider!.Send("通知标题", new Exception("同步Hello"));
  
  // 支持Message文本
  var response = _feishuProvider!.Send("通知标题", "同步Hello");
  Assert.True(response.IsSuccess);
}

// 飞书群机器人支持@用户消息
[Fact]
public void Feishu_Send_Should_Be_SucceedByAt()
{
  // 飞书群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  //var response = _feishuProvider!.Send("通知标题", new Exception("同步Hello"), new CommonNoticeAtUser(){IsAtAll = true});
  
  // 飞书群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  //var response = _feishuProvider!.Send("通知标题", "同步Hello", new CommonNoticeAtUser(){IsAtAll = true});
  Assert.True(response.IsSuccess);
}

4. 企业微信通知

> 配置企业微信群机器人官方文档

Step 1 : 安装包,通过Nuget安装包

Copy dll Common.Notice.dll ==> bin
Install-Package Newtonsoft.Json
Install-Package Microsoft.Extensions.Dependencyinjection -version 3.1.23
Install-Package Microsoft.Extensions.Configuration -version 3.1.23

Step 2 : 方式一: 依赖注入,配置 Startup 启动类

public class Startup
{
    //...
    
    public void ConfigureServices(IServiceCollection services)
    {
        //configuration
        services.AddCommonNotice(config =>
        {
            config.IntervalSeconds = 10;//同一标题的消息,10秒内只能发一条,避免短时间内大量发送重复消息
            config.UseWeixin(option =>
            {
                option.WebHook = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx";//通知地址
            });
        });
    }    
}

Step 3 : 方式一: 依赖注入,IWeixinProvider服务接口使用

[ApiController]
[Route("[controller]/[action]")]
public class CommonNoticeController : ControllerBase
{
    private readonly IWeixinProvider _weixinProvider;
    public CommonNoticeController(IWeixinProvider weixinProvider)
    {
        _weixinProvider = weixinProvider;
    }

    [HttpGet]
    public async Task SendWexin([FromQuery] string str)
    {
        await _weixinProvider.SendAsync(str, new Exception(str));
    }
}

Step 4 : 方式二: 在代码中直接使用

public class CommonService
{
    private readonly ICommonNotice? _weixinProvider;
    
    public CommonService()
    {
        _weixinProvider = new NoticeFactory().UseWeixinNotice(
        new WeixinOptions()
        {
          WebHook = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx" //通知地址
        },
        new NoticeOptions()
        {
          IntervalSeconds = 1
        });
    }

    // 异步调用
    public async Task SendWexin()
    {
        string str = "测试企业微信群机器人消息";
        await _weixinProvider.SendAsync(str, new Exception(str));
    }
    
    // 同步调用
    public void SendWexin()
    {
        string str = "测试企业微信群机器人消息";
        _weixinProvider.Send(str, new Exception(str));
    }
}

Step 5 : 基础用法

// 异步发送企业微信群机器人消息测试
[Fact]
public async Task Weixin_Send_Should_Be_SucceedByAsync()
{
  // 支持Exception对象
  //var response = await _weixinProvider?.SendAsync("通知标题", new Exception("custom exception"))!;
  
  // 支持Message文本
  var response = await _weixinProvider?.SendAsync("通知标题", "custom exception")!;
  Assert.True(response.IsSuccess);
}

// 同步发送企业微信群机器人消息测试
[Fact]
public void Weixin_Send_Should_Be_Succeed()
{
  // 支持Exception对象
  var response = _weixinProvider?.Send("通知标题", new Exception("custom exception"))!;
  
  // 支持Message文本
  var response = _weixinProvider?.Send("通知标题", "custom exception")!;
  Assert.True(response.IsSuccess);
}

// 企业微信群机器人支持@用户消息
[Fact]
public void Weixin_Send_Should_Be_SucceedByAt()
{
  // 企业微信群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  var response = _weixinProvider?.Send("通知标题", new Exception("custom exception"), new CommonNoticeAtUser(){IsAtAll = false, Mobile = new[]{"159XXXXXX44"}})!;
  
  // 企业微信群机器人支持@用户消息
  // UserId:@指定的用户ID列表,各消息平台的UserID,邮件平台为邮箱地址
  // Mobile:@指定的手机号列表,请注意:飞书平台、邮箱发送不支持手机号
  // IsAtAll:@所有人
  var response = _weixinProvider?.Send("通知标题", "custom exception", new CommonNoticeAtUser(){IsAtAll = false, Mobile = new[]{"159XXXXXX44"}})!;
  Assert.True(response.IsSuccess);
}

Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/xiaoandx/Common.Notice

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/xiaoandx/Common.Notice

Clone this repository using git:
git clone git://git.rocketgit.com/user/xiaoandx/Common.Notice

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main