Go:实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)

news2024/11/26 0:29:54

需求很简单,就是用户输入自己的邮箱后,使用官方邮箱给用户发送替邮件模版

在这里插入图片描述

目录

  • 前置
    • 邮件模版
    • 邮箱开启SMTP服务
      • 163邮箱
      • 163企业邮箱
      • 谷歌gmail邮箱
      • 腾讯企业邮箱-失败
      • 其他邮箱-未操作
  • 邮件发送核心代码
    • config.yaml配置
    • 读取邮件相关配置
    • 发送邮件
  • 附录

前置

邮件模版

邮件模版类似如下图发来的欢迎加入的模版
在这里插入图片描述

这里我们使用html格式存储模版,上图源码如下

<html lang="en-US" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>email</title>
    <style>
        a{
            color: #ECC94B !important;
        }
        .foot-text{
            color: rgba(0, 0, 0, 0.50) !important;
        }
    
        .im{
            color:rgba(0,0,0,0.86) !important;
        }

        .center {
            display: flex;
            justify-content: center;
            align-items: center;
            
}
    </style>
</head>
<body style="background-color: white;">
<div style="width: 640px;height: auto;border-radius: 5px;margin: 0 auto;position: relative; padding-bottom: 80px; padding-top: 20px">
    <div>
        <img width="640" src="file:///Users/yanzhixing/Downloads/My/文档/HatchfulExport-All/linkedin_banner_image_2.png" alt="">
    </div>
    <div style="color: rgba(0,0,0,0.86);font-family: 'Roboto','Century Gothic', 'Trebuchet MS', 'Hiragino Sans GB', 微软雅黑, 'Microsoft Yahei', Tahoma, Helvetica, Arial, 'SimSun', sans-serif;font-size: 16px;margin: 10px auto 0px">
        <h2 style="font-size: 20px;font-weight: 700; color: #000">Dear KunZhi Fans,</h2>
        <div>
            <p style="margin: 16px 0; ">Welcome to the family! We are glad to have you on board as a subscriber to my blog.</p >
            <p style="font-weight: 600; color: #000;">Get the latest on <a style="color: #000" href="https://kunzhi.blog.csdn.net/">CSDN</a> and give me a follow if you haven't already.</p>
            <p style="margin: 16px 0">
                <p style="font-weight: 600; color: #000">🧑🏻 About Me</p>
                <p style="margin-bottom: 8px">Former Alibaba programmer, now working for a blockchain company. He is a blogger in the domestic Internet circle, an expert blogger on Alibaba Cloud, and the manager of CSDN Hangzhou City Community. Welcome to communicate and win-win cooperation.</p>
            </p >

            <div style="margin: 16px 0">
                <p style="font-weight: 600; color: #000;">📇 Contact Me</p>
                <p style=" margin-bottom: 8px">Should you have any questions, require assistance, or want to dive deeper into any aspect, you can reach out to me through various channels:</p>

                <div>
                    <p style="margin-bottom: 0; display: flex; margin-bottom: 4px">
                        <span style="margin: 0 8px"></span>
                        <span>Wechat: Follow me <a style="color: #ECC94B;text-decoration: none " target="_blank">kunzhi96</a> to communicate and learn together.</span>
                        <div class="center">
                            <img width="200" src="file:///Users/yanzhixing/Downloads/My/私人/微信二维码.png" alt="">
                        </div>
                    </p>
                    <p style="margin: 0; display: flex; margin-bottom: 4px">
                        <span style="margin: 0 8px"></span>
                        <span>CSDN Blog: Visit my blog -<a style="color: #ECC94B; text-decoration: none" target="_blank" href="https://kunzhi.blog.csdn.net/">鲲志说</a> for in-depth information about my learning content and technology sharing.</span>
                    </p>
                    <p style="margin: 0; display: flex; margin-bottom: 4px">
                        <span style="margin: 0 8px"></span>
                        <span> Email: Feel free to contact us via email at <span style="color: #ECC94B; opacity: 1;">XXX@163.com</span> for any inquiries, feedback, or support needs.</span>
                    </p>
                </div>
                <p style="margin-bottom: 0px">I'm excited to embark on this journey with you.</p>
            </div >
            <p>Warm regards,</p>
            <p>Kun Zhi</p>
            <div style="background-color: #F7F7F7; padding: 40px; text-align:center;">
                <p style="font-size: 24px;font-weight: 700; color: #000;  margin-bottom: 24px; margin-top: 0">KunZhi</p>
                <p style="margin-bottom: 8px; margin-top: 0">This email was send to <span style="color: #ECC94B; opacity: 1;">xxx@gmail.com</span></p>
                <p style="margin-bottom: 24px; margin-top: 0">You’ve received it because you’ve subscribed to our newsletter.</p>
                <div>
                    <a style="color: rgba(0, 0, 0, 0.50); text-decoration: underline" href="unsubscribe_url/unsubscribe?email=unsubscribe_email" class="foot-text">Unsubscribe</a>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

