1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-18 14:47:03 +00:00

queue: Get the DSN domain from the message

Picking the domain used in the DSN message "From" header is more
complicated than it needs to be, causing confusing code paths and having
different uses for the hostname, which should be purely aesthetic.

This patch makes the queue pick the DSN "From" domain from the message
itself, by looking for a local domain in either the sender or the
original recipients. We should find at least one, otherwise it'd be
relaying.

This allows the code to be simplified, and we can narrow the scope of
the hostname option even further.
This commit is contained in:
Alberto Bertogli
2016-11-03 00:48:34 +00:00
parent 2da74c1758
commit fea808f8e3
6 changed files with 43 additions and 36 deletions

View File

@@ -1,11 +1,7 @@
# Main/default hostname to use. # Default hostname to use when saying hello.
# This is used to say hello to clients, and by default as the domain # This is used to say hello to clients, for aesthetic purposes.
# we send delivery notifications errors from. # Default: the system's hostname.
# It should be a domain we can send email from, and we should have a
# certificate for it.
# It usually helps if our IP address resolves to it.
# Default: machine hostname.
#hostname: "mx.example.com" #hostname: "mx.example.com"
# Maximum email size, in megabytes. # Maximum email size, in megabytes.

View File

@@ -29,12 +29,9 @@ var _ = math.Inf
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Config struct { type Config struct {
// Main/default hostname to use. // Default hostname to use when saying hello.
// This is used to say hello to clients, and by default as the domain // This is used to say hello to clients, for aesthetic purposes.
// we send delivery notifications errors from. // Default: the system's hostname.
// It should be a domain we can send email from.
// It usually helps if our IP address resolves to it.
// Default: machine hostname.
Hostname string `protobuf:"bytes,1,opt,name=hostname" json:"hostname,omitempty"` Hostname string `protobuf:"bytes,1,opt,name=hostname" json:"hostname,omitempty"`
// Maximum email size, in megabytes. // Maximum email size, in megabytes.
// Default: 50. // Default: 50.
@@ -48,6 +45,7 @@ type Config struct {
// systemd sockets must be named with "FileDescriptorName=submission". // systemd sockets must be named with "FileDescriptorName=submission".
SubmissionAddress []string `protobuf:"bytes,4,rep,name=submission_address,json=submissionAddress" json:"submission_address,omitempty"` SubmissionAddress []string `protobuf:"bytes,4,rep,name=submission_address,json=submissionAddress" json:"submission_address,omitempty"`
// Address for the monitoring http server. // Address for the monitoring http server.
// Do NOT expose this to the public internet.
// Default: no monitoring http server. // Default: no monitoring http server.
MonitoringAddress string `protobuf:"bytes,5,opt,name=monitoring_address,json=monitoringAddress" json:"monitoring_address,omitempty"` MonitoringAddress string `protobuf:"bytes,5,opt,name=monitoring_address,json=monitoringAddress" json:"monitoring_address,omitempty"`
// Mail delivery agent (MDA, also known as LDA) to use. // Mail delivery agent (MDA, also known as LDA) to use.
@@ -57,10 +55,17 @@ type Config struct {
// Default: "procmail". // Default: "procmail".
MailDeliveryAgentBin string `protobuf:"bytes,6,opt,name=mail_delivery_agent_bin,json=mailDeliveryAgentBin" json:"mail_delivery_agent_bin,omitempty"` MailDeliveryAgentBin string `protobuf:"bytes,6,opt,name=mail_delivery_agent_bin,json=mailDeliveryAgentBin" json:"mail_delivery_agent_bin,omitempty"`
// Command line arguments for the mail delivery agent. One per argument. // Command line arguments for the mail delivery agent. One per argument.
// Some replacements will be done: // Some replacements will be done.
// - "%user%" -> local user (anything before the @) // On an email sent from marsnik@mars to venera@venus:
// - "%domain%" -> domain (anything after the @) // - %from% -> from address (marsnik@mars)
// Default: "-d", "%user" (adequate for procmail) // - %from_user% -> from user (marsnik)
// - %from_domain% -> from domain (mars)
// - %to% -> to address (venera@venus)
// - %to_user% -> to user (venera)
// - %to_domain% -> to domain (venus)
//
// Default: "-f", "%from%", "-d", "%to_user%" (adequate for procmail
// and maildrop).
MailDeliveryAgentArgs []string `protobuf:"bytes,7,rep,name=mail_delivery_agent_args,json=mailDeliveryAgentArgs" json:"mail_delivery_agent_args,omitempty"` MailDeliveryAgentArgs []string `protobuf:"bytes,7,rep,name=mail_delivery_agent_args,json=mailDeliveryAgentArgs" json:"mail_delivery_agent_args,omitempty"`
// Directory where we store our persistent data. // Directory where we store our persistent data.
// Default: "/var/lib/chasquid" // Default: "/var/lib/chasquid"

View File

@@ -2,13 +2,9 @@
syntax = "proto3"; syntax = "proto3";
message Config { message Config {
// Main/default hostname to use. // Default hostname to use when saying hello.
// This is used to say hello to clients, and by default as the domain // This is used to say hello to clients, for aesthetic purposes.
// we send delivery notifications errors from. // Default: the system's hostname.
// It should be a domain we can send email from, and we should have a
// certificate for it.
// It usually helps if our IP address resolves to it.
// Default: machine hostname.
string hostname = 1; string hostname = 1;
// Maximum email size, in megabytes. // Maximum email size, in megabytes.

View File

@@ -105,14 +105,11 @@ type Queue struct {
// Aliases resolver. // Aliases resolver.
aliases *aliases.Resolver aliases *aliases.Resolver
// Domain we use to send delivery status notifications from.
dsnDomain string
} }
// New creates a new Queue instance. // New creates a new Queue instance.
func New(path string, localDomains *set.String, aliases *aliases.Resolver, func New(path string, localDomains *set.String, aliases *aliases.Resolver,
localC, remoteC courier.Courier, dsnDomain string) *Queue { localC, remoteC courier.Courier) *Queue {
os.MkdirAll(path, 0700) os.MkdirAll(path, 0700)
@@ -123,7 +120,6 @@ func New(path string, localDomains *set.String, aliases *aliases.Resolver,
localDomains: localDomains, localDomains: localDomains,
path: path, path: path,
aliases: aliases, aliases: aliases,
dsnDomain: dsnDomain,
} }
} }
@@ -434,7 +430,21 @@ func (item *Item) countRcpt(statuses ...Recipient_Status) int {
func sendDSN(tr *trace.Trace, q *Queue, item *Item) { func sendDSN(tr *trace.Trace, q *Queue, item *Item) {
tr.Debugf("sending DSN") tr.Debugf("sending DSN")
msg, err := deliveryStatusNotification(q.dsnDomain, item) // Pick a (local) domain to send the DSN from. We should always find one,
// as otherwise we're relaying.
domain := "unknown"
if item.From != "<>" && envelope.DomainIn(item.From, q.localDomains) {
domain = envelope.DomainOf(item.From)
} else {
for _, rcpt := range item.Rcpt {
if envelope.DomainIn(rcpt.OriginalAddress, q.localDomains) {
domain = envelope.DomainOf(rcpt.OriginalAddress)
break
}
}
}
msg, err := deliveryStatusNotification(domain, item)
if err != nil { if err != nil {
tr.Errorf("failed to build DSN: %v", err) tr.Errorf("failed to build DSN: %v", err)
return return

View File

@@ -64,7 +64,7 @@ func TestBasic(t *testing.T) {
localC := newTestCourier() localC := newTestCourier()
remoteC := newTestCourier() remoteC := newTestCourier()
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(), q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
localC, remoteC, "dsndomain") localC, remoteC)
localC.wg.Add(2) localC.wg.Add(2)
remoteC.wg.Add(1) remoteC.wg.Add(1)
@@ -117,7 +117,7 @@ func TestDSNOnTimeout(t *testing.T) {
localC := newTestCourier() localC := newTestCourier()
remoteC := newTestCourier() remoteC := newTestCourier()
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(), q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
localC, remoteC, "dsndomain") localC, remoteC)
// Insert an expired item in the queue. // Insert an expired item in the queue.
item := &Item{ item := &Item{
@@ -156,7 +156,7 @@ func TestAliases(t *testing.T) {
localC := newTestCourier() localC := newTestCourier()
remoteC := newTestCourier() remoteC := newTestCourier()
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(), q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
localC, remoteC, "dsndomain") localC, remoteC)
q.aliases.AddDomain("loco") q.aliases.AddDomain("loco")
q.aliases.AddAliasForTesting("ab@loco", "pq@loco", aliases.EMAIL) q.aliases.AddAliasForTesting("ab@loco", "pq@loco", aliases.EMAIL)
@@ -207,7 +207,7 @@ var dumbCourier = DumbCourier{}
func TestFullQueue(t *testing.T) { func TestFullQueue(t *testing.T) {
q := New("/tmp/queue_test", set.NewString(), aliases.NewResolver(), q := New("/tmp/queue_test", set.NewString(), aliases.NewResolver(),
dumbCourier, dumbCourier, "dsndomain") dumbCourier, dumbCourier)
// Force-insert maxQueueSize items in the queue. // Force-insert maxQueueSize items in the queue.
oneID := "" oneID := ""
@@ -247,7 +247,7 @@ func TestFullQueue(t *testing.T) {
func TestPipes(t *testing.T) { func TestPipes(t *testing.T) {
q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(), q := New("/tmp/queue_test", set.NewString("loco"), aliases.NewResolver(),
dumbCourier, dumbCourier, "dsndomain") dumbCourier, dumbCourier)
item := &Item{ item := &Item{
Message: Message{ Message: Message{
ID: <-newID, ID: <-newID,

View File

@@ -123,7 +123,7 @@ func (s *Server) InitDomainInfo(dir string) *domaininfo.DB {
} }
func (s *Server) InitQueue(path string, localC, remoteC courier.Courier) { func (s *Server) InitQueue(path string, localC, remoteC courier.Courier) {
q := queue.New(path, s.localDomains, s.aliasesR, localC, remoteC, s.Hostname) q := queue.New(path, s.localDomains, s.aliasesR, localC, remoteC)
err := q.Load() err := q.Load()
if err != nil { if err != nil {
log.Fatalf("Error loading queue: %v", err) log.Fatalf("Error loading queue: %v", err)