新增加发送邮件功能

This commit is contained in:
izory 2021-09-28 17:42:25 +08:00
parent d5087a1725
commit c24c243dc3
11 changed files with 224 additions and 25 deletions

View File

@ -21,11 +21,11 @@ namespace Infrastructure
int day = date.Day; int day = date.Day;
int hour = date.Hour; int hour = date.Hour;
string timeDir = $"{year}/{month}/{day}/{hour}";// date.ToString("yyyyMM/dd/HH/"); string timeDir = $"{year}{month}{day}";// date.ToString("yyyyMM/dd/HH/");
if (!string.IsNullOrEmpty(path)) if (!string.IsNullOrEmpty(path))
{ {
timeDir = $"{path}/{timeDir}"; timeDir = $"{path}/{timeDir}/";
} }
return timeDir; return timeDir;
} }

View File

@ -27,7 +27,7 @@ namespace Infrastructure
{ {
public string From { get; set; } public string From { get; set; }
public string Password { get; set; } public string Password { get; set; }
public string Host { get; set; } public string Smtp { get; set; }
public int Port { get; set; } public int Port { get; set; }
} }
/// <summary> /// <summary>

View File

@ -1,12 +1,25 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Attribute; using Infrastructure.Attribute;
using Infrastructure.Model;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System; using System;
using ZR.Admin.WebApi.Filters;
using ZR.Common;
namespace ZR.Admin.WebApi.Controllers namespace ZR.Admin.WebApi.Controllers
{ {
public class HomeController : BaseController public class HomeController : BaseController
{ {
private OptionsSetting OptionsSetting;
private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
public HomeController(IOptions<OptionsSetting> options)
{
OptionsSetting = options.Value;
}
/// <summary> /// <summary>
/// 心跳 /// 心跳
/// </summary> /// </summary>
@ -31,7 +44,7 @@ namespace ZR.Admin.WebApi.Controllers
} }
string key = ConfigUtils.Instance.GetConfig("DbKey"); string key = ConfigUtils.Instance.GetConfig("DbKey");
string encryptTxt = NETCore.Encrypt.EncryptProvider.DESEncrypt(content, key); string encryptTxt = NETCore.Encrypt.EncryptProvider.DESEncrypt(content, key);
return Ok(new { content, encryptTxt }); return Ok(new { content, encryptTxt });
} }
/// <summary> /// <summary>
@ -49,5 +62,30 @@ namespace ZR.Admin.WebApi.Controllers
string encryptTxt = NETCore.Encrypt.EncryptProvider.DESDecrypt(content, key); string encryptTxt = NETCore.Encrypt.EncryptProvider.DESDecrypt(content, key);
return Ok(new { content, encryptTxt }); return Ok(new { content, encryptTxt });
} }
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="sendEmailVo">请求参数接收实体</param>
/// <returns></returns>
[ActionPermissionFilter(Permission = "tool:email:send")]
public IActionResult SendEmail([FromBody] SendEmailDto sendEmailVo)
{
if (sendEmailVo == null || string.IsNullOrEmpty(sendEmailVo.Subject) || string.IsNullOrEmpty(sendEmailVo.ToUser))
{
return ToResponse(ApiResult.Error($"请求参数不完整"));
}
if (string.IsNullOrEmpty(OptionsSetting.MailOptions.From) || string.IsNullOrEmpty(OptionsSetting.MailOptions.Password))
{
return ToResponse(ApiResult.Error($"请配置邮箱信息"));
}
MailHelper mailHelper = new MailHelper(OptionsSetting.MailOptions.From, OptionsSetting.MailOptions.Smtp, OptionsSetting.MailOptions.Port, OptionsSetting.MailOptions.Password);
mailHelper.SendMail(sendEmailVo.ToUser, sendEmailVo.Subject, sendEmailVo.Content, sendEmailVo.FileUrl, sendEmailVo.HtmlContent);
logger.Info($"发送邮件{JsonConvert.SerializeObject(sendEmailVo)}");
return SUCCESS(true);
}
} }
} }

