Go 语言封装邮件发送功能

news2025/4/1 14:14:49

Go 语言封装邮件发送功能

  • 🏆 目标
  • 📦 依赖包
  • 🌟 项目结构
  • 🚀 代码实现
  • 🛠️ 主要方法说明
  • 🧪 单元测试
  • 🌈 使用示例
  • 🏆 代码亮点
  • 🌟 改进方向
  • 🚀 总结

在现代 Web 开发中,邮件发送功能是一个常见的需求,特别是在用户注册、密码重置、通知等场景中,往往需要通过邮件发送验证码或其他信息。本文将介绍如何在 Go 语言中封装一个通用的邮件发送包,支持验证码发送和通用邮件发送。


🏆 目标

封装一个邮件发送的包

支持 SMTP 协议发送邮件

提供发送验证码和普通邮件的功能

通过结构体和方法实现面向对象的设计

完善的单元测试,确保代码健壮性


📦 依赖包

在开始之前,需要引入以下依赖包:

go get github.com/jordan-wright/email
go get go.uber.org/zap
go get github.com/stretchr/testify
github.com/jordan-wright/email:一个常用的 Go 语言邮件发送库,简化 SMTP 发送流程。

go.uber.org/zap:Uber 开发的高效日志库,用于记录日志。

github.com/stretchr/testify:Go 的单元测试库。

🌟 项目结构

├── email
│   ├── email.go
│   └── email_test.go
├── model
│   └── cache.go
├── pkg
│   └── logger.go
├── go.mod
├── go.sum
└── main.go

🚀 代码实现

📌 email/email.go
创建 email/email.go 文件,封装邮件发送功能。

package email

import (
	"fmt"
	"gin-mall/model"
	"gin-mall/pkg/logger"
	"net/smtp"
	"time"

	"github.com/jordan-wright/email"
	"go.uber.org/zap"
)

// Email 邮件
type Email struct {
	config  Config   // 邮件配置
	From    string   // 发件人
	To      []string // 收件人
	Subject string   // 主题
	Body    string   // 内容
}

// Config 邮件配置
type Config struct {
	SMTPServer string // SMTP服务器
	SMTPPort   int    // SMTP端口
	Username   string // 用户名
	Password   string // 密码
}

// NewEmail 创建Email实例
func NewEmail(config Config) *Email {
	e := &Email{config: config}
	e.From = config.Username
	return e
}

// SetFrom 设置发件人
func (e *Email) SetFrom(from string) {
	e.From = from
}

// SetTo 设置收件人
func (e *Email) SetTo(to []string) {
	e.To = to
}

// AppendTo 添加收件人
func (e *Email) AppendTo(to string) {
	e.To = append(e.To, to)
}

// SetSubject 设置邮件主题
func (e *Email) SetSubject(subject string) {
	e.Subject = subject
}

// SetBody 设置邮件内容
func (e *Email) SetBody(body string) {
	e.Body = body
}

// Send 发送邮件
func (e *Email) Send() error {
	auth := smtp.PlainAuth("", e.config.Username, e.config.Password, e.config.SMTPServer)

	host := fmt.Sprintf("%s:%d", e.config.SMTPServer, e.config.SMTPPort)

	eClient := email.NewEmail()
	eClient.From = e.From
	eClient.To = e.To
	eClient.Subject = e.Subject
	eClient.Text = []byte(e.Body)

	err := eClient.Send(host, auth)
	if err != nil {
		return err
	}

	return nil
}

// SendVerifyCode 发送验证码
func (e *Email) SendVerifyCode(receiver, code, key string) error {
	// 保存验证码到缓存
	err := model.CacheDb.Set(key, code, 5*time.Minute)
	if err != nil {
		logger.Error("设置缓存失败", zap.Error(err))
		return err
	}

	// 发送邮件
	msg := fmt.Sprintf("【XXX】您的验证码是: %s, 请在5分钟内完成验证.", code)
	e.AppendTo(receiver)
	e.SetSubject("GinMall 验证码")
	e.SetBody(msg)

	return e.Send()
}

🛠️ 主要方法说明

方法名功能说明
NewEmail创建新的邮件实例通过传入 SMTP 配置,创建 Email 结构体
SetFrom设置发件人可自定义发件人
SetTo设置收件人直接设置收件人数组
AppendTo添加收件人动态添加收件人
SetSubject设置主题设置邮件的标题
SetBody设置内容设置邮件的内容
Send发送邮件通过 SMTP 协议发送邮件
SendVerifyCode发送验证码生成并发送验证码

