To gitea and beyond, let's go(-yco)
This commit is contained in:
99
internal/services/email_sender.go
Normal file
99
internal/services/email_sender.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type EmailSender interface {
|
||||
Send(to, subject, body string) error
|
||||
}
|
||||
|
||||
type SMTPSender struct {
|
||||
host string
|
||||
port int
|
||||
username string
|
||||
password string
|
||||
from string
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func NewSMTPSender(cfgHost string, cfgPort int, cfgUsername, cfgPassword, cfgFrom string) *SMTPSender {
|
||||
return &SMTPSender{
|
||||
host: cfgHost,
|
||||
port: cfgPort,
|
||||
username: cfgUsername,
|
||||
password: cfgPassword,
|
||||
from: cfgFrom,
|
||||
timeout: 30 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
func NewSMTPSenderWithTimeout(cfgHost string, cfgPort int, cfgUsername, cfgPassword, cfgFrom string, timeout time.Duration) *SMTPSender {
|
||||
return &SMTPSender{
|
||||
host: cfgHost,
|
||||
port: cfgPort,
|
||||
username: cfgUsername,
|
||||
password: cfgPassword,
|
||||
from: cfgFrom,
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SMTPSender) Send(to, subject, body string) error {
|
||||
if s == nil {
|
||||
return fmt.Errorf("smtp sender is not configured")
|
||||
}
|
||||
|
||||
to = strings.TrimSpace(to)
|
||||
if to == "" {
|
||||
return fmt.Errorf("recipient address is required")
|
||||
}
|
||||
|
||||
address := fmt.Sprintf("%s:%d", s.host, s.port)
|
||||
|
||||
headers := []string{
|
||||
fmt.Sprintf("From: %s", s.from),
|
||||
fmt.Sprintf("To: %s", to),
|
||||
fmt.Sprintf("Subject: %s", subject),
|
||||
"MIME-Version: 1.0",
|
||||
"Content-Type: text/html; charset=\"UTF-8\"",
|
||||
}
|
||||
|
||||
message := strings.Join(headers, "\r\n") + "\r\n\r\n" + body + "\r\n"
|
||||
|
||||
var auth smtp.Auth
|
||||
if strings.TrimSpace(s.username) != "" {
|
||||
auth = smtp.PlainAuth("", s.username, s.password, s.host)
|
||||
}
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- smtp.SendMail(address, auth, s.from, []string{to}, []byte(message))
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-done:
|
||||
return err
|
||||
case <-time.After(s.timeout):
|
||||
return fmt.Errorf("email sending timeout after %v", s.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SMTPSender) SendAsync(to, subject, body string) <-chan error {
|
||||
result := make(chan error, 1)
|
||||
go func() {
|
||||
result <- s.Send(to, subject, body)
|
||||
}()
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *SMTPSender) SetTimeout(timeout time.Duration) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.timeout = timeout
|
||||
}
|
||||
Reference in New Issue
Block a user