一、业务需求

在工作中遇到一个场景,软件bug或功能发布之后,会通知测试进行测试,要求写一个小工具能自动发送邮件,功能包含发送和抄送支持多个,因为只是通知没有写进附件功能,这个其他博客都有搜一下就可以了。

二、以下是实现代码

这里要注意如果接收者邮箱三种方式都没配置则需要手动输入,其他的没配置就是弹异常了。

这里使用的三种配置方其中的环境变量和命令行参数需要导入以下包,我用的是.net5.0所以版本都是选的5.0。使用其他版本不知道会产生什么问题,能一直就一致(前辈给的经验)

使用json方式有个坑就是要把json文件的属性里的复制到输出目录选成始终复制,Environment.CurrentDirectory才找得到它。

查看代码
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Net.Mail;
using System.Text;
namespace gct.sendmail
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine(WriteEmail(args).ToString());
} public static string WriteEmail(string[] args)
{
IConfiguration configuration = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory)
//json文件
.AddJsonFile("appsettings.json")
//系统参数
.AddCommandLine(args)
//环境变量
.AddEnvironmentVariables()
.Build(); //发送者邮箱
string strMailFrom = GetValue(configuration, "From:strMailFrom", "strMailFrom");
//校验码
string strCode = GetValue(configuration, "From:strCode", "strCode");
//是否Html文件格式
bool isHtml = !string.IsNullOrEmpty(configuration["From:isHtml"])?bool.Parse(configuration["From:isHtml"]) :
configuration["isHtml"]!=null ? bool.Parse(configuration["isHtml"]) : false;
//邮件服务器
string strEmailServe = GetValue(configuration, "From:strEmailServe", "strEmailServe");
//端口号
int ePort = !string.IsNullOrEmpty(configuration["From:isHtml"])? int.Parse(configuration["From:ePort"]):
!string.IsNullOrEmpty(configuration["ePort"]) ? int.Parse(configuration["ePort"]) : 25;
//邮件发送名称
string strMailFromName = GetValue(configuration, "From:strMailFromName", "strMailFromName");
string strMailTo = GetValue(configuration, "To:strMailTo", "strMailTo");
if (string.IsNullOrEmpty(strMailTo))
{
Console.WriteLine("请输入收件人邮箱,以" + ";" + "间隔!");
strMailTo = Console.ReadLine().ToString();
}
//抄送
string strMailCC = GetValue(configuration, "To:strMailCC", "strMailCC");
//标题
string strMailSubject = GetValue(configuration, "Content:strMailSubject", "strMailSubject");
//正文
string strMailBody = GetValue(configuration, "Content:strMailBody", "strMailBody"); return SendEmail(strMailFrom, strMailTo, strMailCC, strMailSubject, strMailBody, isHtml, strCode, ePort, strEmailServe, strMailFromName);
}
/// <summary>
/// 发送电子邮件
/// </summary>
/// <param name="mailFrom">邮件发送方</param>
/// <param name="mailTo">邮件接收方</param>
/// <param name="mailCC">抄送</param>
/// <param name="mailHead">标题</param>
/// <param name="mailBody">正文</param>
/// <param name="isHtml">指示邮件正文是否为 HTML 格式。</param>
/// <param name="code">校验码</param>
/// <param name="ePort">端口号</param>
/// <param name="emailServe">邮箱服务器</param>
/// <param name="mailFromName">发件人名称</param>
/// <returns></returns>
public static string SendEmail(string mailFrom, string mailTo, string mailCC,
string mailHead, string mailBody, bool isHtml,
string code, int ePort,string emailServe,string mailFromName)
{ MailMessage eMail = new MailMessage();
SmtpClient eClient = new SmtpClient(emailServe, ePort);
eClient.Credentials = new System.Net.NetworkCredential(mailFrom, code);
eClient.EnableSsl = true;
eClient.UseDefaultCredentials = false;
eMail.Subject = mailHead;
eMail.SubjectEncoding = Encoding.UTF8;
eMail.Body = mailBody;
eMail.BodyEncoding = Encoding.UTF8;
eMail.From = new MailAddress(mailFrom, mailFromName,Encoding.UTF8);
string[] arrMailAddr;
try
{
//用";"分割多个收件人.
eMail.To.Clear();
if (!string.IsNullOrEmpty(mailTo))
{
arrMailAddr = mailTo.Split(';');
foreach (string strTo in arrMailAddr)
{
if (!string.IsNullOrEmpty(strTo))
{
eMail.To.Add(strTo);
}
}
} //用";"分割多个抄送人.
eMail.CC.Clear();
if (!string.IsNullOrEmpty(mailCC))
{
arrMailAddr = mailCC.Split(';');
foreach (string strCC in arrMailAddr)
{
if (!string.IsNullOrEmpty(strCC))
{
eMail.CC.Add(strCC);
}
}
}
if (isHtml)
{
eMail.IsBodyHtml = true;
}
else
{
eMail.IsBodyHtml = false;
} eClient.Send(eMail);
return "邮件已发送,请查收!"; }
catch (Exception ex)
{
return "邮件发送失败,原因:" + ex.Message.ToString();
} }
//获取配置值
public static string GetValue(IConfiguration configuration,string value1,string value2)
{
if (!string.IsNullOrEmpty(configuration[value1]))
{
return configuration[value1];
}
return configuration[value2];
}
}
}

