2021-04-10 01:07:13 +03:00
|
|
|
package mail
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"github.com/emersion/go-sasl"
|
|
|
|
"github.com/emersion/go-smtp"
|
|
|
|
conf "github.com/muety/wakapi/config"
|
|
|
|
"github.com/muety/wakapi/models"
|
|
|
|
"io"
|
|
|
|
)
|
|
|
|
|
2021-04-30 16:14:29 +03:00
|
|
|
type SMTPSendingService struct {
|
|
|
|
config conf.SMTPMailConfig
|
|
|
|
auth sasl.Client
|
2021-04-10 01:07:13 +03:00
|
|
|
}
|
|
|
|
|
2021-04-30 16:14:29 +03:00
|
|
|
func NewSMTPSendingService(config conf.SMTPMailConfig) *SMTPSendingService {
|
|
|
|
return &SMTPSendingService{
|
|
|
|
config: config,
|
2021-04-10 01:07:13 +03:00
|
|
|
auth: sasl.NewPlainClient(
|
|
|
|
"",
|
|
|
|
config.Username,
|
|
|
|
config.Password,
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 16:14:29 +03:00
|
|
|
func (s *SMTPSendingService) Send(mail *models.Mail) error {
|
2023-03-06 22:31:31 +03:00
|
|
|
mail = mail.Sanitized()
|
|
|
|
|
2021-04-10 01:07:13 +03:00
|
|
|
dial := smtp.Dial
|
2021-04-30 16:14:29 +03:00
|
|
|
if s.config.TLS {
|
2021-04-10 01:07:13 +03:00
|
|
|
dial = func(addr string) (*smtp.Client, error) {
|
|
|
|
return smtp.DialTLS(addr, nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 16:14:29 +03:00
|
|
|
c, err := dial(s.config.ConnStr())
|
2021-04-10 01:07:13 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
if ok, _ := c.Extension("STARTTLS"); ok {
|
|
|
|
if err = c.StartTLS(nil); err != nil {
|
2022-11-16 07:29:20 +03:00
|
|
|
errCode := err.(*smtp.SMTPError).Code
|
|
|
|
if errCode == 503 {
|
|
|
|
// TLS already active
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
2021-04-10 01:07:13 +03:00
|
|
|
}
|
|
|
|
}
|
2021-04-30 16:14:29 +03:00
|
|
|
if s.auth != nil {
|
2021-04-10 01:07:13 +03:00
|
|
|
if ok, _ := c.Extension("AUTH"); !ok {
|
|
|
|
return errors.New("smtp: server doesn't support AUTH")
|
|
|
|
}
|
2022-03-04 19:03:04 +03:00
|
|
|
|
|
|
|
if len(s.config.Username) == 0 || len(s.config.Password) == 0 {
|
2022-03-06 13:52:03 +03:00
|
|
|
return errors.New("smtp: server requires authentication, but no authentication is provided")
|
2022-03-04 19:03:04 +03:00
|
|
|
}
|
|
|
|
|
2021-04-30 16:14:29 +03:00
|
|
|
if err = c.Auth(s.auth); err != nil {
|
2021-04-10 01:07:13 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2021-04-30 16:14:29 +03:00
|
|
|
if err = c.Mail(mail.From.Raw(), nil); err != nil {
|
2021-04-10 01:07:13 +03:00
|
|
|
return err
|
|
|
|
}
|
2021-04-30 16:14:29 +03:00
|
|
|
for _, addr := range mail.To.RawStrings() {
|
2021-04-10 01:07:13 +03:00
|
|
|
if err = c.Rcpt(addr); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w, err := c.Data()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-04-30 16:14:29 +03:00
|
|
|
_, err = io.Copy(w, mail.Reader())
|
2021-04-10 01:07:13 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = w.Close()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return c.Quit()
|
|
|
|
}
|