View File

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.IO; using System.IO;
using ZR.Admin.WebApi.Filters;
using ZR.Common; using ZR.Common;
namespace ZR.Admin.WebApi.Controllers namespace ZR.Admin.WebApi.Controllers
@ -26,24 +27,28 @@ namespace ZR.Admin.WebApi.Controllers
/// <param name="formFile"></param> /// <param name="formFile"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
[Verify]
[ActionPermissionFilter(Permission = "system")]
public IActionResult SaveFile([FromForm(Name = "file")] IFormFile formFile) public IActionResult SaveFile([FromForm(Name = "file")] IFormFile formFile)
{ {
if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传图片不能为空"); if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传图片不能为空");
string fileExt = Path.GetExtension(formFile.FileName); string fileExt = Path.GetExtension(formFile.FileName);
string savePath = Path.Combine(WebHostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads"));
if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); }
string fileName = FileUtil.HashFileName(Guid.NewGuid().ToString()).ToLower() + fileExt; string fileName = FileUtil.HashFileName(Guid.NewGuid().ToString()).ToLower() + fileExt;
string finalFilePath = Path.Combine(savePath, fileName); string finalFilePath = Path.Combine(WebHostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads"), fileName);
finalFilePath = finalFilePath.Replace("\\", "/").Replace("//", "/");
if (!Directory.Exists(Path.GetDirectoryName(finalFilePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(finalFilePath));
}
using (var stream = new FileStream(finalFilePath, FileMode.Create)) using (var stream = new FileStream(finalFilePath, FileMode.Create))
{ {
formFile.CopyToAsync(stream); formFile.CopyToAsync(stream);
} }
string accessPath = $"{OptionsSetting.Upload.UploadUrl}/{finalFilePath.Replace("wwwroot", "").Replace("\\", "/")}"; string accessPath = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads").Replace("\\", " /")}{fileName}";
return ToResponse(ToJson(1, accessPath)); return ToResponse(ResultCode.SUCCESS, new { accessPath, fullPath = finalFilePath });
} }
} }
} }

View File

@ -54,12 +54,12 @@ namespace ZR.Admin.WebApi.Filters
bool isDemoMode = ConfigUtils.Instance.GetAppConfig("DemoMode", false); bool isDemoMode = ConfigUtils.Instance.GetAppConfig("DemoMode", false);
//演示公开环境屏蔽权限 //演示公开环境屏蔽权限
string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear" }; string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "send" };
if (isDemoMode && (denyPerms.Any(f => Permission.ToLower().Contains(f.ToLower())) || Permission.Equals("system"))) if (isDemoMode && (denyPerms.Any(f => Permission.ToLower().Contains(f.ToLower())) || Permission.Equals("system")))
{ {
context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "演示模式 , 不允许操作" }); context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "演示模式 , 不允许操作" });
} }
if (!HasPermi) if (!HasPermi && !Permission.Equals("system"))
{ {
logger.Info($"用户{info.NickName}没有权限访问{context.HttpContext.Request.Path},当前权限[{Permission}]"); logger.Info($"用户{info.NickName}没有权限访问{context.HttpContext.Request.Path},当前权限[{Permission}]");
context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "你没有权限访问" }); context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "你没有权限访问" });

View File

@ -13,7 +13,7 @@
"urls": "http://localhost:8888", //url "urls": "http://localhost:8888", //url
"sysConfig": { "sysConfig": {
"DBCommandTimeout": 10, "DBCommandTimeout": 10,
"tokenExpire": 1440,//Jwt token "tokenExpire": 1440, //Jwt token
"cors": "http://localhost:8887" //"," "cors": "http://localhost:8887" //","
}, },
"DemoMode": false, // "DemoMode": false, //
@ -22,7 +22,7 @@
"UploadDirectory": "/", "UploadDirectory": "/",
"UploadUrl": "http://localhost:8888" "UploadUrl": "http://localhost:8888"
}, },
"ALYUN_OCS": { "QIQIU_OSS": {
"REGIONID": "cn-hangzhou", "REGIONID": "cn-hangzhou",
"KEY": "XX", "KEY": "XX",
"SECRET": "XX" "SECRET": "XX"
@ -33,5 +33,15 @@
"autoPre": true, // "autoPre": true, //
"author": "zr", "author": "zr",
"tablePrefix": "live_,sys_" //"表前缀(生成类名不会包含表前缀,多个用逗号分隔)", "tablePrefix": "live_,sys_" //"表前缀(生成类名不会包含表前缀,多个用逗号分隔)",
},
//
"MailOptions": {
//
"From": "xxxx@qq.com",
//
"Password": "123456",
//
"Smtp": "smtp.qq.com",
"Port": 587
} }
} }

View File

@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MailKit" Version="2.15.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Npoi.Mapper" Version="3.5.1" /> <PackageReference Include="Npoi.Mapper" Version="3.5.1" />
</ItemGroup> </ItemGroup>

View File

@ -8,3 +8,16 @@ export function upload(data) {
headers: { "Content-Type": "multipart/form-data" }, headers: { "Content-Type": "multipart/form-data" },
}) })
} }
/**
* 发送邮件
* @param {*} data
* @returns
*/
export function sendEmail(data) {
return request({
url: '/home/SendEmail',
method: 'POST',
data: data,
})
}

View File

