タダです.
前回記事の続きになります.SendGrid のバウンス発生を Golang で取得するまでやったので,その結果を Slack に通知してみました.この記事でその模様をまとめます.
sadayoshi-tada.hatenablog.com
前回記事の振り返り
前回記事では SendGrid API を叩いて bounceDetail
の構造体に指定したレスポンスデータを返すところまで書きました.そのため,今回はレスポンスデータを返して以降の Slack 投稿までのコードをまとめます.
前回記事のコード
package main
import (
"encoding/json"
"fmt"
"strconv"
"time"
sendgrid "github.com/sendgrid/sendgrid-go"
)
type bounceDetail struct {
Created int `json:"created"`
Email string `json:"email"`
Reason string `json:"reason"`
Status string `json:"status"`
}
func getBounceMail(apiKey string) ([]bounceDetail, error) {
var bounceDetail []bounceDetail
startTime := time.Now().Add(-10 * time.Minute).Unix()
endTime := time.Now().Unix()
req := sendgrid.GetRequest(apiKey, "/v3/suppression/bounces", "https://api.sendgrid.com")
req.Method = "GET"
queryParams := make(map[string]string)
queryParams["start_time"] = strconv.FormatInt(startTime, 10)
queryParams["end_time"] = strconv.FormatInt(endTime, 10)
req.QueryParams = queryParams
res, err := sendgrid.API(req)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
if err := json.Unmarshal([]byte(res.Body), &bounceDetail); err != nil {
fmt.Println(err)
return nil, err
}
return bounceDetail, nil
}
バウンスの発生を受け取ってから Slack 投稿までのコード
バウンスの発生を受け取りを getBounceMail()
で行い,そのレスポンスを response
変数に入れています.その後,for 文を回して BouncePostData
構造体に定義したフィールドにマッピングして配列化し,sendSlack
を使って Slack に投稿する形です.10分の間隔でその時間帯内におけるバウンスの発生を確認しますが,1件のバウンスメールに付き1個の通知が出て,バウンスの数分その投稿が増える形になるため,1つのメッセージにすべてのバウンスメールと原因をまとめたい場合は,工夫が必要になりますmm
コード抜粋
type SendGridBounceResult struct {
Result string `json:"result"`
}
type SlackPayload struct {
UserName string `json:"username"`
Text string `json:"text"`
}
type BouncePostData struct {
Email string `json:"email"`
Reason string `json:"reason"`
}
func sendSlack(webhookUrl string, bounceDetails []BouncePostData) error {
for _, message := range bounceDetails {
payload, err := json.Marshal(
SlackPayload{
UserName: "バウンスチェック",
Text: fmt.Sprintf("```\nバウンスの発生したメールアドレス:%s\n原因:%s\n```",
message.Email, message.Reason,
),
},
)
if err != nil {
fmt.Println(err.Error())
return err
}
res, err := http.PostForm(
webhookUrl,
url.Values{"payload": {
string(payload),
},
})
if err != nil {
return err
}
defer res.Body.Close()
}
return nil
}
func main() (SendGridBounceResult, error) {
var bounceDetails []BouncePostData
webhookUrl := "Slack Incoming Webhook URL"
response, err := getBounceMail(apiKey)
if err != nil {
fmt.Println(err.Error())
return SendGridBounceResult{Result: "Error"}, err
}
if len(response) == 0 {
fmt.Println("No Bounce mail.")
return SendGridBounceResult{Result: "Success"}, nil
}
for _, value := range response {
bounceDetails = append(bounceDetails, BouncePostData{
Email: value.Email,
Reason: value.Reason,
})
}
err = sendSlack(webhookUrl, bounceDetails)
if err != nil {
fmt.Println(err.Error())
return SendGridBounceResult{Result: "Error"}, err
}
return SendGridBounceResult{
Result: "Success",
}, nil
}
まとめ
SendGrid のバウンスが発生しているメールは通常都度コンソールをみることになりますが,バウンスが発生してたら Slack に投稿する仕組みを作ったのでその模様をまとめました.実運用に載せましたが,今の所問題は起こっていなく,今まで気づけなかったバウンスに気づきやすく問題に当たれるようになった体感があります.今後も普段のオペレーションから仕組み化すべきなことをコードで解決図っていきたいと思います.