邮箱开启SMTP服务

选择好官方邮箱来开启smtp服务,这里我测试验证了163邮箱、163企业邮箱、谷歌gmail邮箱和腾讯企业邮箱(但腾讯企业邮箱未成功,后续会说明)

163邮箱

  1. 登录163邮箱(一定不要登录到简易版啊)

  2. 登录后如下图所示,点击上面导航栏的设置
    在这里插入图片描述

  3. 按照下图顺序点击 POP3/SMTP/IMAP
    在这里插入图片描述

  4. 开启SMTP服务

如下图我已经是开启状态了
在这里插入图片描述
5. 新增授权密码
如上图,我们如果需要使用SMTP服务,就一定要使用授权码,而且这个密码只出现一次,一定要记得保存好,保存好先留着,我们后面会用到

6.服务器地址及端口

我们使用的是SMTP服务,则对应的服务器地址是smtp.163.com,端口为25,后面都会用到
在这里插入图片描述

自此,163邮箱的smtp服务开启完毕,可直接跳到邮件发送源码处继续即可


163企业邮箱

  1. 登录163企业邮箱

可以看到登录的是网易灵犀办公界面
在这里插入图片描述

  1. 登录后如下图所示,点击上面导航栏的设置-账号与安全-客户端设置
    在这里插入图片描述
  2. 进入客户端设置

可看到如下图

  • 选择IMAP协议
  • 开启并设置客户端授权密码
    在这里插入图片描述
  1. 新增授权密码
    如上图,生成授权码,而且这个密码只出现一次,一定要记得保存好,保存好先留着,我们后面会用到。

可以看到163企业邮箱不同的是,有一个到期时间,也就意味着,到期了,我们需要更换授权码,这一点需要谨记

  1. 服务器地址及端口

我们使用的是SMTP服务,则对应的服务器地址是smtphz.qiye.163.com,端口为25,后面都会用到
在这里插入图片描述

自此,163企业邮箱的smtp服务开启完毕,可直接跳到邮件发送源码处继续即可


谷歌gmail邮箱

  1. 登录 谷歌gmail邮箱
  2. 点击设置-查看所有设置
    在这里插入图片描述
  3. 点击转发和 POP/IMAP 标签页,如下图进行启用设置,并保存更改
    在这里插入图片描述
  4. 创建和使用应用专用密码
  • 前往您的 Google 帐号-选择安全性

  • 在“登录 Google”下方,选择两步验证
    在这里插入图片描述

  • 在页面底部,选择应用专用密码,进行点击
    在这里插入图片描述

  • 输入一个名称,以帮助您记住在什么情况下使用应用专用密码,如我的kunzhi-test
    在这里插入图片描述

  • 选择创建后,会出现如下弹窗。设备的应用专用密码即生成了,是指在设备上生成的 16 个字符的代码。也就是授权码,而且这个密码只出现一次,一定要记得保存好,保存好先留着,我们后面会用到。在这里插入图片描述

  • 选择完成,记得应用名称对应的密码即可
    在这里插入图片描述

  1. 服务器地址及端口

我们使用的是SMTP服务,则对应的服务器地址是smtp.gmail.com,端口为587,后面都会用到
在这里插入图片描述
自此,谷歌gmail邮箱的smtp服务开启完毕,可直接跳到邮件发送源码处继续即可


腾讯企业邮箱-失败