🧪 单元测试

📌 email/email_test.go
创建 email/email_test.go,对邮件发送功能进行测试。

package email

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSendEmail(t *testing.T) {
	config := Config{
		SMTPServer: "smtp.163.com",
		SMTPPort:   25,
		Username:   "your-email@163.com",
		Password:   "your-password",
	}

	email := NewEmail(config)
	assert.NotNil(t, email)

	email.SetFrom(config.Username)
	email.AppendTo("receiver@example.com")
	email.SetSubject("Test Email")
	email.SetBody("This is a test email.")

	err := email.Send()
	assert.Nil(t, err)

	t.Logf("Email sent successfully")
}

🌈 使用示例

在 main.go 文件中直接调用封装好的方法来发送邮件:

package main

import (
	"log"
	"gin-mall/email"
)

func main() {
	config := email.Config{
		SMTPServer: "smtp.163.com",
		SMTPPort:   25,
		Username:   "your-email@163.com",
		Password:   "your-password",
	}

	email := email.NewEmail(config)
	email.SetFrom(config.Username)
	email.AppendTo("receiver@example.com")
	email.SetSubject("Welcome to GinMall")
	email.SetBody("Thank you for signing up to GinMall!")

	err := email.Send()
	if err != nil {
		log.Fatalf("Failed to send email: %v", err)
	} else {
		log.Println("Email sent successfully")
	}
}

🏆 代码亮点

✅ 面向对象设计,封装良好
✅ 使用 go.uber.org/zap 记录日志
✅ 使用 github.com/jordan-wright/email 简化 SMTP 发送
✅ 使用 github.com/stretchr/testify 进行单元测试


🌟 改进方向

  1. 支持 HTML 格式的邮件内容

  2. 支持添加附件

  3. 通过配置文件设置邮件参数

  4. 添加邮件发送失败的重试机制


🚀 总结

通过封装 github.com/jordan-wright/email,我们可以快速实现邮件发送功能。封装良好的结构体和方法,使代码更易于扩展和复用。希望本文能帮助你在 Go 项目中高效地实现邮件功能!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2322101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Thales靶机攻略

1.下载导入VBox,并启动靶机 靶机地址:https://download.vulnhub.com/thales/Thales.zip 解压后,在VBox中导入虚拟电脑。包含所有网卡的MAC地址。 导入完成,设置网卡模式为仅主机网络。开启靶机。 kali网卡更改为桥接模式。点击工…

尝试使用Tauri2+Django+React项目(2)

前言 尝试使用tauri2DjangoReact的项目-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146403103在前面笔者不知道怎么做,搞了半天 笔者看到官网,原来可以使用二进制文件,好好好 嵌入外部二进制文件 | Taurihttps://v2.taur…

6.1 模拟专题:LeetCode 1576. 替换所有的问号

1. 题目链接 LeetCode 1576. 替换所有的问号 2. 题目描述 给定一个仅包含小写字母和问号 ? 的字符串 s,要求将所有 ? 替换为任意小写字母,使得替换后的字符串中 没有相邻的两个字符相同。 示例: 输入:s "?zs" →…

Linux安装go环境

安装一个lazydocker,根据文档需要先安装go环境 https://github.com/jesseduffield/lazydocker 官方文档解析 https://go.dev/doc/install 文档内容如下,一共三步 1.删除先前安装的go,解压下载的go压缩包到/usr/local目录 2.添加环境变量&…

卡特兰数在数据结构上面的运用

原理 Catalan数是一个数列,其第n项表示n个不同结点可以构成的二叉排序树的数量。Catalan数的第n项公式为:  其中,是组合数,表示从2n个元素中选择n个元素的组合数。 Catalan数的原理可以通过以下方式理解&…

悟空crm v12安装好后出现 网络错误问题(已解决)

请求网址: http://wwww.aaaa.com/gateway/adminUser/queryUserNumInfo 请求方法: POST 状态代码: 502 Bad Gateway 远程地址: 101.37.79.226:9807 引荐来源网址政策: strict-origin-when-cross-origin

便携版:随时随地,高效处理 PDF 文件

PDF-XChange Editor Plus 便携版是一款功能强大且极其实用的 PDF 阅读与编辑工具。它不仅支持快速浏览 PDF 文件,还提供了丰富的编辑功能,让用户可以轻松处理 PDF 文档。经过大神优化处理,这款软件已经变得十分轻便,非常适合需要随…