这里需要注意,邮箱发送需要校验码,我这里是用的qq邮箱,其他邮箱大概也要,我懒得截图了,以下为参考来源:.Net调用QQ邮箱发送邮件 - 樱满集 - 博客园 (cnblogs.com)

首先发送邮件要开启一个smtp的服务

第一步:打开qq邮箱点击设置:

 第二步:点击账户

第三步:向下拉找到smtp字样的地方,然后全部开启

相信你能理解这句话,然后你开启的时候会自动弹出授权码,如果没有当时没有复制粘贴可以点击生成授权码 ,来重新生成:

第一种配置方式:json文件,以下是我的配置方式,取值格式是configuration["From:strCode"]

appsettings.json
{
"From": {
//发件人邮箱
"strMailFrom": "",
//邮箱服务器,以下是qq邮箱服务器
"strEmailServe": "smtp.qq.com",
//授权码(注意此处,是授权码你需要到qq邮箱里点设置开启Smtp服务,然后会提示你第三方登录时密码处填写授权码)
"strCode": "",
//是否为Html文件形式
"isHtml": "false",
//端口,默认25
"ePort": "25",
//发送者名称
"strMailFromName": ""
},
"To": {
//抄送,多个以英文符号;间隔
"strMailCC": "",
//收件人邮箱,多个以英文符号;间隔
"strMailTo": ""
},
"Content": {
//标题
"strMailSubject": "邮件测试",
//正文内容
"strMailBody": "邮件测试,请勿回复"
}
}

第二种配置方式,环境变量,除了在项目内能设置,系统的环境变量也能识别到,以下只距离项目内设置的,这里有个问题我还没弄清楚,弄到Linux环境里去之后项目里设置的好像没有生效,这里我验证之后再来更新,建议是使用json方式配置,优先级也是json优先其次环境变量再其次命令行参数。

第三种配置方式,命令行参数

这里很奇怪的是官方说明会用--开头,但取值的时候--是不生效的也就是说--str和str是一样的。具体的我也不知道,有兴趣的可以去官网了解。

以上分享就这些,写的不好或不对的地方欢迎指正。

转载请注明出处

