feat: design a separate package for health check
This commit is contained in:
106
internal/health/smtp.go
Normal file
106
internal/health/smtp.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/smtp"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SMTPConfig struct {
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
From string
|
||||
}
|
||||
|
||||
type SMTPChecker struct {
|
||||
config SMTPConfig
|
||||
}
|
||||
|
||||
func NewSMTPChecker(config SMTPConfig) *SMTPChecker {
|
||||
return &SMTPChecker{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *SMTPChecker) Name() string {
|
||||
return "smtp"
|
||||
}
|
||||
|
||||
func (c *SMTPChecker) Check(ctx context.Context) Result {
|
||||
start := time.Now()
|
||||
address := fmt.Sprintf("%s:%d", c.config.Host, c.config.Port)
|
||||
|
||||
result := Result{
|
||||
Status: StatusHealthy,
|
||||
Timestamp: time.Now().UTC(),
|
||||
Details: map[string]any{
|
||||
"host": address,
|
||||
},
|
||||
}
|
||||
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
result.Status = StatusDegraded
|
||||
result.Message = fmt.Sprintf("Failed to connect to SMTP server: %v", err)
|
||||
result.Latency = time.Since(start)
|
||||
return result
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client, err := smtp.NewClient(conn, c.config.Host)
|
||||
if err != nil {
|
||||
result.Status = StatusDegraded
|
||||
result.Message = fmt.Sprintf("Failed to create SMTP client: %v", err)
|
||||
result.Latency = time.Since(start)
|
||||
return result
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
err = client.Hello("goyco-health-check")
|
||||
if err != nil {
|
||||
result.Status = StatusDegraded
|
||||
result.Message = fmt.Sprintf("EHLO failed: %v", err)
|
||||
result.Latency = time.Since(start)
|
||||
return result
|
||||
}
|
||||
|
||||
if ok, _ := client.Extension("STARTTLS"); ok {
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: c.config.Host,
|
||||
}
|
||||
err = client.StartTLS(tlsConfig)
|
||||
if err != nil {
|
||||
result.Details["starttls"] = "failed"
|
||||
result.Details["starttls_error"] = err.Error()
|
||||
} else {
|
||||
result.Details["starttls"] = "enabled"
|
||||
}
|
||||
} else {
|
||||
result.Details["starttls"] = "not supported"
|
||||
}
|
||||
|
||||
if c.config.Username != "" && c.config.Password != "" {
|
||||
auth := smtp.PlainAuth("", c.config.Username, c.config.Password, c.config.Host)
|
||||
err = client.Auth(auth)
|
||||
if err != nil {
|
||||
result.Details["auth"] = "failed"
|
||||
result.Details["auth_error"] = err.Error()
|
||||
} else {
|
||||
result.Details["auth"] = "success"
|
||||
}
|
||||
} else {
|
||||
result.Details["auth"] = "not configured"
|
||||
}
|
||||
|
||||
client.Quit()
|
||||
|
||||
result.Latency = time.Since(start)
|
||||
result.Details["handshake"] = "completed"
|
||||
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user