package email
import (
"context"
"errors"
"log"
"net/http"
"strings"
"git.sr.ht/~sircmpwn/dowork"
gomail "gopkg.in/mail.v2"
"git.sr.ht/~sircmpwn/core-go/config"
)
var emailCtxKey = &contextKey{"email"}
type contextKey struct {
name string
}
// 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.
func NewTask(ctx context.Context, m *gomail.Message) *work.Task {
conf := config.ForContext(ctx)
return work.NewTask(func(ctx context.Context) error {
return Send(config.Context(ctx, conf), m)
}).Retries(10).After(func(ctx context.Context, task *work.Task) {
if task.Result() == nil {
log.Printf("MAIL TO %s: '%s' sent after %d attempts",
strings.Join(m.GetHeader("To"), ";"),
strings.Join(m.GetHeader("Subject"), ";"),
task.Attempts())
} else {
log.Printf("MAIL TO %s: '%s' failed after %d attempts: %v",
strings.Join(m.GetHeader("To"), ";"),
strings.Join(m.GetHeader("Subject"), ";"),
task.Attempts(), task.Result())
}
})
}
// Enqueues an email for sending with the default parameters.
func Enqueue(ctx context.Context, m *gomail.Message) {
ForContext(ctx).Enqueue(NewTask(ctx, m))
}
// Creates a new email processing queue.
func NewQueue() *work.Queue {
return work.NewQueue("email")
}
// Returns the email worker for this context.
func ForContext(ctx context.Context) *work.Queue {
q, ok := ctx.Value(emailCtxKey).(*work.Queue)
if !ok {
panic(errors.New("No email worker for this context"))
}
return q
}
// Adds HTTP middleware to provide an email work queue to this context.
func Middleware(worker *work.Queue) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), emailCtxKey, worker)
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
}