欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > golang通过飞书邮件服务API发送邮件功能详解

golang通过飞书邮件服务API发送邮件功能详解

2025/4/19 17:10:36 来源:https://blog.csdn.net/zhoupenghui168/article/details/147073554  浏览:    关键词:golang通过飞书邮件服务API发送邮件功能详解

一.需求

需要实现通过飞书邮件服务API发送邮件验证码功能:用户输入邮箱, 点击发送邮件,然后发送邮件验证码, 这里验证码有过期时间, 保存到redis缓存中

二.实现

实现的部分代码如下:

控制器部分代码

// 发送邮件控制器
func EmailSendController(userId uint64, m proto.Message, ctx *gin.Context) (proto.Message, error) {var err errorres := CommonRes(ctx)// 获取请求,将请求转换为具体的类型req, ok := m.(*common.SendEmailCodeReq)if !ok {res.ErrCode = uint64(CodeInvalidRequestType)res.ErrDesc = CodeMap[CodeInvalidRequestType]return res, err}if req.Email == "" {res.ErrCode = uint64(CodeReqDataNotEmpty)res.ErrDesc = CodeMap[CodeReqDataNotEmpty]return res, err}// 实例化飞书结构体emailSender, err := mailer.NewFeishuEmailSender()if err != nil {return res, err}// 发送邮件err = emailSender.SendEmail(req.Email)if err != nil {return res, err}return res, nil
}

 mailer包下feishuEmail.go部分代码

package mailerimport ("bytes""encoding/json""fmt""redisCore""net/http"
)var redisClient redisCore.RedisCoreconst (appID     = "your_app_id"     // 替换为您的飞书应用 IDappSecret = "your_app_secret" // 替换为您的飞书应用 Secret
)// EmailSender 用于发送邮件的结构体
type EmailSender struct {AccessToken string
}// NewEmailSender 创建一个新的 EmailSender 实例
func NewFeishuEmailSender() (*EmailSender, error) {token, err := getAccessToken()if err != nil {return nil, NewError(uint64(CodeSendMsgAccessTokenCheckError), fmt.Errorf("%s: %s", CodeMap[CodeSendMsgAccessTokenCheckError], err.Error()))}return &EmailSender{AccessToken: token}, nil
}// getAccessToken 获取飞书 API 访问令牌
func getAccessToken() (string, error) {url := "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"payload := map[string]string{"app_id":     appID,"app_secret": appSecret,}data, err := json.Marshal(payload)if err != nil {return "", err}resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))if err != nil {return "", err}defer resp.Body.Close()if resp.StatusCode != http.StatusOK {return "", fmt.Errorf("获取访问令牌失败: %s", resp.Status)}var result map[string]interface{}if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {return "", err}accessToken, ok := result["tenant_access_token"].(string)if !ok {return "", fmt.Errorf("未找到访问令牌")}return accessToken, nil
}// SendEmail 发送邮件
func (es *EmailSender) SendEmail(email string) error {code := GetRandomNum()  // 验证码url := "https://open.feishu.cn/open-apis/email/v1/send/"emailData := map[string]interface{}{"email":      email,"subject":    "您的验证码","content":    fmt.Sprintf("您的验证码是: %s", code),"from_email": "system@test.com", // 替换为您的发件邮箱}data, err := json.Marshal(emailData)if err != nil {return NewError(uint64(CodeSendMsgCheckError), fmt.Errorf("%s: json转换错误: %s", CodeMap[CodeSendMsgCheckError], err.Error()))}req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data))if err != nil {return NewError(uint64(CodeSendMsgCheckError), fmt.Errorf("%s: 发送请求错误: %s", CodeMap[CodeSendMsgCheckError], err.Error()))}req.Header.Set("Authorization", "Bearer "+es.AccessToken)req.Header.Set("Content-Type", "application/json")client := &http.Client{}resp, err := client.Do(req)if err != nil {return NewError(uint64(CodeSendMsgCheckError), fmt.Errorf("%s: 发送响应错误: %s", CodeMap[CodeSendMsgCheckError], err.Error()))}defer resp.Body.Close()if resp.StatusCode != http.StatusOK {return NewError(uint64(CodeSendMsgCheckError), fmt.Errorf("%s: 发送邮件失败: %s", CodeMap[CodeSendMsgCheckError], resp.Status))}// 将验证码保存到 Redis,有效期 5 分钟err = redisClient.SaveEmailCode(email, code)if err != nil {return NewError(uint64(CodeSendMsgCheckError), fmt.Errorf("%s: 保存验证码到redis错误: %s", CodeMap[CodeSendMsgCheckError], err.Error()))}return nil
}

redis部分代码


type RedisCore struct {
}var RedisClient *redis.Client// 保存数据到redis
func SetEx(key string, value interface{}, expiration time.Duration) error {err := RedisClient.SetEx(ctxRedis, key, value, expiration).Err()if err != nil {return err}return nil
}// 保存邮件验证码
func (RedisCore) SaveEmailCode(email, code string) error {// 获取邮件验证码keysendEmailTokenKey := pkg.SEND_EMAIL_KEY_PREFIX + ":" + emailerr := SetEx(sendEmailTokenKey, code, 60*time.Second)if err != nil {return err}return nil
}

其他公共方法代码

// 生成随机数
func GetRandomNum() string {var str stringfor i := 0; i < 4; i++ {current := rand.Intn(10)str += strconv.Itoa(current)}return str
}// 自定义错误
func NewError(errCode uint64, err error) error {return New(int32(errCode), err.Error())
}func New(code int32, reason string) error {return &MyError{Code: code, Reason: reason}
}type MyError struct {Code   int32Reason string 
}

好了, 发送邮件操作完成了,上面还有可优化的空间: 比如: 把飞书相关的配置以及邮件模块等放到yml文件中, 通过从yml获取配置信息

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词