git » chasquid » commit fe146f0

queue: Always use the main domain for sending DSNs

author Alberto Bertogli
2016-10-13 11:08:21 UTC
committer Alberto Bertogli
2016-10-21 21:18:53 UTC
parent b8c0ac98f4489a52bebcbe84440f27e64d2725dd

queue: Always use the main domain for sending DSNs

Today, we pick the domain used to send the DSN from based on what we
presented to the client at EHLO time, which itself may be based on the
TLS negotiation (which is not necessarily trusted).

This is complex, not necessarily correct, and involves passing the
domain around through the queue and persisting it in the items.

So this patch simplifies that handling by always using the main domain
as specified by the configuration.

internal/queue/dsn.go +3 -3
internal/queue/dsn_test.go +2 -3
internal/queue/queue.go +13 -9
internal/queue/queue.pb.go +26 -29
internal/queue/queue.proto +0 -3
internal/queue/queue_test.go +8 -8
internal/smtpsrv/conn.go +1 -1
internal/smtpsrv/server.go +1 -1

diff --git a/internal/queue/dsn.go b/internal/queue/dsn.go
index 0300b3e..4475caf 100644
--- a/internal/queue/dsn.go
+++ b/internal/queue/dsn.go
@@ -15,11 +15,11 @@ const maxOrigMsgLen = 256 * 1024
 // There is a standard, https://tools.ietf.org/html/rfc3464, although most
 // MTAs seem to use a plain email and include an X-Failed-Recipients header.
 // We're going with the latter for now, may extend it to the former later.
-func deliveryStatusNotification(item *Item) ([]byte, error) {
+func deliveryStatusNotification(domainFrom string, item *Item) ([]byte, error) {
 	info := dsnInfo{
-		OurDomain:   item.Hostname,
+		OurDomain:   domainFrom,
 		Destination: item.From,
-		MessageID:   "chasquid-dsn-" + <-newID + "@" + item.Hostname,
+		MessageID:   "chasquid-dsn-" + <-newID + "@" + domainFrom,
 		Date:        time.Now().Format(time.RFC1123Z),
 		To:          item.To,
 		Recipients:  item.Rcpt,
diff --git a/internal/queue/dsn_test.go b/internal/queue/dsn_test.go
index 3e6e625..2068d08 100644
--- a/internal/queue/dsn_test.go
+++ b/internal/queue/dsn_test.go
@@ -13,12 +13,11 @@ func TestDSN(t *testing.T) {
 					"oh! horror!", ""},
 				{"newman@rcpt", Recipient_EMAIL, Recipient_FAILED,
 					"oh! the humanity!", ""}},
-			Data:     []byte("data ñaca"),
-			Hostname: "from.org",
+			Data: []byte("data ñaca"),
 		},
 	}
 
-	msg, err := deliveryStatusNotification(item)
+	msg, err := deliveryStatusNotification("dsnDomain", item)
 	if err != nil {
 		t.Error(err)
 	}
diff --git a/internal/queue/queue.go b/internal/queue/queue.go
index 1637ad1..eb74266 100644
--- a/internal/queue/queue.go
+++ b/internal/queue/queue.go
@@ -105,11 +105,14 @@ type Queue struct {
 
 	// Aliases resolver.
 	aliases *aliases.Resolver
+
+	// Domain we use to send delivery status notifications from.
+	dsnDomain string
 }
 
-// Load the queue and launch the sending loops on startup.
+// New creates a new Queue instance.
 func New(path string, localDomains *set.String, aliases *aliases.Resolver,
-	localC, remoteC courier.Courier) *Queue {
+	localC, remoteC courier.Courier, dsnDomain string) *Queue {
 
 	os.MkdirAll(path, 0700)
 
@@ -120,9 +123,11 @@ func New(path string, localDomains *set.String, aliases *aliases.Resolver,
 		localDomains: localDomains,
 		path:         path,
 		aliases:      aliases,
+		dsnDomain:    dsnDomain,
 	}
 }
 
