package middleware import ( "bytes" "context" "fmt" "io" "time" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/transport" kratoshttp "github.com/go-kratos/kratos/v2/transport/http" ) // EmailSender 邮件发送接口 type EmailSender interface { SendError(subject, body string) error } // ErrorToEmail 错误邮件通知中间件 func ErrorToEmail(sender EmailSender, logger log.Logger) middleware.Middleware { helper := log.NewHelper(logger) return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (interface{}, error) { var ( username string body string method string path string ip string ) // 获取用户信息 if claims, ok := GetClaims(ctx); ok { username = claims.Username } if username == "" { username = "Unknown" } if tr, ok := transport.FromServerContext(ctx); ok { path = tr.Operation() if header := tr.RequestHeader(); header != nil { method = header.Get(":method") } if ht, ok := tr.(kratoshttp.Transporter); ok { r := ht.Request() ip = getClientIP(r) // 读取body bodyBytes, _ := io.ReadAll(r.Body) r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) body = string(bodyBytes) } } start := time.Now() reply, err := handler(ctx, req) latency := time.Since(start) // 如果有错误,发送邮件 if err != nil && sender != nil { subject := fmt.Sprintf("%s %s调用了%s报错了", username, ip, path) content := fmt.Sprintf( "接收到的请求为%s\n请求方式为%s\n报错信息如下%s\n耗时%s\n", body, method, err.Error(), latency.String(), ) if sendErr := sender.SendError(subject, content); sendErr != nil { helper.Error("ErrorToEmail Failed, err:", sendErr) } } return reply, err } } }