@ -1,24 +1,28 @@
<template> <template>
<div class="app-container home"> <div class="app-container home">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="10">
<el-card> <el-card>
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>系统公告</span> <span>系统公告</span>
</div> </div>
<el-row> <el-row>
<p>欢迎各位大佬拉取分支开发新功能</p> <p>👀欢迎各位大佬拉取分支开发新功能</p>
<p>各位大佬轻点点服务器低配</p> <p>🎃各位大佬轻点点服务器低配</p>
<p>开源地址: <p>🎉免费开源地址
<el-link type="primary" href="https://gitee.com/izory/ZrAdminNetCore" target="_blank"> <!-- <el-link type="primary" href="https://gitee.com/izory/ZrAdminNetCore" target="_blank">
https://gitee.com/izory/ZrAdminNetCore https://gitee.com/izory/ZrAdminNetCore
</el-link> </el-link> -->
</p> </p>
<h3>如果觉得不错欢迎给个star</h3> <p>
<el-button type="primary" size="mini" icon="el-icon-cloudy" plain @click="goTarget('https://gitee.com/izory/ZrAdminNetCore')">访问码云</el-button>
<el-button type="primary" size="mini" icon="el-icon-cloudy" plain @click="goTarget('https://github.com/izhaorui/ZrAdmin.NET')">Github</el-button>
</p>
<h3>如果觉得不错欢迎给个Star收藏一下 这样作者才有继续免费下去的动力谢谢</h3>
</el-row> </el-row>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="6">
<el-card> <el-card>
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<span>技术选型</span> <span>技术选型</span>
@ -55,7 +59,7 @@
<span>捐赠支持</span> <span>捐赠支持</span>
</div> </div>
<div class="body"> <div class="body">
<span class="tip">如果觉得有用你可以请作者喝杯咖啡表示鼓励</span> <span class="tip">如果觉得有用你可以请作者喝杯咖啡表示鼓励</span>
<img src="http://ss.izhaorui.cn/pay.jpg" alt="donate" width="100%" /> <img src="http://ss.izhaorui.cn/pay.jpg" alt="donate" width="100%" />
</div> </div>
</el-card> </el-card>

View File

@ -0,0 +1,121 @@
<template>
<el-row>
<el-form class="mt10" ref="form" :model="form" label-width="100px" :rules="rules">
<el-form-item label="收件邮箱" prop="toUser">
<el-input v-model="form.toUser">
</el-input>
</el-form-item>
<el-form-item label="邮件主题" prop="subject">
<el-input v-model="form.subject"></el-input>
</el-form-item>
<el-form-item label="邮件内容" prop="content">
<el-input v-model="form.content" rows="3" type="textarea"></el-input>
</el-form-item>
<el-form-item label="附件">
<el-upload name="file" ref="upload" :data="{savetype: form.saveType, filePath: form.filePath}" :headers="headers" :auto-upload="false" :on-success="uploadSuccess" :action="uploadActionUrl">
<el-button slot="trigger" size="mini" icon="el-icon-upload">选择文件</el-button>
<el-button style="margin-left: 10px;" size="mini" type="primary" @click="submitUpload">上传到服务器</el-button>
</el-upload>
</el-form-item>
<el-form-item>
<el-button type="primary" size="mini" @click="formSubmit">立即提交</el-button>
</el-form-item>
</el-form>
</el-row>
</template>
<script>
import { sendEmail } from "@/api/common";
import { getToken } from "@/utils/auth";
export default {
name: "sendEmail",
data() {
return {
form: {
fileUrl: "",
},
headers: {
Token: "",
},
uploadActionUrl: process.env.VUE_APP_BASE_API + "upload/SaveFile",
rules: {
subject: [{ required: true, message: "主题不能为空", trigger: "blur" }],
toUser: [
{ required: true, message: "请输入邮箱地址", trigger: ["blur"] },
{
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"],
type: "email",
},
],
content: [{ required: true, message: "内容不能为空", trigger: "blur" }],
},
};
},
mounted() {
console.log(getToken());
this.headers.Token = getToken();
},
methods: {
//
reset() {
this.form = {
toUser: undefined,
content: undefined,
subject: undefined,
fileUrl: undefined,
};
this.resetForm("form");
},
submitUpload() {
this.$refs.upload.submit();
},
//
uploadSuccess(response, file, fileList) {
console.log(response);
if (response.code == 200) {
this.$message.success("上传成功");
this.form.fileUrl = response.data.fullPath;
} else {
this.$message.error(response.msg);
}
},
formSubmit() {
console.log(JSON.stringify(this.form));
this.$refs["form"].validate((valid) => {
//
if (valid) {
const loading = this.$loading({
lock: true,
text: "Loading",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
//
sendEmail(this.form).then((res) => {
this.open = false;
if (res.code == 200) {
this.$message.success("发送成功");
this.reset();
}
this.$refs.upload.clearFiles();
loading.close();
});
setTimeout(() => {
loading.close();
}, 5000);
} else {
//
return false;
}
});
},
},
};
</script>
<style scoped>
.el-upload-list {
width: 200px;
}
</style>

View File

@ -161,6 +161,13 @@
<param name="content"></param> <param name="content"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:ZR.Admin.WebApi.Controllers.HomeController.SendEmail(Infrastructure.Model.SendEmailDto)">
<summary>
发送邮件
</summary>
<param name="sendEmailVo">请求参数接收实体</param>
<returns></returns>
</member>
<member name="T:ZR.Admin.WebApi.Controllers.ArticleController"> <member name="T:ZR.Admin.WebApi.Controllers.ArticleController">
<summary> <summary>
T4代码自动生成 T4代码自动生成