【Golang】补充:占位符、转义字符、错误处理

🔥 个人主页:星云爱编程 🔥 所属专栏:Golang 🌷追光的人,终会万丈光芒 🎉欢迎大家点赞👍评论📝收藏⭐文章 1、占位符 1.1通用占位符 %v :默认格式的值。适…

文件上传绕过的小点总结(4)

9.末尾点删除处理缺陷 给出源码: $file_name trim($_FILES[upload_file][name]); $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_ext strtolower($file_ext); //转换为小写 $file_ext str_ireplace(::$DATA,…

如何用Spring AI构建MCP Client-Server架构

现代 Web 应用正加速与大语言模型(LLMs)深度融合,构建超越传统问答场景的智能解决方案。为突破模型知识边界,增强上下文理解能力,开发者普遍采用多源数据集成策略,将 LLM 与搜索引擎、数据库、文件系统等外部资源互联。然而,异构数据源的协议差异与格式壁垒,往往导致集…

如何让WordPress不同的页面、栏目显示不同的小工具侧边栏

WooSidebars 是一款用于 WordPress 的插件,主要功能是允许用户根据不同的上下文条件(如特定页面、博客文章、分类目录或搜索结果页面等)来更改侧边栏中显示的小工具。 自定义小工具区域:用户可以轻松创建自定义的小工具区域,并将其设置为在多种条件下显示,只需点击几次即…

智慧座椅的节能效果如何?

嘿呀,你知道不,咱这叁仟智慧座椅的节能效果,那可是像个神秘小宇宙,根据不同的技术和应用场景,会展现出超有趣的变化哦,下面就给你唠唠常见的几种情况哈! 能源回收大变身:有些叁仟智…

Matlab:二维绘图篇——不同坐标系下的绘图命令

目录 1.极坐标系下绘图:polar命令 实例——极坐标图形 实例——直角坐标与极坐标系图形 2.半对数坐标系下绘图:semilogx和semilogy 实例——半对数坐标系图形 3.双对数坐标系下绘图:loglog 实例——双对数坐标系绘图 4.双y轴坐标&…

对三维物体模型的阈值操作

对三维物体模型的阈值操作 1. 使用point_coord_x、point_coord_y、point_coord_z阈值分割麻辣兔头2. point_normal_x、point_normal_y、point_normal_z有什么区别?3. 去除离群点 1. 使用point_coord_x、point_coord_y、point_coord_z阈值分割麻辣兔头 dev_open_win…

prometheus 添加alertmanager添加dingtalk机器人告警

1、dingtalk创建机器人,目前我们采用加白名单的方式校验 2、定位到如下图 test结果如下

向量数据库学习笔记(1) —— 基础概念

一、 嵌入模型 Embedding Models 嵌入模型是将复杂数据(如文本、图像、音频等)转换为向量表示的机器学习模型 1. 核心概念 嵌入(Embedding):将高维、非结构化的数据映射到低维、稠密的向量空间 向量表示:输出固定长度的数值向量…

【算法】动态规划:回文子串问题、两个数组的dp

⭐️个人主页:小羊 ⭐️所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 回文子串问题回文子串最长回文子串分割回文串 IV分割回文串 II *最长回文子序列让字符串成为回文串的最少插入次数 两个数组的dp最…

文件上传绕过的小点总结(3)

6.文件首尾加空绕过 源码给出这样的,发现文件名处理没有首尾去空,于是我们可以采用首尾加空的方式绕过。 $file_name $_FILES[upload_file][name]; $file_name deldot($file_name);//删除文件名末尾的点 $file_ext strrchr($file_name, .); $file_e…

OpenHarmony 入门——ArkUI 跨页面数据同步和应用全局单例的UI状态存储AppStorage 小结(三)

文章大纲 引言一、AppStorage 应用全局的UI状态存储1、StorageProp和StorageLink装饰器建立联系2、StorageProp2.1、StorageProp使用规则2.2、StorageProp变量的传递/访问规则2.3、StorageProp支持的观察变化2.4、StorageProp 值初始化和更新 3、StorageLink3.1、StorageLink使…

阿里云国际站代理商:物联网设备怎样就近接入计算节点?

配置边缘计算实例 登录边缘计算控制台,找到已创建的边缘实例,点击实例名称后的“查看”。 分配OPC UA驱动到边缘实例中,选择OPCUA驱动,点击“设备列表”后的“驱动配置”,在弹出对话框中点击“添加通道”,…