author | Alberto Bertogli
<albertito@blitiri.com.ar> 2016-09-12 02:47:36 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2016-10-09 23:50:24 UTC |
parent | 69222284e077cf4b70ebe045a3a001686bbe1d97 |
chasquid.go | +57 | -33 |
chasquid_test.go | +1 | -1 |
internal/config/config.go | +7 | -3 |
internal/config/config.pb.go | +21 | -17 |
internal/config/config.proto | +11 | -5 |
internal/config/config_test.go | +11 | -7 |
internal/systemd/systemd.go | +22 | -7 |
internal/systemd/systemd_test.go | +36 | -15 |
test/t-01-simple_local/config/chasquid.conf | +2 | -1 |
test/t-02-exim/config/chasquid.conf | +2 | -1 |
diff --git a/chasquid.go b/chasquid.go index dd85229..7c93b6c 100644 --- a/chasquid.go +++ b/chasquid.go @@ -94,30 +94,37 @@ func main() { // as a remote domain (for loops, alias resolutions, etc.). s.AddDomain("localhost") + // Load the addresses and listeners. + systemdLs, err := systemd.Listeners() + if err != nil { + glog.Fatalf("Error getting systemd listeners: %v", err) + } + + loadAddresses(s, conf.SmtpAddress, systemdLs["smtp"], ModeSMTP) + loadAddresses(s, conf.SubmissionAddress, systemdLs["submission"], ModeSubmission) + + s.ListenAndServe() +} + +func loadAddresses(srv *Server, addrs []string, ls []net.Listener, mode SocketMode) { // Load addresses. acount := 0 - for _, addr := range conf.Address { + for _, addr := range addrs { // The "systemd" address indicates we get listeners via systemd. if addr == "systemd" { - ls, err := systemd.Listeners() - if err != nil { - glog.Fatalf("Error getting listeners via systemd: %v", err) - } - s.AddListeners(ls) + srv.AddListeners(ls, mode) acount += len(ls) } else { - s.AddAddr(addr) + srv.AddAddr(addr, mode) acount++ } } if acount == 0 { - glog.Errorf("No addresses/listeners configured") - glog.Errorf("If using systemd, check that you started chasquid.socket") + glog.Errorf("No %v addresses/listeners", mode) + glog.Errorf("If using systemd, check that you named the sockets") glog.Fatalf("Exiting") } - - s.ListenAndServe() } // Helper to load a single domain configuration into the server. @@ -160,6 +167,15 @@ func setupSignalHandling() { }() } +// Mode for a socket (listening or connection). +// We keep them distinct, as policies can differ between them. +type SocketMode string + +const ( + ModeSMTP SocketMode = "SMTP" + ModeSubmission SocketMode = "Submission" +) + type Server struct { // Main hostname, used for display only. Hostname string @@ -171,10 +187,10 @@ type Server struct { certs, keys []string // Addresses. - addrs []string + addrs map[SocketMode][]string // Listeners (that came via systemd). - listeners []net.Listener + listeners map[SocketMode][]net.Listener // TLS config. tlsConfig *tls.Config @@ -197,6 +213,8 @@ type Server struct { func NewServer() *Server { return &Server{ + addrs: map[SocketMode][]string{}, + listeners: map[SocketMode][]net.Listener{}, connTimeout: 20 * time.Minute, commandTimeout: 1 * time.Minute, localDomains: &set.String{}, @@ -209,12 +227,12 @@ func (s *Server) AddCerts(cert, key string) { s.keys = append(s.keys, key) } -func (s *Server) AddAddr(a string) { - s.addrs = append(s.addrs, a) +func (s *Server) AddAddr(a string, m SocketMode) { + s.addrs[m] = append(s.addrs[m], a) } -func (s *Server) AddListeners(ls []net.Listener) { - s.listeners = append(s.listeners, ls...) +func (s *Server) AddListeners(ls []net.Listener, m SocketMode) { + s.listeners[m] = append(s.listeners[m], ls...) } func (s *Server) AddDomain(d string) { @@ -256,26 +274,28 @@ func (s *Server) ListenAndServe() { s.queue = queue.New( &courier.Procmail{}, &courier.SMTP{}, s.localDomains) - for _, addr := range s.addrs { - // Listen. - l, err := net.Listen("tcp", addr) - if err != nil { - glog.Fatalf("Error listening: %v", err) - } - defer l.Close() + for m, addrs := range s.addrs { + for _, addr := range addrs { + // Listen. + l, err := net.Listen("tcp", addr) + if err != nil { + glog.Fatalf("Error listening: %v", err) + } - glog.Infof("Server listening on %s", addr) + glog.Infof("Server listening on %s (%v)", addr, m) - // Serve. - go s.serve(l) + // Serve. + go s.serve(l, m) + } } - for _, l := range s.listeners { - defer l.Close() - glog.Infof("Server listening on %s (via systemd)", l.Addr()) + for m, ls := range s.listeners { + for _, l := range ls { + glog.Infof("Server listening on %s (%v, via systemd)", l.Addr(), m) - // Serve. - go s.serve(l) + // Serve. + go s.serve(l, m) + } } // Never return. If the serve goroutines have problems, they will abort @@ -285,7 +305,7 @@ func (s *Server) ListenAndServe() { } } -func (s *Server) serve(l net.Listener) { +func (s *Server) serve(l net.Listener, mode SocketMode) { for { conn, err := l.Accept() if err != nil { @@ -297,6 +317,7 @@ func (s *Server) serve(l net.Listener) { maxDataSize: s.MaxDataSize, netconn: conn, tc: textproto.NewConn(conn), + mode: mode, tlsConfig: s.tlsConfig, userDBs: s.userDBs, deadline: time.Now().Add(s.connTimeout), @@ -305,6 +326,8 @@ func (s *Server) serve(l net.Listener) { } go sc.Handle() } + + l.Close() } type Conn struct { @@ -317,6 +340,7 @@ type Conn struct { // Connection information. netconn net.Conn tc *textproto.Conn + mode SocketMode // System configuration. config *config.Config diff --git a/chasquid_test.go b/chasquid_test.go index d17770a..14f494c 100644 --- a/chasquid_test.go +++ b/chasquid_test.go @@ -379,7 +379,7 @@ func realMain(m *testing.M) int { s.Hostname = "localhost" s.MaxDataSize = 50 * 1024 * 1025 s.AddCerts(tmpDir+"/cert.pem", tmpDir+"/key.pem") - s.AddAddr(srvAddr) + s.AddAddr(srvAddr, ModeSMTP) udb := userdb.New("/dev/null") udb.AddUser("testuser", "testpasswd") diff --git a/internal/config/config.go b/internal/config/config.go index 0b48a69..f60400e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -43,8 +43,11 @@ func Load(path string) (*Config, error) { c.MaxDataSizeMb = 50 } - if len(c.Address) == 0 { - c.Address = append(c.Address, "systemd") + if len(c.SmtpAddress) == 0 { + c.SmtpAddress = append(c.SmtpAddress, "systemd") + } + if len(c.SubmissionAddress) == 0 { + c.SubmissionAddress = append(c.SubmissionAddress, "systemd") } if c.MailDeliveryAgentBin == "" { @@ -63,7 +66,8 @@ func logConfig(c *Config) { glog.Infof("Configuration:") glog.Infof(" Hostname: %q", c.Hostname) glog.Infof(" Max data size (MB): %d", c.MaxDataSizeMb) - glog.Infof(" Addresses: %v", c.Address) + glog.Infof(" SMTP Addresses: %v", c.SmtpAddress) + glog.Infof(" Submission Addresses: %v", c.SubmissionAddress) glog.Infof(" Monitoring address: %s", c.MonitoringAddress) glog.Infof(" MDA: %s %v", c.MailDeliveryAgentBin, c.MailDeliveryAgentArgs) } diff --git a/internal/config/config.pb.go b/internal/config/config.pb.go index ba208c0..bd6bf18 100644 --- a/internal/config/config.pb.go +++ b/internal/config/config.pb.go @@ -36,24 +36,27 @@ type Config struct { // Maximum email size, in megabytes. // Default: 50. MaxDataSizeMb int64 `protobuf:"varint,2,opt,name=max_data_size_mb" json:"max_data_size_mb,omitempty"` - // Addresses to listen on. + // Addresses to listen on for SMTP (usually port 25). // Default: "systemd", which means systemd passes sockets to us. - Address []string `protobuf:"bytes,3,rep,name=address" json:"address,omitempty"` + SmtpAddress []string `protobuf:"bytes,3,rep,name=smtp_address" json:"smtp_address,omitempty"` + // Addresses to listen on for submission (usually port 587). + // Default: "systemd", which means systemd passes sockets to us. + SubmissionAddress []string `protobuf:"bytes,4,rep,name=submission_address" json:"submission_address,omitempty"` // Address for the monitoring http server. // Default: no monitoring http server. - MonitoringAddress string `protobuf:"bytes,4,opt,name=monitoring_address" json:"monitoring_address,omitempty"` + MonitoringAddress string `protobuf:"bytes,5,opt,name=monitoring_address" json:"monitoring_address,omitempty"` // Mail delivery agent (MDA, also known as LDA) to use. // This should point to the binary to use to deliver email to local users. // The content of the email will be passed via stdin. // If it exits unsuccessfully, we assume the mail was not delivered. // Default: "procmail". - MailDeliveryAgentBin string `protobuf:"bytes,5,opt,name=mail_delivery_agent_bin" json:"mail_delivery_agent_bin,omitempty"` + MailDeliveryAgentBin string `protobuf:"bytes,6,opt,name=mail_delivery_agent_bin" json:"mail_delivery_agent_bin,omitempty"` // Command line arguments for the mail delivery agent. One per argument. // Some replacements will be done: // - "%user%" -> local user (anything before the @) // - "%domain%" -> domain (anything after the @) // Default: "-d", "%user" (adequate for procmail) - MailDeliveryAgentArgs []string `protobuf:"bytes,6,rep,name=mail_delivery_agent_args" json:"mail_delivery_agent_args,omitempty"` + MailDeliveryAgentArgs []string `protobuf:"bytes,7,rep,name=mail_delivery_agent_args" json:"mail_delivery_agent_args,omitempty"` } func (m *Config) Reset() { *m = Config{} } @@ -68,16 +71,17 @@ func init() { func init() { proto.RegisterFile("config.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 169 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x8e, 0x41, 0xca, 0xc2, 0x30, - 0x10, 0x46, 0xe9, 0xdf, 0xdf, 0xaa, 0x83, 0x60, 0xc9, 0xc6, 0xc1, 0x8d, 0xc5, 0x95, 0x2b, 0x37, - 0x1e, 0xc1, 0x83, 0x0c, 0x53, 0x13, 0xe3, 0x40, 0x93, 0x48, 0x12, 0x44, 0x3d, 0x8f, 0x07, 0xb5, - 0x06, 0xdc, 0xb9, 0xfd, 0xde, 0xe3, 0xf1, 0xc1, 0xe2, 0x14, 0xfc, 0x59, 0xec, 0xfe, 0x1a, 0x43, - 0x0e, 0xdb, 0x57, 0x05, 0xcd, 0xb1, 0x0c, 0xaa, 0x85, 0xd9, 0x25, 0xa4, 0xec, 0xd9, 0x19, 0xac, - 0xba, 0x6a, 0x37, 0x57, 0x08, 0xad, 0xe3, 0x3b, 0x69, 0xce, 0x4c, 0x49, 0x9e, 0x86, 0x5c, 0x8f, - 0x7f, 0x23, 0xa9, 0xd5, 0x12, 0xa6, 0xac, 0x75, 0x34, 0x29, 0x61, 0xdd, 0xd5, 0xa3, 0xba, 0x06, - 0xe5, 0x82, 0x97, 0x1c, 0xa2, 0x78, 0x4b, 0x5f, 0xf6, 0x5f, 0x32, 0x1b, 0x58, 0x39, 0x96, 0x81, - 0xb4, 0x19, 0xe4, 0x66, 0xe2, 0x83, 0xd8, 0x1a, 0x9f, 0xa9, 0x17, 0x8f, 0x93, 0x22, 0x74, 0x80, - 0xbf, 0x04, 0x8e, 0x36, 0x61, 0xf3, 0xc9, 0xf7, 0x4d, 0x79, 0x7b, 0x78, 0x07, 0x00, 0x00, 0xff, - 0xff, 0xa3, 0xe4, 0x58, 0xd3, 0xbd, 0x00, 0x00, 0x00, + // 186 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0xcf, 0xc1, 0x8a, 0xc2, 0x30, + 0x10, 0x80, 0x61, 0xba, 0xdd, 0xed, 0xee, 0x0e, 0x3d, 0x94, 0xb0, 0xb0, 0xc1, 0x8b, 0xc5, 0x93, + 0x27, 0x2f, 0x3e, 0x82, 0x0f, 0x12, 0x26, 0x26, 0xc6, 0x81, 0x26, 0x29, 0x99, 0x28, 0xea, 0xfb, + 0xf9, 0x5e, 0xd6, 0x80, 0x3d, 0x79, 0x9d, 0xef, 0x67, 0x86, 0x81, 0x76, 0x1f, 0xc3, 0x81, 0xdc, + 0x66, 0x4c, 0x31, 0xc7, 0xd5, 0xbd, 0x82, 0x66, 0x57, 0x06, 0xa2, 0x83, 0x9f, 0x63, 0xe4, 0x1c, + 0xd0, 0x5b, 0x59, 0xf5, 0xd5, 0xfa, 0x57, 0x48, 0xe8, 0x3c, 0x5e, 0x94, 0xc1, 0x8c, 0x8a, 0xe9, + 0x66, 0x95, 0xd7, 0xf2, 0x63, 0x92, 0x5a, 0xfc, 0x41, 0xcb, 0x3e, 0x8f, 0x0a, 0x8d, 0x49, 0x96, + 0x59, 0xd6, 0x7d, 0x3d, 0xf5, 0x0b, 0x10, 0x7c, 0xd2, 0x9e, 0x98, 0x29, 0x86, 0xd9, 0x3e, 0x5f, + 0xe6, 0x63, 0xa0, 0x1c, 0x13, 0x05, 0x37, 0xdb, 0x57, 0xb9, 0xb3, 0x84, 0x7f, 0x8f, 0x34, 0x28, + 0x63, 0x07, 0x3a, 0xdb, 0x74, 0x55, 0xe8, 0x6c, 0xc8, 0x4a, 0x53, 0x90, 0x4d, 0x09, 0x7a, 0x90, + 0xef, 0x02, 0x4c, 0x8e, 0xe5, 0xf7, 0x73, 0xbd, 0x6e, 0xca, 0x3b, 0xdb, 0x47, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x75, 0x30, 0x88, 0xe6, 0xde, 0x00, 0x00, 0x00, } diff --git a/internal/config/config.proto b/internal/config/config.proto index 507c06d..493dbef 100644 --- a/internal/config/config.proto +++ b/internal/config/config.proto @@ -11,26 +11,32 @@ message Config { // Default: 50. int64 max_data_size_mb = 2; - // Addresses to listen on. + // Addresses to listen on for SMTP (usually port 25). // Default: "systemd", which means systemd passes sockets to us. - repeated string address = 3; + // systemd sockets must be named with "FileDescriptorName=smtp". + repeated string smtp_address = 3; + + // Addresses to listen on for submission (usually port 587). + // Default: "systemd", which means systemd passes sockets to us. + // systemd sockets must be named with "FileDescriptorName=submission". + repeated string submission_address = 4; // Address for the monitoring http server. // Default: no monitoring http server. - string monitoring_address = 4; + string monitoring_address = 5; // Mail delivery agent (MDA, also known as LDA) to use. // This should point to the binary to use to deliver email to local users. // The content of the email will be passed via stdin. // If it exits unsuccessfully, we assume the mail was not delivered. // Default: "procmail". - string mail_delivery_agent_bin = 5; + string mail_delivery_agent_bin = 6; // Command line arguments for the mail delivery agent. One per argument. // Some replacements will be done: // - "%user%" -> local user (anything before the @) // - "%domain%" -> domain (anything after the @) // Default: "-d", "%user" (adequate for procmail) - repeated string mail_delivery_agent_args = 6; + repeated string mail_delivery_agent_args = 7; } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6abdc47..790c2a0 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -40,8 +40,12 @@ func TestEmptyConfig(t *testing.T) { t.Errorf("max data size != 50: %d", c.MaxDataSizeMb) } - if len(c.Address) != 1 || c.Address[0] != "systemd" { - t.Errorf("unexpected address default: %v", c.Address) + if len(c.SmtpAddress) != 1 || c.SmtpAddress[0] != "systemd" { + t.Errorf("unexpected address default: %v", c.SmtpAddress) + } + + if len(c.SubmissionAddress) != 1 || c.SubmissionAddress[0] != "systemd" { + t.Errorf("unexpected address default: %v", c.SubmissionAddress) } if c.MonitoringAddress != "" { @@ -53,8 +57,8 @@ func TestEmptyConfig(t *testing.T) { func TestFullConfig(t *testing.T) { confStr := ` hostname: "joust" - address: ":1234" - address: ":5678" + smtp_address: ":1234" + smtp_address: ":5678" monitoring_address: ":1111" max_data_size_mb: 26 ` @@ -75,9 +79,9 @@ func TestFullConfig(t *testing.T) { t.Errorf("max data size != 26: %d", c.MaxDataSizeMb) } - if len(c.Address) != 2 || - c.Address[0] != ":1234" || c.Address[1] != ":5678" { - t.Errorf("different address: %v", c.Address) + if len(c.SmtpAddress) != 2 || + c.SmtpAddress[0] != ":1234" || c.SmtpAddress[1] != ":5678" { + t.Errorf("different address: %v", c.SmtpAddress) } if c.MonitoringAddress != ":1111" { diff --git a/internal/systemd/systemd.go b/internal/systemd/systemd.go index 4cbaf5e..75f2686 100644 --- a/internal/systemd/systemd.go +++ b/internal/systemd/systemd.go @@ -7,6 +7,7 @@ import ( "net" "os" "strconv" + "strings" "syscall" ) @@ -21,10 +22,12 @@ var ( // Listeners creates a slice net.Listener from the file descriptors passed // by systemd, via the LISTEN_FDS environment variable. -// See sd_listen_fds(3) for more details. -func Listeners() ([]net.Listener, error) { +// See sd_listen_fds(3) and sd_listen_fds_with_names(3) for more details. +func Listeners() (map[string][]net.Listener, error) { pidStr := os.Getenv("LISTEN_PID") nfdsStr := os.Getenv("LISTEN_FDS") + fdNamesStr := os.Getenv("LISTEN_FDNAMES") + fdNames := strings.Split(fdNamesStr, ":") // Nothing to do if the variables are not set. if pidStr == "" || nfdsStr == "" { @@ -45,26 +48,38 @@ func Listeners() ([]net.Listener, error) { "error reading $LISTEN_FDS=%q: %v", nfdsStr, err) } - listeners := []net.Listener{} + // We should have as many names as we have descriptors. + // Note that if we have no descriptors, fdNames will be [""] (due to how + // strings.Split works), so we consider that special case. + if nfds > 0 && (fdNamesStr == "" || len(fdNames) != nfds) { + return nil, fmt.Errorf( + "Incorrect LISTEN_FDNAMES, have you set FileDescriptorName?") + } - for fd := firstFD; fd < firstFD+nfds; fd++ { + listeners := map[string][]net.Listener{} + + for i := 0; i < nfds; i++ { + fd := firstFD + i // We don't want childs to inherit these file descriptors. syscall.CloseOnExec(fd) - name := fmt.Sprintf("[systemd-fd-%d]", fd) - lis, err := net.FileListener(os.NewFile(uintptr(fd), name)) + name := fdNames[i] + + sysName := fmt.Sprintf("[systemd-fd-%d-%v]", fd, name) + lis, err := net.FileListener(os.NewFile(uintptr(fd), sysName)) if err != nil { return nil, fmt.Errorf( "Error making listener out of fd %d: %v", fd, err) } - listeners = append(listeners, lis) + listeners[name] = append(listeners[name], lis) } // Remove them from the environment, to prevent accidental reuse (by // us or children processes). os.Unsetenv("LISTEN_PID") os.Unsetenv("LISTEN_FDS") + os.Unsetenv("LISTEN_FDNAMES") return listeners, nil } diff --git a/internal/systemd/systemd_test.go b/internal/systemd/systemd_test.go index 34bca4b..226b124 100644 --- a/internal/systemd/systemd_test.go +++ b/internal/systemd/systemd_test.go @@ -5,12 +5,14 @@ import ( "net" "os" "strconv" + "strings" "testing" ) -func setenv(pid, fds string) { +func setenv(pid, fds string, names ...string) { os.Setenv("LISTEN_PID", pid) os.Setenv("LISTEN_FDS", fds) + os.Setenv("LISTEN_FDNAMES", strings.Join(names, ":")) } func TestEmptyEnvironment(t *testing.T) { @@ -30,16 +32,26 @@ func TestEmptyEnvironment(t *testing.T) { } func TestBadEnvironment(t *testing.T) { + // Create a listener so we have something to reference. + l := newListener(t) + firstFD = listenerFd(t, l) + ourPID := strconv.Itoa(os.Getpid()) - cases := []struct{ pid, fds string }{ - {"a", "4"}, - {ourPID, "a"}, + cases := []struct { + pid, fds string + names []string + }{ + {"a", "1", []string{"name"}}, // Invalid PID. + {ourPID, "a", []string{"name"}}, // Invalid number of fds. + {"1", "1", []string{"name"}}, // PID != ourselves. + {ourPID, "1", []string{"name1", "name2"}}, // Too many names. + {ourPID, "1", []string{}}, // Not enough names. } for _, c := range cases { - setenv(c.pid, c.fds) + setenv(c.pid, c.fds, c.names...) if ls, err := Listeners(); err == nil { - t.Logf("Case: LISTEN_PID=%q LISTEN_FDS=%q", c.pid, c.fds) + t.Logf("Case: LISTEN_PID=%q LISTEN_FDS=%q LISTEN_FDNAMES=%q", c.pid, c.fds, c.names) t.Errorf("Unexpected result: %v // %v", ls, err) } } @@ -98,13 +110,15 @@ func TestOneSocket(t *testing.T) { l := newListener(t) firstFD = listenerFd(t, l) - setenv(strconv.Itoa(os.Getpid()), "1") + setenv(strconv.Itoa(os.Getpid()), "1", "name") - ls, err := Listeners() - if err != nil || len(ls) != 1 { - t.Fatalf("Got an invalid result: %v // %v", ls, err) + lsMap, err := Listeners() + if err != nil || len(lsMap) != 1 { + t.Fatalf("Got an invalid result: %v // %v", lsMap, err) } + ls := lsMap["name"] + if !sameAddr(ls[0].Addr(), l.Addr()) { t.Errorf("Listener 0 address mismatch, expected %#v, got %#v", l.Addr(), ls[0].Addr()) @@ -134,11 +148,16 @@ func TestManySockets(t *testing.T) { firstFD = f0 - setenv(strconv.Itoa(os.Getpid()), "2") + setenv(strconv.Itoa(os.Getpid()), "2", "name1", "name2") - ls, err := Listeners() - if err != nil || len(ls) != 2 { - t.Fatalf("Got an invalid result: %v // %v", ls, err) + lsMap, err := Listeners() + if err != nil || len(lsMap) != 2 { + t.Fatalf("Got an invalid result: %v // %v", lsMap, err) + } + + ls := []net.Listener{ + lsMap["name1"][0], + lsMap["name2"][0], } if !sameAddr(ls[0].Addr(), l0.Addr()) { @@ -151,7 +170,9 @@ func TestManySockets(t *testing.T) { l1.Addr(), ls[1].Addr()) } - if os.Getenv("LISTEN_PID") != "" || os.Getenv("LISTEN_FDS") != "" { + if os.Getenv("LISTEN_PID") != "" || + os.Getenv("LISTEN_FDS") != "" || + os.Getenv("LISTEN_FDNAMES") != "" { t.Errorf("Failed to reset the environment") } } diff --git a/test/t-01-simple_local/config/chasquid.conf b/test/t-01-simple_local/config/chasquid.conf index 1302399..5c36cb4 100644 --- a/test/t-01-simple_local/config/chasquid.conf +++ b/test/t-01-simple_local/config/chasquid.conf @@ -1,4 +1,5 @@ -address: ":1025" +smtp_address: ":1025" +submission_address: ":1587" monitoring_address: ":1099" mail_delivery_agent_bin: "test-mda" diff --git a/test/t-02-exim/config/chasquid.conf b/test/t-02-exim/config/chasquid.conf index 1302399..5c36cb4 100644 --- a/test/t-02-exim/config/chasquid.conf +++ b/test/t-02-exim/config/chasquid.conf @@ -1,4 +1,5 @@ -address: ":1025" +smtp_address: ":1025" +submission_address: ":1587" monitoring_address: ":1099" mail_delivery_agent_bin: "test-mda"