+// Load the queue and launch the sending loops on startup.
 func (q *Queue) Load() error {
 	files, err := filepath.Glob(q.path + "/" + itemFilePrefix + "*")
 	if err != nil {
@@ -153,7 +158,7 @@ func (q *Queue) Len() int {
 }
 
 // Put an envelope in the queue.
-func (q *Queue) Put(hostname, from string, to []string, data []byte) (string, error) {
+func (q *Queue) Put(from string, to []string, data []byte) (string, error) {
 	if q.Len() >= maxQueueSize {
 		return "", errQueueFull
 	}
@@ -161,10 +166,9 @@ func (q *Queue) Put(hostname, from string, to []string, data []byte) (string, er
 
 	item := &Item{
 		Message: Message{
-			ID:       <-newID,
-			From:     from,
-			Data:     data,
-			Hostname: hostname,
+			ID:   <-newID,
+			From: from,
+			Data: data,
 		},
 		CreatedAt: time.Now(),
 	}
@@ -423,13 +427,13 @@ func (item *Item) countRcpt(status Recipient_Status) int {
 func sendDSN(tr *trace.Trace, q *Queue, item *Item) {
 	tr.Debugf("sending DSN")
 
-	msg, err := deliveryStatusNotification(item)
+	msg, err := deliveryStatusNotification(q.dsnDomain, item)
 	if err != nil {
 		tr.Errorf("failed to build DSN: %v", err)
 		return
 	}
 
-	id, err := q.Put(item.Hostname, "<>", []string{item.From}, msg)
+	id, err := q.Put("<>", []string{item.From}, msg)
 	if err != nil {
 		tr.Errorf("failed to queue DSN: %v", err)
 		return
diff --git a/internal/queue/queue.pb.go b/internal/queue/queue.pb.go
index a4e47d9..5ac595f 100644
--- a/internal/queue/queue.pb.go
+++ b/internal/queue/queue.pb.go
@@ -86,8 +86,6 @@ type Message struct {
 	Data []byte       `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"`
 	// Creation timestamp.
 	CreatedAtTs *google_protobuf.Timestamp `protobuf:"bytes,6,opt,name=created_at_ts,json=createdAtTs" json:"created_at_ts,omitempty"`
-	// Hostname of the server receiving this message.
-	Hostname string `protobuf:"bytes,7,opt,name=hostname" json:"hostname,omitempty"`
 }
 
 func (m *Message) Reset()                    { *m = Message{} }
@@ -137,31 +135,30 @@ func init() {
 func init() { proto.RegisterFile("queue.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-	// 403 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x90, 0x51, 0x8b, 0x9c, 0x30,
-	0x14, 0x85, 0xab, 0xeb, 0x38, 0x3b, 0xd7, 0x76, 0x2b, 0xa1, 0xa5, 0x61, 0xfa, 0xb2, 0x48, 0x1f,
-	0xba, 0x14, 0xb4, 0x4c, 0x1f, 0x0b, 0x85, 0x01, 0xdd, 0x22, 0x74, 0x87, 0xc1, 0xf5, 0x5d, 0x32,
-	0x9a, 0x71, 0x03, 0x6a, 0xac, 0x89, 0x0f, 0xfd, 0x47, 0xfd, 0x3f, 0xfd, 0x43, 0x4d, 0xa2, 0x4e,
-	0xa1, 0xfb, 0x96, 0x7b, 0xcf, 0xc9, 0xe5, 0x3b, 0x07, 0xbc, 0x9f, 0x23, 0x1d, 0x69, 0xd8, 0x0f,
-	0x5c, 0x72, 0xb4, 0x32, 0xc3, 0xf6, 0x6b, 0xcd, 0xe4, 0xd3, 0x78, 0x0a, 0x4b, 0xde, 0x46, 0x35,
-	0x6f, 0x48, 0x57, 0x47, 0x46, 0x3f, 0x8d, 0xe7, 0xa8, 0x97, 0xbf, 0x7a, 0x2a, 0x22, 0xc9, 0x5a,
-	0x2a, 0x24, 0x69, 0xfb, 0x7f, 0xaf, 0xe9, 0x46, 0xf0, 0xc7, 0x82, 0xf5, 0x03, 0x15, 0x82, 0xd4,
-	0x14, 0xdd, 0x80, 0x9d, 0xc6, 0xd8, 0xba, 0xb5, 0x3e, 0x6e, 0x32, 0x9b, 0xc5, 0x08, 0x81, 0x73,
-	0x1e, 0x78, 0x8b, 0x6d, 0xb3, 0x31, 0x6f, 0xed, 0xc9, 0x39, 0xbe, 0xba, 0xbd, 0xd2, 0x1e, 0xc5,
-	0xf0, 0x01, 0x9c, 0xa1, 0xec, 0x25, 0x76, 0xd4, 0xc6, 0xdb, 0xf9, 0xe1, 0xc4, 0x97, 0xd1, 0x92,
-	0xf5, 0x8c, 0x76, 0x32, 0x33, 0xaa, 0xbe, 0x54, 0x11, 0x49, 0xf0, 0x4a, 0x5d, 0x7a, 0x99, 0x99,
-	0x37, 0xfa, 0x06, 0xaf, 0xca, 0x81, 0x12, 0x49, 0xab, 0x82, 0xc8, 0x42, 0x0a, 0xec, 0x2a, 0xd1,
-	0xdb, 0x6d, 0xc3, 0x9a, 0xf3, 0xba, 0x99, 0x33, 0xaa, 0x0c, 0x61, 0xbe, 0x20, 0x67, 0xde, 0xfc,
-	0x61, 0x2f, 0x73, 0x81, 0xb6, 0x70, 0xfd, 0xc4, 0x85, 0xec, 0x48, 0x4b, 0xf1, 0xda, 0x10, 0x5e,
-	0xe6, 0xe0, 0xb7, 0x0d, 0x9b, 0x0b, 0x03, 0xc2, 0xb0, 0x26, 0x55, 0x35, 0xa8, 0x94, 0x73, 0xb8,
-	0x65, 0x44, 0x77, 0xe0, 0xe8, 0x82, 0x4c, 0xc2, 0x9b, 0xdd, 0xdb, 0xff, 0xe9, 0xc3, 0x5c, 0x89,
-	0x99, 0xb1, 0xa0, 0x08, 0x5c, 0x05, 0x21, 0x47, 0xa1, 0xc2, 0x6b, 0xf3, 0xbb, 0x67, 0xe6, 0x47,
-	0x23, 0x67, 0xb3, 0x0d, 0x7d, 0x86, 0x37, 0x0d, 0x11, 0xb2, 0x38, 0x13, 0xd6, 0x8c, 0x03, 0x2d,
-	0xda, 0xa9, 0x65, 0xd5, 0x94, 0x46, 0x40, 0x5a, 0xbb, 0x9f, 0xa4, 0xa5, 0xff, 0x3b, 0xf0, 0xf9,
-	0xc0, 0x6a, 0xd6, 0x91, 0xa6, 0x58, 0x80, 0x57, 0xc6, 0xfd, 0x7a, 0xd9, 0xef, 0xa7, 0x75, 0xf0,
-	0x1e, 0x1c, 0xcd, 0x86, 0x36, 0xb0, 0x4a, 0x1e, 0xf6, 0xe9, 0x0f, 0xff, 0x05, 0xba, 0x06, 0xe7,
-	0x98, 0x1e, 0x13, 0xdf, 0x0a, 0x3e, 0x81, 0x3b, 0xb1, 0x20, 0x0f, 0xd6, 0xc7, 0xe4, 0x10, 0xa7,
-	0x87, 0xef, 0x93, 0xe1, 0x31, 0x39, 0xe4, 0xbe, 0x85, 0x00, 0xdc, 0x7b, 0xf5, 0x29, 0x89, 0x7d,
-	0xfb, 0xe4, 0x9a, 0x9e, 0xbf, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x8f, 0x29, 0x0e, 0xd0, 0x5a,
-	0x02, 0x00, 0x00,
+	// 386 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x50, 0xd1, 0x0e, 0x93, 0x30,
+	0x14, 0x15, 0x06, 0xcc, 0x5d, 0x74, 0x92, 0x46, 0x23, 0x99, 0x2f, 0x0b, 0xf1, 0xc1, 0xc5, 0x04,
+	0xcc, 0x7c, 0x34, 0x31, 0x59, 0x02, 0x33, 0x24, 0x6e, 0x59, 0x18, 0xef, 0xa4, 0x83, 0x0e, 0x9b,
+	0xc0, 0x8a, 0xb4, 0x3c, 0xf8, 0x47, 0xfe, 0x81, 0xbf, 0x67, 0x5b, 0x40, 0x13, 0x7d, 0xbb, 0x3d,
+	0xe7, 0xf4, 0xde, 0x73, 0x0e, 0xb8, 0xdf, 0x07, 0x32, 0x90, 0xb0, 0xeb, 0x99, 0x60, 0xc8, 0xd6,
+	0x8f, 0xcd, 0xa7, 0x9a, 0x8a, 0x6f, 0xc3, 0x2d, 0x2c, 0x59, 0x1b, 0xd5, 0xac, 0xc1, 0x8f, 0x3a,
+	0xd2, 0xfc, 0x6d, 0xb8, 0x47, 0x9d, 0xf8, 0xd1, 0x11, 0x1e, 0x09, 0xda, 0x12, 0x2e, 0x70, 0xdb,
+	0xfd, 0x9d, 0xc6, 0x1d, 0xc1, 0x2f, 0x03, 0x96, 0x27, 0xc2, 0x39, 0xae, 0x09, 0x5a, 0x83, 0x99,
+	0xc6, 0xbe, 0xb1, 0x35, 0xde, 0xad, 0x32, 0x93, 0xc6, 0x08, 0x81, 0x75, 0xef, 0x59, 0xeb, 0x9b,
+	0x1a, 0xd1, 0xb3, 0xd2, 0xe4, 0xcc, 0x5f, 0x6c, 0x17, 0x4a, 0x23, 0x3d, 0xbc, 0x05, 0xab, 0x2f,
+	0x3b, 0xe1, 0x5b, 0x12, 0x71, 0xf7, 0x5e, 0x38, 0xfa, 0xcb, 0x48, 0x49, 0x3b, 0x4a, 0x1e, 0x22,
+	0xd3, 0xac, 0xda, 0x54, 0x61, 0x81, 0x7d, 0x5b, 0x6e, 0x7a, 0x96, 0xe9, 0x19, 0x7d, 0x86, 0xe7,
+	0x65, 0x4f, 0xb0, 0x20, 0x55, 0x81, 0x45, 0x21, 0xb8, 0xef, 0x48, 0xd2, 0xdd, 0x6f, 0xc2, 0x9a,
+	0xb1, 0xba, 0x99, 0x32, 0xca, 0x0c, 0x61, 0x3e, 0x5b, 0xce, 0xdc, 0xe9, 0xc3, 0x41, 0xe4, 0x3c,
+	0xf8, 0x69, 0xc2, 0xea, 0xcf, 0x1d, 0xe4, 0xc3, 0x12, 0x57, 0x55, 0x2f, 0x93, 0x4c, 0x01, 0xe6,
+	0x27, 0xda, 0x81, 0xa5, 0x4a, 0xd0, 0x29, 0xd6, 0xfb, 0x57, 0xff, 0x3a, 0x0c, 0x73, 0x49, 0x66,
+	0x5a, 0x82, 0x22, 0x70, 0xe4, 0x21, 0x31, 0x70, 0x19, 0x50, 0x89, 0x5f, 0xff, 0x27, 0xbe, 0x6a,
+	0x3a, 0x9b, 0x64, 0xe8, 0x03, 0xbc, 0x6c, 0x30, 0x17, 0xc5, 0x1d, 0xd3, 0x66, 0xe8, 0x49, 0xd1,
+	0x8e, 0x4d, 0xca, 0x36, 0x94, 0x05, 0xa4, 0xb8, 0xe3, 0x48, 0xcd, 0x1d, 0xef, 0xc0, 0x63, 0x3d,
+	0xad, 0xe9, 0x03, 0x37, 0xc5, 0x6c, 0xd8, 0xd6, 0xea, 0x17, 0x33, 0x7e, 0x18, 0xe1, 0xe0, 0x0d,
+	0x58, 0xca, 0x1b, 0x5a, 0x81, 0x9d, 0x9c, 0x0e, 0xe9, 0x57, 0xef, 0x09, 0x7a, 0x0a, 0xd6, 0x25,
+	0xbd, 0x24, 0x9e, 0x11, 0xbc, 0x07, 0x67, 0xf4, 0x82, 0x5c, 0x58, 0x5e, 0x92, 0x73, 0x9c, 0x9e,
+	0xbf, 0x8c, 0x82, 0x6b, 0x72, 0xce, 0x3d, 0x03, 0x01, 0x38, 0x47, 0xf9, 0x29, 0x89, 0x3d, 0xf3,
+	0xe6, 0xe8, 0x2e, 0x3f, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xda, 0xc1, 0x0d, 0xbb, 0x3e, 0x02,
+	0x00, 0x00,
 }
diff --git a/internal/queue/queue.proto b/internal/queue/queue.proto
index 2d2d514..80218cf 100644
--- a/internal/queue/queue.proto
+++ b/internal/queue/queue.proto
@@ -19,9 +19,6 @@ message Message {
 
 	// Creation timestamp.
 	google.protobuf.Timestamp created_at_ts = 6;
-
-	// Hostname of the server receiving this message.
-	string hostname = 7;
 }
 
 message Recipient {
diff --git a/internal/queue/queue_test.go b/internal/queue/queue_test.go
index f729f1c..649c7ef 100644
--- a/internal/queue/queue_test.go
+++ b/internal/queue/queue_test.go
@@ -64,11 +64,11 @@ func TestBasic(t *testing.T) {
 	localC := newTestCourier()
 	remoteC := newTestCourier()
 	q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
-		localC, remoteC)
+		localC, remoteC, "dsndomain")
 
 	localC.wg.Add(2)
 	remoteC.wg.Add(1)
-	id, err := q.Put("host", "from", []string{"am@loco", "x@remote", "nodomain"}, []byte("data"))
+	id, err := q.Put("from", []string{"am@loco", "x@remote", "nodomain"}, []byte("data"))
 	if err != nil {
 		t.Fatalf("Put: %v", err)
 	}
@@ -115,7 +115,7 @@ func TestBasic(t *testing.T) {
 
 func TestFullQueue(t *testing.T) {
 	q := New("/tmp/queue_test", set.NewString(), aliases.NewResolver(),
-		dumbCourier, dumbCourier)
+		dumbCourier, dumbCourier, "dsndomain")
 
 	// Force-insert maxQueueSize items in the queue.
 	oneID := ""
@@ -135,7 +135,7 @@ func TestFullQueue(t *testing.T) {
 	}
 
 	// This one should fail due to the queue being too big.
-	id, err := q.Put("host", "from", []string{"to"}, []byte("data-qf"))
+	id, err := q.Put("from", []string{"to"}, []byte("data-qf"))
 	if err != errQueueFull {
 		t.Errorf("Not failed as expected: %v - %v", id, err)
 	}
@@ -146,7 +146,7 @@ func TestFullQueue(t *testing.T) {
 	q.q[oneID].WriteTo(q.path)
 	q.Remove(oneID)
 
-	id, err = q.Put("host", "from", []string{"to"}, []byte("data"))
+	id, err = q.Put("from", []string{"to"}, []byte("data"))
 	if err != nil {
 		t.Errorf("Put: %v", err)
 	}
@@ -164,7 +164,7 @@ var dumbCourier = DumbCourier{}
 
 func TestAliases(t *testing.T) {
 	q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
-		dumbCourier, dumbCourier)
+		dumbCourier, dumbCourier, "dsndomain")
 
 	q.aliases.AddDomain("loco")
 	q.aliases.AddAliasForTesting("ab@loco", "pq@loco", aliases.EMAIL)
@@ -187,7 +187,7 @@ func TestAliases(t *testing.T) {
 			{"ata@hualpa", Recipient_EMAIL, Recipient_PENDING, "", "cd@loco"}}},
 	}
 	for _, c := range cases {
-		id, err := q.Put("host", "from", c.to, []byte("data"))
+		id, err := q.Put("from", c.to, []byte("data"))
 		if err != nil {
 			t.Errorf("Put: %v", err)
 		}
@@ -201,7 +201,7 @@ func TestAliases(t *testing.T) {
 
 func TestPipes(t *testing.T) {
 	q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
-		dumbCourier, dumbCourier)
+		dumbCourier, dumbCourier, "dsndomain")
 	item := &Item{
 		Message: Message{
 			ID:   <-newID,
diff --git a/internal/smtpsrv/conn.go b/internal/smtpsrv/conn.go
index e464a3b..592091f 100644
--- a/internal/smtpsrv/conn.go
+++ b/internal/smtpsrv/conn.go
@@ -510,7 +510,7 @@ func (c *Conn) DATA(params string) (code int, msg string) {
 
 	// There are no partial failures here: we put it in the queue, and then if
 	// individual deliveries fail, we report via email.
-	msgID, err := c.queue.Put(c.hostname, c.mailFrom, c.rcptTo, c.data)
+	msgID, err := c.queue.Put(c.mailFrom, c.rcptTo, c.data)
 	if err != nil {
 		return 554, fmt.Sprintf("Failed to enqueue message: %v", err)
 	}
diff --git a/internal/smtpsrv/server.go b/internal/smtpsrv/server.go
index 4172737..ad4a4d5 100644
--- a/internal/smtpsrv/server.go
+++ b/internal/smtpsrv/server.go
@@ -119,7 +119,7 @@ func (s *Server) InitDomainInfo(dir string) *domaininfo.DB {
 }
 
 func (s *Server) InitQueue(path string, localC, remoteC courier.Courier) {
-	q := queue.New(path, s.localDomains, s.aliasesR, localC, remoteC)
+	q := queue.New(path, s.localDomains, s.aliasesR, localC, remoteC, s.Hostname)
 	err := q.Load()
 	if err != nil {
 		glog.Fatalf("Error loading queue: %v", err)