腾讯企业邮箱失败的原因是因为一直没有找到授权码在哪里进行设置,同时使用邮箱的密码作为授权码也无法发送邮件,所以一直没有实现,但是前面的操作步骤可以放出来供大家参考,如果有人找到了腾讯企业邮箱的操作方法请一定要评论区给出解法。

  • 企业微信管理后台

  • 开启腾讯企业邮箱的POP/SMTP/IMAP服务
    在这里插入图片描述

  • 企业邮箱服务器及端口号设置

其他邮箱-未操作

这个链接的操作我并未实际执行,需要的可以参考

  • 发件服务设置-包含:阿里云邮箱设置、Outlook邮箱设置

邮件发送核心代码

config.yaml配置

这里是发送邮件的邮箱相关配置,这里就使用到之前只出现一次的授权码了,以及对应的服务器地址和端口

email:
# 163邮箱
  template_dir: /test.html
  smtp_server: smtp.163.com
  smtp_port: 25
  smtp_user: KunZhi
  smtp_password: 授权码
  from_email: XXXX@163.com

# 腾讯企业邮箱
  # smtp_server: smtp.exmail.qq.com
  # smtp_port: 465
  # smtp_user: KunZhi
  # smtp_password: 授权码
  # from_email: XXXX

# 163企业邮箱
  # smtp_server: smtphz.qiye.163.com
  # smtp_port: 25
  # smtp_user: KunZhi
  # smtp_password: 授权码
  # from_email: XXXX

  
# gmail
#   smtp_server: smtp.gmail.com
#   smtp_port: 587
#   smtp_user: KunZhi
#   smtp_password: 授权码
#   from_email: XXXX@gmail.com

这里的smtp_user如下图,就是展示的发件人名称
在这里插入图片描述

读取邮件相关配置

	//读取邮件相关配置
	err = sendWelcomeEmail(Cfg{
		SenderAddress:  viper.GetString("email.from_email"),
		SenderName:     viper.GetString("email.smtp_user"),
		SenderPwd:      viper.GetString("email.smtp_password"),
		MailServerHost: viper.GetString("email.smtp_server"),
		MailServerPort: viper.GetString("email.smtp_port"),
	}, viper.GetString("email.from_email"), toEmail, unsubscribeUrl)
	if err != nil {
		errors.Errorf("Failed to send email: ", toEmail, err)
		responseData := gin.H{
			"message": "Failed to send email: " + toEmail,
			"code":    -1,
		}
		c.JSON(http.StatusOK, responseData)
		return err
	}

发送邮件


func sendWelcomeEmail(cfg Cfg, template string, recipientEmail, unsubscribeUrl string) error {
	currentDir, err2 := os.Getwd()

	if err2 != nil {
		log.Fatalf("Failed to get current working directory: %v", err2)
	}
    //获取邮件模版
	htmlContent, err3 := ioutil.ReadFile(currentDir + viper.GetString("email.template_dir"))

	if err3 != nil {
		fmt.Println("Failed to read HTML file:", err3)
		return err3
	}

	// 邮件标题
	subject := "Your Journey Begins Here"
	message := string(htmlContent)
	// 需要替换邮件模版中的字符串映射
	replacements := map[string]string{
		"xxx@gmail.com":     recipientEmail,
		"header_img":        viper.GetString("img.header_img"),
	}
	// 替换字符串
	for oldStr, newStr := range replacements {
		message = strings.Replace(message, oldStr, newStr, -1) // -1 表示替换所有匹配项
	}

	// 连接到 SMTP 服务器并发送电子邮件
	auth := smtp.PlainAuth("", cfg.SenderAddress, cfg.SenderPwd, cfg.MailServerHost)
	to := []string{recipientEmail}
	msg := []byte("To: " + recipientEmail + "\r\n" +
		"Subject: " + subject + "\r\n" +
		"From: " + cfg.SenderName + " <" + cfg.SenderAddress + ">\r\n" +
		"MIME-Version: 1.0\r\n" +
		"Content-Type: text/html; charset=utf-8\r\n" + // 将内容类型设置为 HTML
		"\r\n" + message)

	//发送邮件
	err := smtp.SendMail(cfg.MailServerHost+":"+cfg.MailServerPort, auth, cfg.SenderAddress, to, msg)
	if err != nil {
		fmt.Println("failed to send email:", err)
		return err
	}

	return nil
}

