use golang as sender
This commit is contained in:
parent
403cb5a6ad
commit
2ff79c7780
|
@ -10,19 +10,39 @@ AdminRole = "Admin"
|
||||||
# metrics descriptions
|
# metrics descriptions
|
||||||
MetricsYamlFile = "./etc/metrics.yaml"
|
MetricsYamlFile = "./etc/metrics.yaml"
|
||||||
|
|
||||||
# Linkage with notify.py script
|
[[NotifyChannels]]
|
||||||
NotifyChannels = [ "email", "dingtalk", "wecom", "feishu" ]
|
Label = "邮箱"
|
||||||
|
# do not change Key
|
||||||
|
Key = "email"
|
||||||
|
|
||||||
|
[[NotifyChannels]]
|
||||||
|
Label = "钉钉机器人"
|
||||||
|
# do not change Key
|
||||||
|
Key = "dingtalk"
|
||||||
|
|
||||||
|
[[NotifyChannels]]
|
||||||
|
Label = "企微机器人"
|
||||||
|
# do not change Key
|
||||||
|
Key = "wecom"
|
||||||
|
|
||||||
|
[[NotifyChannels]]
|
||||||
|
Label = "飞书机器人"
|
||||||
|
# do not change Key
|
||||||
|
Key = "feishu"
|
||||||
|
|
||||||
[[ContactKeys]]
|
[[ContactKeys]]
|
||||||
Label = "Wecom Robot Token"
|
Label = "Wecom Robot Token"
|
||||||
|
# do not change Key
|
||||||
Key = "wecom_robot_token"
|
Key = "wecom_robot_token"
|
||||||
|
|
||||||
[[ContactKeys]]
|
[[ContactKeys]]
|
||||||
Label = "Dingtalk Robot Token"
|
Label = "Dingtalk Robot Token"
|
||||||
|
# do not change Key
|
||||||
Key = "dingtalk_robot_token"
|
Key = "dingtalk_robot_token"
|
||||||
|
|
||||||
[[ContactKeys]]
|
[[ContactKeys]]
|
||||||
Label = "Feishu Robot Token"
|
Label = "Feishu Robot Token"
|
||||||
|
# do not change Key
|
||||||
Key = "feishu_robot_token"
|
Key = "feishu_robot_token"
|
||||||
|
|
||||||
[Log]
|
[Log]
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -23,12 +23,15 @@ require (
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/prometheus/common v0.26.0
|
github.com/prometheus/common v0.26.0
|
||||||
github.com/prometheus/prometheus v2.5.0+incompatible
|
github.com/prometheus/prometheus v2.5.0+incompatible
|
||||||
|
github.com/tidwall/gjson v1.14.0 // indirect
|
||||||
github.com/toolkits/pkg v1.2.9
|
github.com/toolkits/pkg v1.2.9
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
||||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
|
||||||
google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect
|
google.golang.org/genproto v0.0.0-20211007155348-82e027067bd4 // indirect
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
google.golang.org/grpc v1.41.0 // indirect
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||||
gorm.io/driver/mysql v1.1.2
|
gorm.io/driver/mysql v1.1.2
|
||||||
gorm.io/driver/postgres v1.1.1
|
gorm.io/driver/postgres v1.1.1
|
||||||
gorm.io/gorm v1.21.15
|
gorm.io/gorm v1.21.15
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -298,6 +298,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w=
|
||||||
|
github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/toolkits/pkg v1.2.9 h1:zGlrJDl+2sMBoxBRIoMtAwvKmW5wctuji2+qHCecMKk=
|
github.com/toolkits/pkg v1.2.9 h1:zGlrJDl+2sMBoxBRIoMtAwvKmW5wctuji2+qHCecMKk=
|
||||||
github.com/toolkits/pkg v1.2.9/go.mod h1:ZUsQAOoaR99PSbes+RXSirvwmtd6+XIUvizCmrjfUYc=
|
github.com/toolkits/pkg v1.2.9/go.mod h1:ZUsQAOoaR99PSbes+RXSirvwmtd6+XIUvizCmrjfUYc=
|
||||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||||
|
@ -465,12 +471,16 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/toolkits/pkg/slice"
|
|
||||||
"github.com/toolkits/pkg/str"
|
"github.com/toolkits/pkg/str"
|
||||||
|
|
||||||
"github.com/didi/nightingale/v5/src/webapi/config"
|
"github.com/didi/nightingale/v5/src/webapi/config"
|
||||||
|
@ -101,7 +100,7 @@ func (ar *AlertRule) Verify() error {
|
||||||
if len(channels) > 0 {
|
if len(channels) > 0 {
|
||||||
nlst := make([]string, 0, len(channels))
|
nlst := make([]string, 0, len(channels))
|
||||||
for i := 0; i < len(channels); i++ {
|
for i := 0; i < len(channels); i++ {
|
||||||
if slice.ContainsString(config.C.NotifyChannels, channels[i]) {
|
if config.LabelAndKeyHasKey(config.C.NotifyChannels, channels[i]) {
|
||||||
nlst = append(nlst, channels[i])
|
nlst = append(nlst, channels[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,3 +155,11 @@ func mapKeys(m map[int64]struct{}) []int64 {
|
||||||
}
|
}
|
||||||
return lst
|
return lst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StringSetKeys(m map[string]struct{}) []string {
|
||||||
|
lst := make([]string, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
lst = append(lst, k)
|
||||||
|
}
|
||||||
|
return lst
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/didi/nightingale/v5/src/server/config"
|
"github.com/didi/nightingale/v5/src/server/config"
|
||||||
|
"github.com/didi/nightingale/v5/src/server/sender"
|
||||||
promstat "github.com/didi/nightingale/v5/src/server/stat"
|
promstat "github.com/didi/nightingale/v5/src/server/stat"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ func Start(ctx context.Context) error {
|
||||||
|
|
||||||
go reportQueueSize()
|
go reportQueueSize()
|
||||||
|
|
||||||
|
go sender.StartEmailSender()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
"github.com/toolkits/pkg/file"
|
"github.com/toolkits/pkg/file"
|
||||||
"github.com/toolkits/pkg/logger"
|
"github.com/toolkits/pkg/logger"
|
||||||
"github.com/toolkits/pkg/runner"
|
"github.com/toolkits/pkg/runner"
|
||||||
|
@ -21,6 +22,7 @@ import (
|
||||||
"github.com/didi/nightingale/v5/src/pkg/sys"
|
"github.com/didi/nightingale/v5/src/pkg/sys"
|
||||||
"github.com/didi/nightingale/v5/src/server/config"
|
"github.com/didi/nightingale/v5/src/server/config"
|
||||||
"github.com/didi/nightingale/v5/src/server/memsto"
|
"github.com/didi/nightingale/v5/src/server/memsto"
|
||||||
|
"github.com/didi/nightingale/v5/src/server/sender"
|
||||||
"github.com/didi/nightingale/v5/src/storage"
|
"github.com/didi/nightingale/v5/src/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -117,8 +119,110 @@ func alertingRedisPub(bs []byte) {
|
||||||
func handleNotice(notice Notice, bs []byte) {
|
func handleNotice(notice Notice, bs []byte) {
|
||||||
alertingCallScript(bs)
|
alertingCallScript(bs)
|
||||||
|
|
||||||
// TODO 弄个channel发邮件,学习daemon写法
|
emailset := make(map[string]struct{})
|
||||||
// 收集tokens、phones,发呗
|
phoneset := make(map[string]struct{})
|
||||||
|
wecomset := make(map[string]struct{})
|
||||||
|
dingtalkset := make(map[string]struct{})
|
||||||
|
feishuset := make(map[string]struct{})
|
||||||
|
|
||||||
|
for _, user := range notice.Event.NotifyUsersObj {
|
||||||
|
if user.Email != "" {
|
||||||
|
emailset[user.Email] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Phone != "" {
|
||||||
|
phoneset[user.Phone] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
bs, err := user.Contacts.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("handle_notice: failed to marshal contacts: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := gjson.GetBytes(bs, "dingtalk_robot_token")
|
||||||
|
if ret.Exists() {
|
||||||
|
dingtalkset[ret.String()] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gjson.GetBytes(bs, "wecom_robot_token")
|
||||||
|
if ret.Exists() {
|
||||||
|
wecomset[ret.String()] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gjson.GetBytes(bs, "feishu_robot_token")
|
||||||
|
if ret.Exists() {
|
||||||
|
feishuset[ret.String()] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
phones := StringSetKeys(phoneset)
|
||||||
|
|
||||||
|
for _, ch := range notice.Event.NotifyChannelsJSON {
|
||||||
|
switch ch {
|
||||||
|
case "email":
|
||||||
|
if len(emailset) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
subject, has := notice.Tpls["subject.tpl"]
|
||||||
|
if !has {
|
||||||
|
subject = "subject.tpl not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
content, has := notice.Tpls["mailbody.tpl"]
|
||||||
|
if !has {
|
||||||
|
content = "mailbody.tpl not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.WriteEmail(subject, content, StringSetKeys(emailset))
|
||||||
|
case "dingtalk":
|
||||||
|
if len(dingtalkset) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content, has := notice.Tpls["dingtalk.tpl"]
|
||||||
|
if !has {
|
||||||
|
content = "dingtalk.tpl not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.SendDingtalk(sender.DingtalkMessage{
|
||||||
|
Title: notice.Event.RuleName,
|
||||||
|
Text: content,
|
||||||
|
AtMobiles: phones,
|
||||||
|
Tokens: StringSetKeys(dingtalkset),
|
||||||
|
})
|
||||||
|
case "wecom":
|
||||||
|
if len(wecomset) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content, has := notice.Tpls["wecom.tpl"]
|
||||||
|
if !has {
|
||||||
|
content = "wecom.tpl not found"
|
||||||
|
}
|
||||||
|
sender.SendWecom(sender.WecomMessage{
|
||||||
|
Text: content,
|
||||||
|
Tokens: StringSetKeys(wecomset),
|
||||||
|
})
|
||||||
|
case "feishu":
|
||||||
|
if len(feishuset) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content, has := notice.Tpls["feishu.tpl"]
|
||||||
|
if !has {
|
||||||
|
content = "feishu.tpl not found"
|
||||||
|
}
|
||||||
|
sender.SendFeishu(sender.FeishuMessage{
|
||||||
|
Text: content,
|
||||||
|
AtMobiles: phones,
|
||||||
|
Tokens: StringSetKeys(feishuset),
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
logger.Info("channel ", ch, " not supported by golang")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func notify(event *models.AlertCurEvent) {
|
func notify(event *models.AlertCurEvent) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package sender
|
package sender
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/didi/nightingale/v5/src/server/poster"
|
"github.com/didi/nightingale/v5/src/server/poster"
|
||||||
|
@ -31,13 +32,18 @@ type dingtalk struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendDingtalk(message DingtalkMessage) {
|
func SendDingtalk(message DingtalkMessage) {
|
||||||
|
ats := make([]string, len(message.AtMobiles))
|
||||||
|
for i := 0; i < len(message.AtMobiles); i++ {
|
||||||
|
ats[i] = "@" + message.AtMobiles[i]
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < len(message.Tokens); i++ {
|
for i := 0; i < len(message.Tokens); i++ {
|
||||||
url := "https://oapi.dingtalk.com/robot/send?access_token=" + message.Tokens[i]
|
url := "https://oapi.dingtalk.com/robot/send?access_token=" + message.Tokens[i]
|
||||||
body := dingtalk{
|
body := dingtalk{
|
||||||
Msgtype: "markdown",
|
Msgtype: "markdown",
|
||||||
Markdown: dingtalkMarkdown{
|
Markdown: dingtalkMarkdown{
|
||||||
Title: message.Title,
|
Title: message.Title,
|
||||||
Text: message.Text,
|
Text: message.Text + " " + strings.Join(ats, " "),
|
||||||
},
|
},
|
||||||
At: dingtalkAt{
|
At: dingtalkAt{
|
||||||
AtMobiles: message.AtMobiles,
|
AtMobiles: message.AtMobiles,
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package sender
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/v5/src/server/config"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
"gopkg.in/gomail.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mailch = make(chan *gomail.Message, 100000)
|
||||||
|
|
||||||
|
func WriteEmail(subject, content string, tos []string) {
|
||||||
|
m := gomail.NewMessage()
|
||||||
|
|
||||||
|
m.SetHeader("From", config.C.SMTP.From)
|
||||||
|
m.SetHeader("To", tos...)
|
||||||
|
m.SetHeader("Subject", subject)
|
||||||
|
m.SetBody("text/html", content)
|
||||||
|
|
||||||
|
mailch <- m
|
||||||
|
}
|
||||||
|
|
||||||
|
func dialSmtp(d *gomail.Dialer) gomail.SendCloser {
|
||||||
|
for {
|
||||||
|
if s, err := d.Dial(); err != nil {
|
||||||
|
logger.Errorf("email_sender: failed to dial smtp: %s", err)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartEmailSender() {
|
||||||
|
conf := config.C.SMTP
|
||||||
|
|
||||||
|
d := gomail.NewDialer(conf.Host, conf.Port, conf.User, conf.Pass)
|
||||||
|
if conf.InsecureSkipVerify {
|
||||||
|
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
var s gomail.SendCloser
|
||||||
|
open := false
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case m, ok := <-mailch:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !open {
|
||||||
|
s = dialSmtp(d)
|
||||||
|
open = true
|
||||||
|
}
|
||||||
|
if err := gomail.Send(s, m); err != nil {
|
||||||
|
logger.Errorf("email_sender: failed to send: %s", err)
|
||||||
|
}
|
||||||
|
// Close the connection to the SMTP server if no email was sent in
|
||||||
|
// the last 30 seconds.
|
||||||
|
case <-time.After(30 * time.Second):
|
||||||
|
if open {
|
||||||
|
if err := s.Close(); err != nil {
|
||||||
|
logger.Warningf("email_sender: failed to close smtp connection: %s", err)
|
||||||
|
}
|
||||||
|
open = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,8 +78,8 @@ type Config struct {
|
||||||
I18N string
|
I18N string
|
||||||
AdminRole string
|
AdminRole string
|
||||||
MetricsYamlFile string
|
MetricsYamlFile string
|
||||||
ContactKeys []ContactKey
|
ContactKeys []LabelAndKey
|
||||||
NotifyChannels []string
|
NotifyChannels []LabelAndKey
|
||||||
Log logx.Config
|
Log logx.Config
|
||||||
HTTP httpx.Config
|
HTTP httpx.Config
|
||||||
JWTAuth JWTAuth
|
JWTAuth JWTAuth
|
||||||
|
@ -94,11 +94,20 @@ type Config struct {
|
||||||
Ibex Ibex
|
Ibex Ibex
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContactKey struct {
|
type LabelAndKey struct {
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LabelAndKeyHasKey(keys []LabelAndKey, key string) bool {
|
||||||
|
for i := 0; i < len(keys); i++ {
|
||||||
|
if keys[i].Key == key {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type JWTAuth struct {
|
type JWTAuth struct {
|
||||||
SigningKey string
|
SigningKey string
|
||||||
AccessExpired int64
|
AccessExpired int64
|
||||||
|
|
Loading…
Reference in New Issue