1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-23 15:37:01 +00:00

chasquid: Load and resolve aliases

This patch integrates the aliases resolution into the daemon and queue.

The queue now will resolve aliases at Put time.
This commit is contained in:
Alberto Bertogli
2016-09-22 00:22:39 +01:00
parent bab8a8083c
commit c34c073c1c
15 changed files with 251 additions and 32 deletions

View File

@@ -19,6 +19,7 @@ import (
"bytes"
"blitiri.com.ar/go/chasquid/internal/aliases"
"blitiri.com.ar/go/chasquid/internal/courier"
"blitiri.com.ar/go/chasquid/internal/envelope"
"blitiri.com.ar/go/chasquid/internal/protoio"
@@ -91,10 +92,13 @@ type Queue struct {
// Path where we store the queue.
path string
// Aliases resolver.
aliases *aliases.Resolver
}
// Load the queue and launch the sending loops on startup.
func New(path string, localDomains *set.String) *Queue {
func New(path string, localDomains *set.String, aliases *aliases.Resolver) *Queue {
os.MkdirAll(path, 0700)
return &Queue{
@@ -103,6 +107,7 @@ func New(path string, localDomains *set.String) *Queue {
remoteC: &courier.SMTP{},
localDomains: localDomains,
path: path,
aliases: aliases,
}
}
@@ -151,11 +156,30 @@ func (q *Queue) Put(from string, to []string, data []byte) (string, error) {
}
for _, t := range to {
item.Rcpt = append(item.Rcpt, &Recipient{
Address: t,
Type: Recipient_EMAIL,
Status: Recipient_PENDING,
})
rcpts, err := q.aliases.Resolve(t)
if err != nil {
return "", fmt.Errorf("error resolving aliases for %q: %v", t, err)
}
// Add the recipients (after resolving aliases); this conversion is
// not very pretty but at least it's self contained.
for _, aliasRcpt := range rcpts {
r := &Recipient{
Address: aliasRcpt.Addr,
Status: Recipient_PENDING,
}
switch aliasRcpt.Type {
case aliases.EMAIL:
r.Type = Recipient_EMAIL
case aliases.PIPE:
r.Type = Recipient_PIPE
default:
glog.Errorf("unknown alias type %v when resolving %q",
aliasRcpt.Type, t)
return "", fmt.Errorf("internal error - unknown alias type")
}
item.Rcpt = append(item.Rcpt, r)
}
}
err := item.WriteTo(q.path)

View File

@@ -3,10 +3,12 @@ package queue
import (
"bytes"
"fmt"
"reflect"
"sync"
"testing"
"time"
"blitiri.com.ar/go/chasquid/internal/aliases"
"blitiri.com.ar/go/chasquid/internal/set"
)
@@ -58,7 +60,7 @@ func newTestCourier() *TestCourier {
func TestBasic(t *testing.T) {
localC := newTestCourier()
remoteC := newTestCourier()
q := New("/tmp/queue_test", set.NewString("loco"))
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver())
q.localC = localC
q.remoteC = remoteC
@@ -99,7 +101,7 @@ func TestBasic(t *testing.T) {
}
func TestFullQueue(t *testing.T) {
q := New("/tmp/queue_test", set.NewString())
q := New("/tmp/queue_test", set.NewString(), aliases.NewResolver())
// Force-insert maxQueueSize items in the queue.
oneID := ""
@@ -136,8 +138,53 @@ func TestFullQueue(t *testing.T) {
q.Remove(id)
}
// Dumb courier, for when we don't care for the results.
type DumbCourier struct{}
func (c DumbCourier) Deliver(from string, to string, data []byte) error {
return nil
}
func TestAliases(t *testing.T) {
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver())
q.localC = DumbCourier{}
q.remoteC = DumbCourier{}
q.aliases.AddDomain("loco")
q.aliases.AddAliasForTesting("ab@loco", "pq@loco", aliases.EMAIL)
q.aliases.AddAliasForTesting("ab@loco", "rs@loco", aliases.EMAIL)
q.aliases.AddAliasForTesting("ab@loco", "command", aliases.PIPE)
q.aliases.AddAliasForTesting("cd@loco", "ata@hualpa", aliases.EMAIL)
cases := []struct {
to []string
expected []*Recipient
}{
{[]string{"ab@loco"}, []*Recipient{
{"pq@loco", Recipient_EMAIL, Recipient_PENDING},
{"rs@loco", Recipient_EMAIL, Recipient_PENDING},
{"command", Recipient_PIPE, Recipient_PENDING}}},
{[]string{"ab@loco", "cd@loco"}, []*Recipient{
{"pq@loco", Recipient_EMAIL, Recipient_PENDING},
{"rs@loco", Recipient_EMAIL, Recipient_PENDING},
{"command", Recipient_PIPE, Recipient_PENDING},
{"ata@hualpa", Recipient_EMAIL, Recipient_PENDING}}},
}
for _, c := range cases {
id, err := q.Put("from", c.to, []byte("data"))
if err != nil {
t.Errorf("Put: %v", err)
}
item := q.q[id]
if !reflect.DeepEqual(item.Rcpt, c.expected) {
t.Errorf("case %q, expected %v, got %v", c.to, item.Rcpt, c.expected)
}
q.Remove(id)
}
}
func TestPipes(t *testing.T) {
q := New("/tmp/queue_test", set.NewString("loco"))
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver())
item := &Item{
Message: Message{
ID: <-newID,