如上代码,可以实现SMTP邮件发送订阅功能,如有任何问题欢迎私聊或评论区留言


附录

  • 163帮助中心
  • 163邮箱无法发送邮件发生退信问题 550 User has no permission以及554, DT:SPM的解决办法
  • 163企业邮箱帮助中心-灵犀办公客户端的设置方法
  • 谷歌邮箱-使用应用专用密码登录

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

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

相关文章

深度学习笔记之线性代数

深度学习笔记之线性代数 一、向量 在数学表示法中&#xff0c;向量通常记为粗体小写的符号&#xff08;例如&#xff0c;x&#xff0c;y&#xff0c;z&#xff09;当向量表示数据集中的样本时&#xff0c;它们的值具有一定的现实意义。例如研究医院患者可能面临的心脏病发作风…

Ubuntu系统初始设置

更换国内源 安装截图工具 安装中文输入法 安装QQ 参考&#xff1a; 安装双系统win10Ubuntu20.04LTS&#xff08;详细到我自己都害怕&#xff09; 引导方式磁盘分区方法UEFIGPTLegancyMBR 安装网络助手 sudo apt install net-tools 安装VS Code 使用从官网下载.deb安装包…

MySQL使用Xtrabackup在线做主从

1、主库上操作 1.1前提 172.16.11.2&#xff08;主库&#xff09; 172.16.11.4&#xff08;从库&#xff09; 在执行备份之前&#xff0c;确保数据库没有锁定&#xff0c;以避免备份期间的任何写操作。 确保主库上的 MySQL 服务器正在运行&#xff0c;以便备份数据的一致性。…

八、2023.10.2.Linux(二).8

文章目录 17、简述一下虚拟内存和物理内存&#xff0c;为什么要用虚拟内存&#xff0c;好处是什么&#xff1f;18、虚拟地址到物理地址怎么映射的&#xff1f;19、说说堆栈溢出是什么&#xff0c;会怎么样&#xff1f;20、简述操作系统中malloc的实现原理?21、说说进程空间从高…

uboot启动流程-涉及board_init_f 函数

一. uboot启动流程 _main 函数中会调用 board_init_f 函数&#xff0c;本文简单分析一下 board_init_f 函数。 二. board_init_f 函数 board_init_f 函数主要有两个工作&#xff1a; (1) 初始化一系列外设&#xff0c;比如串口、定时器&#xff0c;或者打印一些消息等。…

Docker Tutorial

什么是Docker 为每个应用提供完全隔离的运行环境 Dockerfile&#xff0c; Image&#xff0c;Container Image&#xff1a; 相当于虚拟机的快照&#xff08;snapshot&#xff09;里面包含了我们需要部署的应用程序以及替它所关联的所有库。通过image&#xff0c;我们可以创建很…

音乐创作软件:ToneLIB Jam v4.7.8 Crack

从强大的选项卡编辑器到 3D 模式 Tonelib Jam 是一款用于播放和创作音乐的综合软件应用程序。TL Jam专为初学者和经验丰富的吉他手而设计&#xff0c;可以提供一个完美的平台来掌握乐器&#xff0c;让您轻松学习自己喜欢的歌曲或设置高效的日常吉他练习程序。TL Jam 具有功能强…

目标检测|边框检测框转换,交并比计算 代码实现

文章目录 1. 相互转换的函数2.交并比实现 在目标检测任务中&#xff0c;非常重要的一部分就是框出检测框 这就需要检测框的位置大小等一些信息 一般我们有如下两种方式标记一个检测的位置和大小 1 两点法 检测框左上角坐标(x1,y1)&#xff0c;检测框右下角坐标&#xff08;x2…

2023年最新云存储工具排行榜:找到适合你的云存储服务

随着数据规模的不断增长&#xff0c;传统的本地存储已经无法满足用户的需求。云存储工具通过提供灵活、安全和高效的数据存储服务&#xff0c;成为了现代化的数据管理方式。在众多云存储工具中&#xff0c;有一些在功能和性能方面表现出色&#xff0c;成为用户首选。下面是2023…

时间序列-AR模型与MA模型的原理与实现

