forked from vikunja/vikunja
feat: reopen SMTP connection if closed
This commit is contained in:
parent
1e7871b5c0
commit
bfb71926a3
@ -19,6 +19,9 @@ package mail
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
@ -46,7 +49,6 @@ func getClient() (*mail.Client, error) {
|
||||
if config.MailerForceSSL.GetBool() {
|
||||
tlsPolicy = mail.TLSMandatory
|
||||
}
|
||||
|
||||
opts := []mail.Option{
|
||||
mail.WithTLSPortPolicy(tlsPolicy),
|
||||
mail.WithTLSConfig(&tls.Config{
|
||||
@ -82,6 +84,38 @@ func getClient() (*mail.Client, error) {
|
||||
)
|
||||
}
|
||||
|
||||
func resilientSend(client *mail.Client, message *mail.Msg) error {
|
||||
const maxRetries = 3
|
||||
retries := 0
|
||||
|
||||
for retries < maxRetries {
|
||||
log.Debug("Sending mail")
|
||||
err := client.Send(message)
|
||||
if err == nil {
|
||||
log.Debug("Mail sent")
|
||||
return nil
|
||||
}
|
||||
|
||||
var sendError *mail.SendError
|
||||
_ = errors.As(err, &sendError)
|
||||
|
||||
if sendError.Reason != mail.ErrConnCheck {
|
||||
// only ErrConnCheck is retried, other exceptions are thrown
|
||||
return err
|
||||
}
|
||||
|
||||
log.Warning("Connection was closed, reconnecting before retrying")
|
||||
err = client.DialWithContext(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("Connection re-established")
|
||||
retries++
|
||||
}
|
||||
|
||||
return errors.New(fmt.Sprintf("could not send mail after %d retries", retries))
|
||||
}
|
||||
|
||||
// StartMailDaemon starts the mail daemon
|
||||
func StartMailDaemon() {
|
||||
Queue = make(chan *mail.Msg, config.MailerQueuelength.GetInt())
|
||||
@ -110,25 +144,32 @@ func StartMailDaemon() {
|
||||
return
|
||||
}
|
||||
if !open {
|
||||
log.Debug("Opening connection to mail server")
|
||||
err = c.DialWithContext(context.Background())
|
||||
if err != nil {
|
||||
log.Errorf("Error during connect to smtp server: %s", err)
|
||||
break
|
||||
}
|
||||
log.Debug("Connected to mail server")
|
||||
open = true
|
||||
}
|
||||
err = c.Send(m)
|
||||
err = resilientSend(c, m)
|
||||
if err != nil {
|
||||
log.Errorf("Error when sending mail: %s", err)
|
||||
log.Errorf("Error sending mail: %s", err)
|
||||
break
|
||||
}
|
||||
// Close the connection to the SMTP server if no email was sent in
|
||||
// the last 30 seconds.
|
||||
case <-time.After(config.MailerQueueTimeout.GetDuration() * time.Second):
|
||||
if open {
|
||||
log.Debug("Closing connection to mail server due to queue timeout")
|
||||
open = false
|
||||
err = c.Close()
|
||||
if err != nil {
|
||||
if strings.HasPrefix(err.Error(), "not connected to SMTP server") {
|
||||
log.Warning("Connection to mail server was already closed")
|
||||
break
|
||||
}
|
||||
log.Errorf("Error closing the mail server connection: %s\n", err)
|
||||
break
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user