SMTP 全名为Simple Mail Transfer Protocol 简单邮件传输协议,它是邮件服务器用来在电子邮件发件人和收件人之间发送、接收和/或中继外发邮件的应用程序。
SMTP 电子邮件服务器将有一个地址(或多个地址),可由您使用的邮件客户端或应用程序设置,通常格式为 smtp.serveraddress.com。例如,Gmail 的 SMTP 服务器主机地址为 smtp.gmail.com,Twilio SendGrid 的为 smtp.sendgrid.com。您通常可以在邮件客户端的帐户或设置部分中找到您的 SMTP 电子邮件服务器地址。
当您发送电子邮件时,SMTP 服务器会处理您的电子邮件,决定将消息发送到哪个服务器,并将消息中继到该服务器。收件人的收件箱服务提供商(例如 Gmail 或 AOL)会下载邮件并将其放入收件人的收件箱中。
理论上是的,他与一般大多服务器相同,SMTP 服务器处理要发送到另一台服务器的数据,但它具有处理与电子邮件发送、接收和中继相关的数据的非常具体的目的。SMTP 服务器也不一定在机器上。它是一个不断运行以期待发送新邮件的应用程序。
这边我们使用"net/smtp"
这个官方的标准库来实现功能。
app/service/smtp.go
package service
import (
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"ironman-2021/app/middleware"
"net/smtp"
"os"
)
func Send(title string, body string, to string) {
envErr := godotenv.Load()
if envErr != nil {
panic(envErr)
}
from := os.Getenv("MAIL_USERNAME")
pass := os.Getenv("MAIL_PASSWORD")
port := os.Getenv("MAIL_PORT")
server := os.Getenv("MAIL_SERVER")
msg := "From: " + from + "\n" +
"To: " + to + "\n" +
"Subject: " + title + "\n" +
body
err := smtp.SendMail(server + ":" + port,
smtp.PlainAuth("", from, pass, server),
from, []string{to}, []byte(msg))
if err != nil{
middleware.Logger().WithFields(logrus.Fields{
"name": "Smtp",
}).Error("error: ", err)
return
}
middleware.Logger().WithFields(logrus.Fields{
"name": "Smtp",
}).Info("Send from: ", from + ", To: ", to)
}
MAIL_USERNAME
, MAIL_PASSWORD
, MAIL_PORT
与MAIL_SERVER
都给load进function来使用。app/controller/user.go
这边我们则是在创建新使用者成功时,发送一封提醒信。
// CreateUser @Summary
// @Tags user
// @version 1.0
// @produce application/json
// @param language header string true "language"
// @param register body Register true "register"
// @Success 200 string successful return value
// @Router /v1/users [post]
func (u UsersController) CreateUser(c *gin.Context) {
t := gi18n.New()
var form Register
bindErr := c.BindJSON(&form)
lan := c.Request.Header.Get("language")
if lan == "" {
lan = "en"
}
t.SetLanguage(lan)
if bindErr == nil {
err := service.RegisterOneUser(form.Account, form.Password, form.Email)
if err == nil {
service.Send("Register Notification", "Welcome to become our membership", form.Email)
c.JSON(http.StatusOK, gin.H{
"status": 1,
"msg": t.Translate(c, "Response_Success"),
"data": nil,
})
} else {
c.JSON(http.StatusInternalServerError, gin.H{
"status": -1,
"msg": "Register Failed" + err.Error(),
"data": nil,
})
}
} else {
c.JSON(http.StatusBadRequest, gin.H{
"status": -1,
"msg": "Failed to parse register data" + bindErr.Error(),
"data": nil,
})
}
}
最後使用者则会收到一封类似下方的mail,同时我们在log也能看到发送成功的信息。
time="131310-10-10 1010:1010:1010" level=info msg="Send from: [email protected], To: [email protected]" name=Smtp
time="131310-10-10 1010:1010:1010" level=info msg="| 200 | 5.7536937s | 192.168.144.1 | POST | /v1/users/ |"
这章节我们实作了如何以smtp转发信件,但这边也遇到了一个小问题,那就是我们因为要等待smtp转发完毕才会将response回给client端,因此我们的response time变长了许多。也因此在下个章节我们要将现行架构结合async
来创造一个更好的使用者体验。
这次的程序码我也会放在下方连结提供参考。
https://github.com/Neskem/Ironman-2021/tree/Day-28
<<: Day28-介接 API(番外篇 III)Dialogflow ES 之 Fulfillment 与 Events
>>: 【Day 28】- 这个验证码有点难破解(应对反爬虫技术-验证码篇)
近期将依些老程序转移至微服务上, 因为原本程序使用了大量 out 语法, 为了能够让微服务的 API...
伫列定义 具有线性串列结构,资料遵循着先进先出,後进後出的存取顺序 实际使用 一、手枪的子弹 二、电...
昨天介绍完SMO算法第三步,今天就要来写这个方法第四步, 昨天我们得到aj,接下来要使用aj来更新a...
理想上 一个组织只要慎用选择人才 这些精挑细选而来的员工就会永远发光发热 BUT 有时候是你用人辜...
今天我们来看一下 powershell 中的循环。在 powershell 有两种循环,一种 for...