文章目录 1 自回归模型AR Model1.1 自回归模型 vs 多元线性回归模型1.1.1 线性回归1.1.2 AR(1)模型1.1.3 AR(p)模型 1.2 AR建模问题 2 移动平均模型 MA Model2.1 MA模型的数学表示2.1.1 MA(1)模型2.2.2 MA(q)模型 2.2 MA建模问题 ARIMA模型是AR模型&#xff08;自回归模型&…

计算机网络(二):物理层

参考引用 计算机网络微课堂-湖科大教书匠计算机网络&#xff08;第7版&#xff09;-谢希仁 1. 物理层的基本概念 物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流物理层为数据链路层屏蔽了各种传输媒体的差异&#xff0c;使数据链路层只需要考虑如何完成本…

levelDB引擎

一、背景 1.1、影响磁盘性能的因素&#xff1a; 主要受限于磁盘的寻道时间&#xff0c;优化磁盘数据访问的方法是尽量减少磁盘的IO次数。磁盘数据访问效率取决于磁盘IO次数&#xff0c;而磁盘IO次数又取决于数据在磁盘上的组织方式。磁盘数据存储大多采用B树类型数据结构&…

排序篇(三)----交换排序

排序篇(三)----交换排序 1.冒泡排序 基本思想: ​ 通过不断地比较相邻的元素&#xff0c;将较大的元素往后移动&#xff0c;从而实现排序的目的。 具体的步骤如下&#xff1a; 从待排序的数组中选择相邻的两个元素进行比较&#xff0c;如果前一个元素大于后一个元素&#…

Java编程技巧:swagger2、knif4j集成SpringBoot或者SpringCloud项目

目录 1、springbootswagger2knif4j2、springbootswagger3knif4j3、springcloudswagger2knif4j 1、springbootswagger2knif4j 2、springbootswagger3knif4j 3、springcloudswagger2knif4j 注意点&#xff1a; Api注解&#xff1a;Controller类上的Api注解需要添加tags属性&a…

在云服务器上打开ftp服务-踩坑及心得

我们产生这个需求的原因是因为打算搭建一个博客&#xff0c;选择了使用wordpress框架。然后&#xff0c;在安装插件的过程中&#xff0c;需要使用FTP服务进行操作。于是&#xff0c;我们决定搞清楚这个过程&#xff0c;并在其中遇到的困难进行记录。 一、安装vsftpd # 安装 s…

python生成中金所期权行权价

参考沪深300股指期权的合约表&#xff0c;写一个工具函数&#xff1a; 使用方法 def get_format_option_gap(value: float, deviation: int 0): # 根据中证1000指数获取点位"""根据标准的行权价&#xff0c;生成不同档位的期权列表&#xff0c;适合中金所:…

铁道货车通用技术条件

声明 本文是学习GB-T 5600-2018 铁道货车通用技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 90 mm90 mm。 B.2 制造要求 B.2.1 车体钢结构组成后&#xff1a; a) 敞车钢质侧、端板的平面度公差应小于或等于15 mm/m; 压型侧、端板的平面度…

S0003-Mac下iTerm2+zsh+ohmyzsh打造优雅美观终端

背景 优雅耐看的终端工具&#xff0c;必是每个程序员的追求。 本人也不例外&#xff0c;从业几年先后使用过&#xff1a; windows电脑&#xff1a;cmd、git bash、wsl zsh、terminal zshMac电脑: 自带terminal、iTerm2、terminal zsh 其中windows terminal zsh、mac ter…

数据结构——二叉树的基本概念及顺序存储(堆)

目录 一.前言 二.树概念及结构 2.1 树的概念 2.2 树的相关概念 2.3 树的表现 2.4 树在实际中的应用&#xff08;表示文件系统的目录树结构&#xff09; 三.二叉树的概念及结构 3.1 概念 3.2 特殊的二叉树 3.3 二叉树的性质 3.4 二叉树的存储结构 3.4.1 顺序存储 3…

Vitamin K

各位 比对 机制 --Mechanism of Action of Vitamin K Carboxylase (VKC).IV. Intermediates and Transition State-davis2007.pdf --Mechanism of Action of Vitamin K Carboxylase (VKC).IV. Intermediates and Transition State-davis2007.pdf -- 维生素K的作用机制-dow…