1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-17 14:37:02 +00:00

queue: Support sending to pipes

With the introduction of aliases, the queue may now be delivering mail to
pipes. This patch implements pipe delivery.

It uses a fixed 30s timeout for now, as these commands should really not take
much time, and we don't want to overly complicate the configuration for now.
This commit is contained in:
Alberto Bertogli
2016-09-22 02:18:35 +01:00
parent a531092f8b
commit bab8a8083c
4 changed files with 76 additions and 33 deletions

View File

@@ -6,14 +6,19 @@ package queue
//go:generate protoc --go_out=. -I=${GOPATH}/src -I. queue.proto
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"
"bytes"
"blitiri.com.ar/go/chasquid/internal/courier"
"blitiri.com.ar/go/chasquid/internal/envelope"
"blitiri.com.ar/go/chasquid/internal/protoio"
@@ -248,20 +253,10 @@ func (item *Item) SendLoop(q *Queue) {
wg.Add(1)
go func(rcpt *Recipient, oldStatus Recipient_Status) {
defer wg.Done()
// TODO: Different types of recipients.
to := rcpt.Address
tr.LazyPrintf("%s sending", to)
var err error
// TODO: If this is all the difference we end up having
// between the two couriers, consider going back to using a
// routing courier.
if envelope.DomainIn(to, q.localDomains) {
err = q.localC.Deliver(item.From, to, item.Data)
} else {
err = q.remoteC.Deliver(item.From, to, item.Data)
}
err := item.deliver(q, rcpt)
if err != nil {
// TODO: Local deliveries should not be retried, if they
@@ -322,6 +317,26 @@ func (item *Item) SendLoop(q *Queue) {
// remove item from the queue, and remove from disk.
}
func (item *Item) deliver(q *Queue, rcpt *Recipient) error {
if rcpt.Type == Recipient_PIPE {
c := strings.Fields(rcpt.Address)
if len(c) == 0 {
return fmt.Errorf("empty pipe")
}
ctx, _ := context.WithDeadline(context.Background(),
time.Now().Add(30*time.Second))
cmd := exec.CommandContext(ctx, c[0], c[1:]...)
cmd.Stdin = bytes.NewReader(item.Data)
return cmd.Run()
} else {
if envelope.DomainIn(rcpt.Address, q.localDomains) {
return q.localC.Deliver(item.From, rcpt.Address, item.Data)
} else {
return q.remoteC.Deliver(item.From, rcpt.Address, item.Data)
}
}
}
func nextDelay(last time.Duration) time.Duration {
switch {
case last < 1*time.Minute: