M email/send.go => email/send.go +18 -5
@@ 4,10 4,10 @@ import (
"context"
"fmt"
"io"
- "net/mail"
"strconv"
_ "github.com/emersion/go-message/charset"
+ "github.com/emersion/go-message/mail"
"github.com/emersion/go-sasl"
"github.com/emersion/go-smtp"
@@ 111,10 111,23 @@ func mailSetup(ctx context.Context) (*smtp.Client, *mail.Address, error) {
// Sends an email. Blocks until it's sent or an error occurs.
func Send(ctx context.Context, msg io.Reader, rcpts []string) error {
- c, sender, err := mailSetup(ctx)
+ worker := ForContext(ctx)
+
+ if worker.client == nil || worker.client.Noop() != nil {
+ worker.client = nil
+
+ c, sender, err := mailSetup(ctx)
+ if err != nil {
+ return err
+ }
+ worker.client = c
+ worker.sender = sender
+ }
+
+ err := worker.client.SendMail(worker.sender.Address, rcpts, msg)
if err != nil {
- return err
+ worker.client.Close()
+ worker.client = nil
}
- defer c.Close()
- return c.SendMail(sender.Address, rcpts, msg)
+ return err
}
M email/worker.go => email/worker.go +11 -4
@@ 18,6 18,7 @@ import (
_ "github.com/emersion/go-message/charset"
"github.com/emersion/go-message/mail"
"github.com/emersion/go-pgpmail"
+ "github.com/emersion/go-smtp"
"github.com/vaughan0/go-ini"
)
@@ 27,6 28,12 @@ type contextKey struct {
name string
}
+type workerContext struct {
+ client *smtp.Client
+ sender *mail.Address
+ queue *Queue
+}
+
// Returns a task which will send this email for the work queue. If the caller
// does not need to customize the task parameters, the Enqueue function may be
// more desirable.
@@ 81,7 88,7 @@ func prepareSigned(header mail.Header, buf *bytes.Buffer,
func EnqueueStd(ctx context.Context, header mail.Header,
bodyReader io.Reader, rcptKey *string) error {
- queue := ForContext(ctx)
+ queue := ForContext(ctx).queue
to, err := header.AddressList("To")
if err != nil {
@@ 246,8 253,8 @@ func NewQueue(conf ini.File) *Queue {
}
// Returns the email worker for this context.
-func ForContext(ctx context.Context) *Queue {
- q, ok := ctx.Value(emailCtxKey).(*Queue)
+func ForContext(ctx context.Context) *workerContext {
+ q, ok := ctx.Value(emailCtxKey).(*workerContext)
if !ok {
panic(errors.New("No email worker for this context"))
}
@@ 256,7 263,7 @@ func ForContext(ctx context.Context) *Queue {
// Returns a context which includes the given mail worker.
func Context(ctx context.Context, queue *Queue) context.Context {
- return context.WithValue(ctx, emailCtxKey, queue)
+ return context.WithValue(ctx, emailCtxKey, &workerContext{queue: queue})
}
// Adds HTTP middleware to provide an email work queue to this context.