feat: mail config and mail send

This commit is contained in:
zchengo
2023-01-24 20:03:35 +08:00
parent a9e33f2bcc
commit 35886fde4f
17 changed files with 731 additions and 8 deletions
+78
View File
@@ -0,0 +1,78 @@
package api
import (
"crm/models"
"crm/response"
"crm/service"
"log"
"strconv"
"github.com/gin-gonic/gin"
)
type MailConfigApi struct {
mailConfigService *service.MailConfigService
}
func NewMailConfigApi() *MailConfigApi {
return &MailConfigApi{
mailConfigService: service.NewMailConfigService(),
}
}
// 保存邮件服务配置
func (m *MailConfigApi) Save(context *gin.Context) {
var param models.MailConfigSaveParam
uid, _ := strconv.Atoi(context.Request.Header.Get("uid"))
err := context.ShouldBind(&param)
if uid <= 0 || err != nil {
response.Result(response.ErrCodeParamInvalid, nil, context)
log.Println(err)
return
}
param.Creator = int64(uid)
errCode := m.mailConfigService.Save(&param)
if errCode == 0 {
mailConfig, errCode := m.mailConfigService.GetInfo(int64(uid))
response.Result(errCode, mailConfig, context)
return
}
response.Result(errCode, nil, context)
}
// 开启或关闭邮件服务
func (m *MailConfigApi) UpdateStatus(context *gin.Context) {
var param models.MailConfigStatusParam
uid, _ := strconv.Atoi(context.Request.Header.Get("uid"))
err := context.ShouldBind(&param)
if uid <= 0 || err != nil {
response.Result(response.ErrCodeParamInvalid, nil, context)
log.Println(err)
return
}
param.Creator = int64(uid)
errCode := m.mailConfigService.UpdateStatus(&param)
response.Result(errCode, nil, context)
}
// 获取邮件服务配置信息
func (m *MailConfigApi) GetInfo(context *gin.Context) {
uid, _ := strconv.Atoi(context.Request.Header.Get("uid"))
if uid <= 0 {
response.Result(response.ErrCodeParamInvalid, nil, context)
return
}
mailConfig, errCode := m.mailConfigService.GetInfo(int64(uid))
response.Result(errCode, mailConfig, context)
}
// 检查邮件配置的有效性
func (m *MailConfigApi) Check(context *gin.Context) {
uid, _ := strconv.Atoi(context.Request.Header.Get("uid"))
if uid <= 0 {
response.Result(response.ErrCodeParamInvalid, nil, context)
return
}
errCode := m.mailConfigService.Check(int64(uid))
response.Result(errCode, nil, context)
}
+16
View File
@@ -4,6 +4,7 @@ import (
"crm/models"
"crm/response"
"crm/service"
"log"
"strconv"
"github.com/gin-gonic/gin"
@@ -45,6 +46,21 @@ func (c *CustomerApi) Update(context *gin.Context) {
response.Result(errCode, nil, context)
}
// 发送邮件给客户
func (c *CustomerApi) SendMail(context *gin.Context) {
var param models.CustomerSendMailParam
uid, _ := strconv.Atoi(context.Request.Header.Get("uid"))
err := context.ShouldBind(&param)
if uid <= 0 || err != nil {
response.Result(response.ErrCodeParamInvalid, nil, context)
log.Println(err)
return
}
param.Uid = int64(uid)
errCode := c.customerService.SendMail(&param)
response.Result(errCode, nil, context)
}
// 删除客户
func (c *CustomerApi) Delete(context *gin.Context) {
var param models.CustomerDeleteParam
+27 -1
View File
@@ -2,13 +2,15 @@ package common
import (
"crm/global"
"crm/models"
"crypto/tls"
"fmt"
"log"
"gopkg.in/gomail.v2"
)
// 发送邮件
// 发送邮件(系统级别)
// QQ邮箱:SMTP 服务器地址:smtp.qq.comSSL协议端口:465/994 | 非SSL协议端口:25
// 163邮箱:SMTP 服务器地址:smtp.163.com(端口:25
func SendMail(email, content string) error {
@@ -30,4 +32,28 @@ func SendMail(email, content string) error {
return err
}
return nil
}
// 发送邮件给客户(客户级别)
func SendMailToCustomer(mp models.MailParam) error {
m := gomail.NewMessage()
m.SetHeader("From", mp.Sender)
m.SetHeader("To", mp.Receiver)
m.SetHeader("Subject", mp.Subject)
m.SetBody("text/html", mp.Content)
d := gomail.NewDialer(mp.Smtp, mp.Port, mp.Sender, mp.AuthCode)
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
log.Printf("send mail to customer error : %s", err)
return err
}
return nil
}
// 检测STMP服务是否可连接
func DialMail(smtp string, port int, sender, authCode string) error {
d := gomail.NewDialer(smtp, port, sender, authCode)
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
_, err := d.Dial()
return err
}
+82
View File
@@ -0,0 +1,82 @@
package dao
import (
"crm/global"
"crm/models"
"time"
)
type MailConfigDao struct {
}
func NewMailConfigDao() *MailConfigDao {
return &MailConfigDao{}
}
func (m *MailConfigDao) Save(param *models.MailConfigSaveParam) error {
if !isExists(param.Creator) {
return create(param)
}
return update(param)
}
func (m *MailConfigDao) GetInfo(uid int64) (*models.MailConfig, error) {
var mc models.MailConfig
err := global.Db.Table(MAIL_CONFIG).Where("creator = ?", uid).First(&mc).Error
if err != nil {
return nil, err
}
return &mc, nil
}
func (m *MailConfigDao) UpdateStatus(param *models.MailConfigStatusParam) error {
mailConfig := models.MailConfig{
Status: param.Status,
Updated: time.Now().Unix(),
}
db := global.Db.Model(&mailConfig).Where("id = ? and creator = ?", param.Id, param.Creator)
if err := db.Updates(&mailConfig).Error; err != nil {
return err
}
return nil
}
func isExists(uid int64) bool {
var mc models.MailConfig
db := global.Db.Table(MAIL_CONFIG).Where("creator = ?", uid).First(&mc)
return db.RowsAffected != NumberNull
}
func create(param *models.MailConfigSaveParam) error {
mailConfig := models.MailConfig{
Stmp: param.Stmp,
Port: param.Port,
AuthCode: param.AuthCode,
Email: param.Email,
Status: 1,
Creator: param.Creator,
Created: time.Now().Unix(),
}
if err := global.Db.Create(&mailConfig).Error; err != nil {
return err
}
return nil
}
func update(param *models.MailConfigSaveParam) error {
mailConfig := models.MailConfig{
Id: param.Id,
Stmp: param.Stmp,
Port: param.Port,
AuthCode: param.AuthCode,
Email: param.Email,
Status: param.Status,
Creator: param.Creator,
Updated: time.Now().Unix(),
}
db := global.Db.Model(&mailConfig).Select("*").Omit("id", "creator", "created")
if err := db.Updates(&mailConfig).Error; err != nil {
return err
}
return nil
}
+7
View File
@@ -39,6 +39,7 @@ func Router() {
route.GET("/customer/option", api.NewCustomerApi().QueryOption)
route.GET("/customer/export", api.NewCustomerApi().Export)
route.POST("/customer/create", api.NewCustomerApi().Create)
route.POST("/customer/send", api.NewCustomerApi().SendMail)
route.PUT("/customer/update", api.NewCustomerApi().Update)
route.DELETE("/customer/delete", api.NewCustomerApi().Delete)
@@ -62,6 +63,12 @@ func Router() {
// 仪表盘模块
route.GET("/dashboard/sum", api.NewDashboardApi().Summary)
// 配置模块
route.GET("/config/info", api.NewMailConfigApi().GetInfo)
route.GET("/config/check", api.NewMailConfigApi().Check)
route.PUT("/config/save", api.NewMailConfigApi().Save)
route.PUT("/config/status", api.NewMailConfigApi().UpdateStatus)
// 订阅模块
route.GET("/subscribe/info", api.NewSubscribeApi().GetInfo)
route.POST("/subscribe/pay", api.NewSubscribeApi().Pay)
+11
View File
@@ -5,3 +5,14 @@ type Page struct {
PageNum int `form:"pageNum" json:"pageNum"`
PageSize int `form:"pageSize" json:"pageSize"`
}
// 发送邮件参数模型
type MailParam struct {
Smtp string
Port int
AuthCode string
Sender string
Subject string
Content string
Receiver string
}
+39
View File
@@ -0,0 +1,39 @@
package models
type MailConfig struct {
Id int64 `gorm:"primaryKey"`
Stmp string `gorm:"stmp"`
Port int `gorm:"port"`
AuthCode string `gorm:"auth_code"`
Email string `gorm:"email"`
Status int `gorm:"status"`
Creator int64 `gorm:"creator"`
Created int64 `gorm:"created"`
Updated int64 `gorm:"updated"`
}
type MailConfigSaveParam struct {
Id int64 `json:"id" binding:"omitempty,gt=0"`
Stmp string `json:"stmp" binding:"omitempty,ip|hostname"`
Port int `json:"port" binding:"omitempty,gt=0"`
AuthCode string `json:"authCode" binding:"omitempty,gt=0"`
Email string `json:"email" binding:"omitempty,email"`
Status int `json:"status" binding:"omitempty,oneof=1 2"`
Creator int64 `json:"creator" binding:"omitempty"`
}
type MailConfigStatusParam struct {
Id int64 `json:"id" binding:"required,gt=0"`
Status int `json:"status" binding:"required,oneof=1 2"`
Creator int64 `json:"creator" binding:"omitempty"`
}
type MailConfigInfo struct {
Id int64 `json:"id"`
Stmp string `json:"stmp"`
Port int `json:"port"`
AuthCode string `json:"authCode"`
Email string `json:"email"`
Status int `json:"status"`
Usability int `json:"usability"`
}
+7
View File
@@ -45,6 +45,13 @@ type CustomerUpdateParam struct {
Status int `json:"status" binding:"-"`
}
type CustomerSendMailParam struct {
Uid int64 `json:"uid" binding:"-"`
Receiver string `json:"receiver" binding:"required,email"`
Subject string `json:"subject" binding:"omitempty,gt=0"`
Content string `json:"content" binding:"required,gt=0"`
}
type CustomerDeleteParam struct {
Ids []int64 `json:"ids" binding:"required"`
}
+7
View File
@@ -23,6 +23,10 @@ const (
ErrCodePayFailed = 20001 // 支付宝支付失败
ErrCodeFileExportFailed = 30001 // 文件导出失败
ErrCodeMailConfigInvalid = 50001 // 邮件服务配置无效
ErrCodeMailSendFailed = 50002 // 邮件发送失败
ErrCodeMailSendUnEnable = 50003 // 邮件服务未开启
)
var msg = map[int]string{
@@ -42,4 +46,7 @@ var msg = map[int]string{
ErrCodeEmailFormatInvalid: "email format invalid",
ErrCodeUserPassResetFailed: "user password reset failed",
ErrCodeFileExportFailed: "file export failed",
ErrCodeMailConfigInvalid: "mail config invalid",
ErrCodeMailSendFailed: "mail send failed",
ErrCodeMailSendUnEnable: "mail send server unEnable",
}
+63
View File
@@ -0,0 +1,63 @@
package service
import (
"crm/common"
"crm/dao"
"crm/models"
"crm/response"
)
type MailConfigService struct {
mailConfigDao *dao.MailConfigDao
}
func NewMailConfigService() *MailConfigService {
return &MailConfigService{
mailConfigDao: dao.NewMailConfigDao(),
}
}
// 保存邮件服务配置
func (m *MailConfigService) Save(param *models.MailConfigSaveParam) int {
if err := m.mailConfigDao.Save(param); err != nil {
return response.ErrCodeFailed
}
return response.ErrCodeSuccess
}
// 开启或关闭邮件服务
func (m *MailConfigService) UpdateStatus(param *models.MailConfigStatusParam) int {
if err := m.mailConfigDao.UpdateStatus(param); err != nil {
return response.ErrCodeFailed
}
return response.ErrCodeSuccess
}
// 获取邮件配置信息
func (m *MailConfigService) GetInfo(uid int64) (*models.MailConfigInfo, int) {
mc, err := m.mailConfigDao.GetInfo(uid)
if err != nil {
return nil, response.ErrCodeFailed
}
mailConfig := models.MailConfigInfo{
Id: mc.Id,
Stmp: mc.Stmp,
Port: mc.Port,
AuthCode: mc.AuthCode,
Email: mc.Email,
Status: mc.Status,
}
return &mailConfig, response.ErrCodeSuccess
}
// 检查邮件配置的有效性
func (m *MailConfigService) Check(uid int64) int {
mc, err := m.mailConfigDao.GetInfo(uid)
if err != nil {
return response.ErrCodeMailConfigInvalid
}
if err = common.DialMail(mc.Stmp, mc.Port, mc.Email, mc.AuthCode); err != nil {
return response.ErrCodeMailConfigInvalid
}
return response.ErrCodeSuccess
}
+30
View File
@@ -9,6 +9,11 @@ import (
"time"
)
const (
Open = 1
Close = 2
)
type CustomerService struct {
}
@@ -57,6 +62,31 @@ func (c *CustomerService) Update(param *models.CustomerUpdateParam) int {
return response.ErrCodeSuccess
}
// 发送邮件给客户
func (c *CustomerService) SendMail(param *models.CustomerSendMailParam) int {
var mc models.MailConfig
err := global.Db.Model(&models.MailConfig{}).Where("creator = ?", param.Uid).First(&mc).Error
if err != nil {
return response.ErrCodeMailSendFailed
}
if mc.Status == Close {
return response.ErrCodeMailSendUnEnable
}
mailParam := models.MailParam{
Smtp: mc.Stmp,
Port: mc.Port,
AuthCode: mc.AuthCode,
Sender: mc.Email,
Subject: param.Subject,
Content: param.Content,
Receiver: param.Receiver,
}
if err := common.SendMailToCustomer(mailParam); err != nil {
return response.ErrCodeMailSendFailed
}
return response.ErrCodeSuccess
}
// 删除客户
func (c *CustomerService) Delete(param *models.CustomerDeleteParam) int {
if err := global.Db.Delete(&models.Customer{}, param.Ids).Error; err != nil {