.net 发邮件的小工具,包含json,环境变量,命令行参数三种配置方式的更多相关文章

  1. iOS系统提供开发环境下命令行编译工具:xcodebuild

    iOS系统提供开发环境下命令行编译工具:xcodebuild[3] xcodebuild 在介绍xcodebuild之前,需要先弄清楚一些在XCode环境下的一些概念[4]: Workspace:简单 ...

  2. JSON的三种解析方式

    一.什么是JSON? JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度. JSON就是一串字符串 只不过元素会使用特定 ...

  3. Shell 参数(2) --解析命令行参数工具:getopts/getopt

    getopt 与 getopts 都是 Bash 中用来获取与分析命令行参数的工具,常用在 Shell 脚本中被用来分析脚本参数. 两者的比较 (1)getopts 是 Shell 内建命令,geto ...

  4. .NET 命令行参数包含应用程序路径吗?

    如果你关注过命令行参数,也许发现有时你会在命令行参数的第一个参数中中看到应用程序的路径,有时又不会.那么什么情况下有路径呢? 其实是否有路径只是取决于获取命令行参数的时候用的是什么方法.而这是 Win ...

  5. PHP 命令行参数解析工具类

    <?php/** * 命令行参数解析工具类 * @author guolinchao * @email luoyecb@163.com */class CommandLine{ // store ...

  6. 命令行参数 && json 协议 && 自定义 error 类型

    命令行参数 在写代码的时候,在运行程序做一些初始化操作的时候,往往会通过命令行传参数到程序中,那么就会用到命令行参数 例如,指定程序运行的模式和级别: go run HTTPServer.go --m ...

  7. Python 中命令行参数解析工具 docopt 安装和应用

    什么是 docopt? 1.docopt 是一种 Python 编写的命令行执行脚本的交互语言. 它是一种语言! 它是一种语言! 它是一种语言! 2.使用这种语言可以在自己的脚本中,添加一些规则限制. ...

  8. Go 命令行参数,JSON 序列化与反序列化

    #### Go 命令行参数,JSON 序列,反序列化这一节来学习一下Go 如果解析命令行参数,以及JSON 的序列化及反序列化; 命令行参数对于熟悉Linux 的同学来说比较清楚,如: ls -a , ...

  9. 小工具:天气查询 Vs自定义设置 DevGridControl中GridView排序问题 小工具:火车票查询 小工具:邮件发送 小工具:截图&简单图像处理

    小工具:天气查询   开发一个天气查询的工具主要由两步构成,一是数据的获取,二是数据的展示.  一.数据获取 数据获取又可以分为使用其它公司提供的API和手动抓取其它网站数据. 1. 某公司提供的AP ...

  10. iOS10打电话、发短信、发邮件等小功能

    注意:iOS10.0以后,使用openURL会有延迟,需要使用 openURL: options: completionHandler: 一.概要 本文中主要就是介绍在iOS中实现打电话.发短信.发邮 ...

随机推荐

  1. 从 vs 的 rc 文件中获取版本号

    更新项目版本号时,需要与 rc 文件的 version 同步,比较方便的方法是直接从 rc 文件中获取版本号,并应用到程序中 // 删除日志检查 bool GetVersion() { // get ...

  2. Ubuntu常用工具和问题整理

    安装Ubuntu虚拟机时常会遇到的几个问题 1.安装时设置镜像 安装Ubuntu系统时设置国内镜像可以加快安装速度:http://mirrors.aliyun.com/ubuntu/ 参考:ubunt ...

  3. Anaconda下载安装步骤

    下载地址 下载比较慢的,用迅雷下,点击复制地址,然后在迅雷里面直接创建连接 Anaconda基于python3.8 Anaconda基于python3.6的 安装步骤 没啥说的,一路安装,中间有个勾选 ...

  4. django学习第九天---raw查询原生sql和python脚本中调用django环境和ORM锁和事务

    ORM执行原生sql语句 在模型查询api不够用的情况下,我们还可以使用原始的sql语句进行查询 方式1 raw() raw()方法,返回模型的实例django.db.models.query.Raw ...

  5. 【Azure 应用服务】如果发现当前使用的订阅无法在China North 3 区中创建App Service服务,如何来解决这个问题呢?

    问题描述 在创建App Service服务时,突然发现无法选择China North 3区域,如何来解决这个问题呢? 问题解答 根据Azure中服务都需要在订阅中注册的原理,因为China North ...

  6. [C/C++] PCWSTR LPCTSTR等等

    目录 为什么会有这个 L"" 宏 LPCWSTR字符串比较 wchar_t 和 char 之间转换 关于 ANSI编码 乌拉~~~ 这是我第一百篇博文咯~ 为什么会有这个 真的开发 ...

  7. 影刀rpa:关于if单条件切换到多条件时的不便之处

    现有需求,只判断一个条件是否满足即可,但随着后续业务开发,这里得if就需要判断多个条件,此时要是想将if单条件改为多条件的话,就得先拉一个if多条件的指令,然后再将if单条件中的语句全部移动到if多条 ...

  8. 有n步台阶,一次只能上1步或2步,共有多少种走法

    循环迭代:   1 public class steps { 2 public int js(int n) { 3 int one = 2; //初始化为第三级台阶最后跨一步的走法 4 int two ...

  9. 通过debug搞清楚.vue文件怎么变成.js文件

    前言 我们每天写的vue代码都是写在vue文件中,但是浏览器却只认识html.css.js等文件类型.所以这个时候就需要一个工具将vue文件转换为浏览器能够认识的js文件,想必你第一时间就想到了web ...

  10. koa 放置 前台打包dist 目录

    const Koa = require('koa'); const app = new Koa() //public是指的放置前端静态资源的文件夹名称 app.use(require('koa-sta ...