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

Support submission (directly) over TLS (submissions/smtps/port 465)

This patch adds support for TLS-wrapped submission connections.

Instead of clients establishing a connection over plain text and then
using STARTTLS to switch over a TLS connection, this new mode allows the
clients to connect directly over TLS, like it's done in HTTPS.

This is not an official standard yet, but it's reasonably common in
practice, and provides some advantages over the traditional submission
port.

The default port is 465, commonly used for this; chasquid defaults to
systemd file descriptor passing as for the other protocols (for now).
This commit is contained in:
Alberto Bertogli
2017-04-01 12:47:46 +01:00
parent c4255933bd
commit 213bc63a95
22 changed files with 157 additions and 48 deletions

View File

@@ -161,6 +161,8 @@ func main() {
systemdLs["smtp"], smtpsrv.ModeSMTP) systemdLs["smtp"], smtpsrv.ModeSMTP)
loadAddresses(s, conf.SubmissionAddress, loadAddresses(s, conf.SubmissionAddress,
systemdLs["submission"], smtpsrv.ModeSubmission) systemdLs["submission"], smtpsrv.ModeSubmission)
loadAddresses(s, conf.SubmissionOverTlsAddress,
systemdLs["submission_tls"], smtpsrv.ModeSubmissionTLS)
s.ListenAndServe() s.ListenAndServe()
} }

View File

@@ -0,0 +1,11 @@
[Unit]
Description=chasquid mail daemon (submission over TLS sockets)
[Socket]
ListenStream=465
FileDescriptorName=submission_tls
Service=chasquid.service
[Install]
WantedBy=chasquid.target

View File

@@ -1,6 +1,8 @@
[Unit] [Unit]
Description=chasquid mail daemon (service) Description=chasquid mail daemon (service)
Requires=chasquid-smtp.socket chasquid-submission.socket Requires=chasquid-smtp.socket \
chasquid-submission.socket \
chasquid-submission_tls.socket
[Service] [Service]
ExecStart=/usr/local/bin/chasquid \ ExecStart=/usr/local/bin/chasquid \

View File

@@ -50,6 +50,9 @@ func Load(path string) (*Config, error) {
if len(c.SubmissionAddress) == 0 { if len(c.SubmissionAddress) == 0 {
c.SubmissionAddress = append(c.SubmissionAddress, "systemd") c.SubmissionAddress = append(c.SubmissionAddress, "systemd")
} }
if len(c.SubmissionOverTlsAddress) == 0 {
c.SubmissionOverTlsAddress = append(c.SubmissionOverTlsAddress, "systemd")
}
if c.MailDeliveryAgentBin == "" { if c.MailDeliveryAgentBin == "" {
c.MailDeliveryAgentBin = "maildrop" c.MailDeliveryAgentBin = "maildrop"

View File

@@ -44,16 +44,20 @@ type Config struct {
// Default: "systemd", which means systemd passes sockets to us. // Default: "systemd", which means systemd passes sockets to us.
// 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"`
// Addresses to listen on for submission-over-TLS (usually port 465).
// Default: "systemd", which means systemd passes sockets to us.
// systemd sockets must be named with "FileDescriptorName=submission_tls".
SubmissionOverTlsAddress []string `protobuf:"bytes,5,rep,name=submission_over_tls_address,json=submissionOverTlsAddress" json:"submission_over_tls_address,omitempty"`
// Address for the monitoring http server. // Address for the monitoring http server.
// Do NOT expose this to the public internet. // 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,6,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.
// This should point to the binary to use to deliver email to local users. // This should point to the binary to use to deliver email to local users.
// The content of the email will be passed via stdin. // The content of the email will be passed via stdin.
// If it exits unsuccessfully, we assume the mail was not delivered. // If it exits unsuccessfully, we assume the mail was not delivered.
// Default: "maildrop". // Default: "maildrop".
MailDeliveryAgentBin string `protobuf:"bytes,6,opt,name=mail_delivery_agent_bin,json=mailDeliveryAgentBin" json:"mail_delivery_agent_bin,omitempty"` MailDeliveryAgentBin string `protobuf:"bytes,7,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.
// On an email sent from marsnik@mars to venera@venus: // On an email sent from marsnik@mars to venera@venus:
@@ -66,26 +70,26 @@ type Config struct {
// //
// Default: "-f", "%from%", "-d", "%to_user%" (adequate for procmail // Default: "-f", "%from%", "-d", "%to_user%" (adequate for procmail
// and maildrop). // 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,8,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"
DataDir string `protobuf:"bytes,8,opt,name=data_dir,json=dataDir" json:"data_dir,omitempty"` DataDir string `protobuf:"bytes,9,opt,name=data_dir,json=dataDir" json:"data_dir,omitempty"`
// Suffix separator, to perform suffix removal of local users. // Suffix separator, to perform suffix removal of local users.
// For example, if you set this to "-+", email to local user // For example, if you set this to "-+", email to local user
// "user-blah" and "user+blah" will be delivered to "user". // "user-blah" and "user+blah" will be delivered to "user".
// Including "+" is strongly encouraged, as it is assumed for email // Including "+" is strongly encouraged, as it is assumed for email
// forwarding. // forwarding.
// Default: "+". // Default: "+".
SuffixSeparators string `protobuf:"bytes,9,opt,name=suffix_separators,json=suffixSeparators" json:"suffix_separators,omitempty"` SuffixSeparators string `protobuf:"bytes,10,opt,name=suffix_separators,json=suffixSeparators" json:"suffix_separators,omitempty"`
// Characters to drop from the user part on local emails. // Characters to drop from the user part on local emails.
// For example, if you set this to "._", email to local user // For example, if you set this to "._", email to local user
// "u.se_r" will be delivered to "user". // "u.se_r" will be delivered to "user".
// Default: ".". // Default: ".".
DropCharacters string `protobuf:"bytes,10,opt,name=drop_characters,json=dropCharacters" json:"drop_characters,omitempty"` DropCharacters string `protobuf:"bytes,11,opt,name=drop_characters,json=dropCharacters" json:"drop_characters,omitempty"`
// Path where to write the mail log to. // Path where to write the mail log to.
// If "<syslog>", log using the syslog (at MAIL|INFO priority). // If "<syslog>", log using the syslog (at MAIL|INFO priority).
// Default: <syslog> // Default: <syslog>
MailLogPath string `protobuf:"bytes,11,opt,name=mail_log_path,json=mailLogPath" json:"mail_log_path,omitempty"` MailLogPath string `protobuf:"bytes,12,opt,name=mail_log_path,json=mailLogPath" json:"mail_log_path,omitempty"`
} }
func (m *Config) Reset() { *m = Config{} } func (m *Config) Reset() { *m = Config{} }
@@ -100,25 +104,27 @@ func init() {
func init() { proto.RegisterFile("config.proto", fileDescriptor0) } func init() { proto.RegisterFile("config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 320 bytes of a gzipped FileDescriptorProto // 351 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x91, 0xcd, 0x4e, 0x02, 0x31, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x92, 0x4d, 0x4f, 0x22, 0x41,
0x10, 0x80, 0x83, 0xab, 0xfc, 0x14, 0x50, 0x68, 0x34, 0x56, 0x4f, 0xc8, 0x05, 0x12, 0xa3, 0x17, 0x10, 0x86, 0xc3, 0xc2, 0xf2, 0xd1, 0xc0, 0x2e, 0x74, 0x76, 0xb3, 0xbd, 0x7a, 0x41, 0x2e, 0x90,
0x63, 0x3c, 0x23, 0x1c, 0x35, 0x31, 0xf0, 0x00, 0xcd, 0x2c, 0x5b, 0xba, 0x93, 0xd0, 0x76, 0xd3, 0x18, 0xbd, 0x18, 0xe3, 0xc9, 0x03, 0xc2, 0x51, 0xa3, 0x01, 0xef, 0x9d, 0x1a, 0xa6, 0x99, 0xe9,
0x29, 0x06, 0x79, 0x4d, 0x5f, 0xc8, 0x6c, 0xd1, 0xc5, 0x44, 0x8f, 0xf3, 0x7d, 0xdf, 0x64, 0x27, 0x64, 0xba, 0x7b, 0x52, 0xd5, 0x10, 0xe4, 0x67, 0xf8, 0x8b, 0xcd, 0x34, 0x32, 0x90, 0xe8, 0xb1,
0x5b, 0xd6, 0x59, 0x3a, 0xbb, 0x42, 0x7d, 0x5f, 0x78, 0x17, 0xdc, 0xf0, 0x33, 0x61, 0xf5, 0x69, 0x9e, 0xf7, 0x79, 0x53, 0x35, 0x93, 0x66, 0x9d, 0xa5, 0xb3, 0x2b, 0x9d, 0x5c, 0xe7, 0xe8, 0xbc,
0x04, 0xfc, 0x9a, 0x35, 0x73, 0x47, 0xc1, 0x82, 0x51, 0xa2, 0x36, 0xa8, 0x8d, 0x5b, 0xf3, 0x6a, 0x1b, 0xbe, 0xd7, 0x58, 0x7d, 0x1a, 0x00, 0x3f, 0x63, 0xcd, 0xd4, 0x91, 0xb7, 0x60, 0x94, 0xa8,
0xe6, 0x23, 0xd6, 0x33, 0xb0, 0x95, 0x19, 0x04, 0x90, 0x84, 0x3b, 0x25, 0x4d, 0x2a, 0x8e, 0x06, 0x0c, 0x2a, 0xe3, 0xd6, 0xbc, 0x9c, 0xf9, 0x88, 0xf5, 0x0c, 0x6c, 0x65, 0x0c, 0x1e, 0x24, 0xe9,
0xb5, 0x71, 0x32, 0xef, 0x1a, 0xd8, 0xce, 0x20, 0xc0, 0x02, 0x77, 0xea, 0x35, 0xe5, 0x37, 0xac, 0x9d, 0x92, 0x26, 0x12, 0x3f, 0x06, 0x95, 0x71, 0x75, 0xde, 0x35, 0xb0, 0x9d, 0x81, 0x87, 0x85,
0x43, 0x26, 0x14, 0x12, 0xb2, 0xcc, 0x2b, 0x22, 0x91, 0x0c, 0x92, 0x71, 0x6b, 0xde, 0x2e, 0xd9, 0xde, 0xa9, 0xa7, 0x88, 0x5f, 0xb0, 0x0e, 0x19, 0x9f, 0x4b, 0x88, 0x63, 0x54, 0x44, 0xa2, 0x3a,
0x64, 0x8f, 0xf8, 0x1d, 0xe3, 0xb4, 0x49, 0x0d, 0x12, 0xa1, 0xb3, 0x55, 0x78, 0x1c, 0xc3, 0xfe, 0xa8, 0x8e, 0x5b, 0xf3, 0x76, 0xc1, 0x26, 0x7b, 0xc4, 0xaf, 0x18, 0xa7, 0x75, 0x64, 0x34, 0x91,
0xc1, 0xfc, 0xca, 0x8d, 0xb3, 0x18, 0x9c, 0x47, 0xab, 0xab, 0xfc, 0x24, 0x1e, 0xd8, 0x3f, 0x98, 0x76, 0xb6, 0x14, 0x6b, 0x41, 0xec, 0x1f, 0x93, 0x83, 0x7e, 0xcf, 0xce, 0x4f, 0x74, 0xb7, 0x51,
0x9f, 0xfc, 0x91, 0x5d, 0x1a, 0xc0, 0xb5, 0xcc, 0xd4, 0x1a, 0xdf, 0x95, 0xff, 0x90, 0xa0, 0x95, 0x28, 0x7d, 0x46, 0x65, 0xef, 0x67, 0xe8, 0x89, 0xa3, 0xf2, 0xbc, 0x51, 0xf8, 0x9a, 0xd1, 0xc9,
0x0d, 0x32, 0x45, 0x2b, 0xea, 0x71, 0xe7, 0xbc, 0xd4, 0xb3, 0x6f, 0x3b, 0x29, 0xe5, 0x33, 0x5a, 0x36, 0xe3, 0xac, 0xf6, 0x0e, 0xb5, 0x4d, 0xca, 0x56, 0x3d, 0x7c, 0x5f, 0xff, 0x98, 0x1c, 0xf4,
0xfe, 0xc4, 0xc4, 0x7f, 0x6b, 0xe0, 0x35, 0x89, 0x46, 0x3c, 0xed, 0xe2, 0xcf, 0xde, 0xc4, 0x6b, 0x5b, 0xf6, 0xcf, 0x80, 0xce, 0x64, 0xac, 0x32, 0xbd, 0x51, 0xf8, 0x26, 0x21, 0x51, 0xd6, 0xcb,
0xe2, 0x57, 0xac, 0x19, 0xff, 0x4a, 0x86, 0x5e, 0x34, 0xe3, 0x07, 0x1a, 0xe5, 0x3c, 0x43, 0xcf, 0x48, 0x5b, 0xd1, 0x08, 0x9d, 0x3f, 0x45, 0x3c, 0xfb, 0x4c, 0x27, 0x45, 0xf8, 0xa0, 0x2d, 0xbf,
0x6f, 0x59, 0x9f, 0x36, 0xab, 0x15, 0x6e, 0x25, 0xa9, 0x02, 0x3c, 0x04, 0xe7, 0x49, 0xb4, 0x62, 0x63, 0xe2, 0xbb, 0x1a, 0x60, 0x42, 0xa2, 0x19, 0x2e, 0xfc, 0xfb, 0xa5, 0x37, 0xc1, 0x84, 0xf8,
0xd3, 0xdb, 0x8b, 0x45, 0xc5, 0xf9, 0x88, 0x9d, 0x65, 0xde, 0x15, 0x72, 0x99, 0x83, 0x87, 0x65, 0x7f, 0xd6, 0x0c, 0x3f, 0x35, 0xd6, 0x28, 0x5a, 0x61, 0x41, 0xa3, 0x98, 0x67, 0x1a, 0xf9, 0x25,
0x50, 0x9e, 0x04, 0x8b, 0xe9, 0x69, 0x89, 0xa7, 0x15, 0xe5, 0x43, 0xd6, 0x8d, 0x97, 0xae, 0x9d, 0xeb, 0xd3, 0x7a, 0xb5, 0xd2, 0x5b, 0x49, 0x2a, 0x07, 0x04, 0xef, 0x90, 0x04, 0x0b, 0x4e, 0x6f,
0x96, 0x05, 0x84, 0x5c, 0xb4, 0x63, 0xd6, 0x2e, 0xe1, 0x8b, 0xd3, 0x6f, 0x10, 0xf2, 0xb4, 0x1e, 0x1f, 0x2c, 0x4a, 0xce, 0x47, 0xec, 0x77, 0x8c, 0x2e, 0x97, 0xcb, 0x14, 0x10, 0x96, 0x5e, 0x21,
0x1f, 0xf7, 0xe1, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x04, 0x0f, 0xa4, 0xff, 0xec, 0x01, 0x00, 0x00, 0x89, 0x76, 0x50, 0x7f, 0x15, 0x78, 0x5a, 0x52, 0x3e, 0x64, 0xdd, 0x70, 0x69, 0xe6, 0x12, 0x99,
0x83, 0x4f, 0x45, 0x27, 0x68, 0xed, 0x02, 0x3e, 0xba, 0xe4, 0x05, 0x7c, 0x1a, 0xd5, 0xc3, 0xdb,
0xb8, 0xf9, 0x08, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x6f, 0x6c, 0xff, 0x2b, 0x02, 0x00, 0x00,
} }

View File

@@ -21,17 +21,22 @@ message Config {
// systemd sockets must be named with "FileDescriptorName=submission". // systemd sockets must be named with "FileDescriptorName=submission".
repeated string submission_address = 4; repeated string submission_address = 4;
// Addresses to listen on for submission-over-TLS (usually port 465).
// Default: "systemd", which means systemd passes sockets to us.
// systemd sockets must be named with "FileDescriptorName=submission_tls".
repeated string submission_over_tls_address = 5;
// Address for the monitoring http server. // Address for the monitoring http server.
// Do NOT expose this to the public internet. // Do NOT expose this to the public internet.
// Default: no monitoring http server. // Default: no monitoring http server.
string monitoring_address = 5; string monitoring_address = 6;
// Mail delivery agent (MDA, also known as LDA) to use. // Mail delivery agent (MDA, also known as LDA) to use.
// This should point to the binary to use to deliver email to local users. // This should point to the binary to use to deliver email to local users.
// The content of the email will be passed via stdin. // The content of the email will be passed via stdin.
// If it exits unsuccessfully, we assume the mail was not delivered. // If it exits unsuccessfully, we assume the mail was not delivered.
// Default: "maildrop". // Default: "maildrop".
string mail_delivery_agent_bin = 6; string mail_delivery_agent_bin = 7;
// 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.
@@ -45,11 +50,11 @@ message Config {
// //
// Default: "-f", "%from%", "-d", "%to_user%" (adequate for procmail // Default: "-f", "%from%", "-d", "%to_user%" (adequate for procmail
// and maildrop). // and maildrop).
repeated string mail_delivery_agent_args = 7; repeated string mail_delivery_agent_args = 8;
// Directory where we store our persistent data. // Directory where we store our persistent data.
// Default: "/var/lib/chasquid" // Default: "/var/lib/chasquid"
string data_dir = 8; string data_dir = 9;
// Suffix separator, to perform suffix removal of local users. // Suffix separator, to perform suffix removal of local users.
// For example, if you set this to "-+", email to local user // For example, if you set this to "-+", email to local user
@@ -57,17 +62,17 @@ message Config {
// Including "+" is strongly encouraged, as it is assumed for email // Including "+" is strongly encouraged, as it is assumed for email
// forwarding. // forwarding.
// Default: "+". // Default: "+".
string suffix_separators = 9; string suffix_separators = 10;
// Characters to drop from the user part on local emails. // Characters to drop from the user part on local emails.
// For example, if you set this to "._", email to local user // For example, if you set this to "._", email to local user
// "u.se_r" will be delivered to "user". // "u.se_r" will be delivered to "user".
// Default: ".". // Default: ".".
string drop_characters = 10; string drop_characters = 11;
// Path where to write the mail log to. // Path where to write the mail log to.
// If "<syslog>", log using the syslog (at MAIL|INFO priority). // If "<syslog>", log using the syslog (at MAIL|INFO priority).
// Default: <syslog> // Default: <syslog>
string mail_log_path = 11; string mail_log_path = 12;
} }

View File

@@ -55,12 +55,31 @@ var (
// Mode for a socket (listening or connection). // Mode for a socket (listening or connection).
// We keep them distinct, as policies can differ between them. // We keep them distinct, as policies can differ between them.
type SocketMode string type SocketMode struct {
// Is this mode submission?
IsSubmission bool
// Is this mode TLS-wrapped? That means that we don't use STARTTLS, the
// connection is directly established over TLS (like HTTPS).
TLS bool
}
func (mode SocketMode) String() string {
s := "SMTP"
if mode.IsSubmission {
s = "submission"
}
if mode.TLS {
s += "+TLS"
}
return s
}
// Valid socket modes. // Valid socket modes.
const ( var (
ModeSMTP SocketMode = "SMTP" ModeSMTP = SocketMode{IsSubmission: false, TLS: false}
ModeSubmission SocketMode = "submission" ModeSubmission = SocketMode{IsSubmission: true, TLS: false}
ModeSubmissionTLS = SocketMode{IsSubmission: true, TLS: true}
) )
// Incoming SMTP connection. // Incoming SMTP connection.
@@ -137,6 +156,7 @@ func (c *Conn) Handle() {
c.tr = trace.New("SMTP.Conn", c.conn.RemoteAddr().String()) c.tr = trace.New("SMTP.Conn", c.conn.RemoteAddr().String())
defer c.tr.Finish() defer c.tr.Finish()
c.tr.Debugf("Connected, mode: %s", c.mode)
c.tc.PrintfLine("220 %s ESMTP chasquid", c.hostname) c.tc.PrintfLine("220 %s ESMTP chasquid", c.hostname)
@@ -314,7 +334,7 @@ func (c *Conn) MAIL(params string) (code int, msg string) {
if !strings.HasPrefix(strings.ToLower(params), "from:") { if !strings.HasPrefix(strings.ToLower(params), "from:") {
return 500, "unknown command" return 500, "unknown command"
} }
if c.mode == ModeSubmission && !c.completedAuth { if c.mode.IsSubmission && !c.completedAuth {
return 550, "mail to submission port must be authenticated" return 550, "mail to submission port must be authenticated"
} }

View File

@@ -199,6 +199,11 @@ func (s *Server) ListenAndServe() {
} }
func (s *Server) serve(l net.Listener, mode SocketMode) { func (s *Server) serve(l net.Listener, mode SocketMode) {
// If this mode is expected to be TLS-wrapped, make it so.
if mode.TLS {
l = tls.NewListener(l, s.tlsConfig)
}
for { for {
conn, err := l.Accept() conn, err := l.Accept()
if err != nil { if err != nil {
@@ -213,6 +218,7 @@ func (s *Server) serve(l net.Listener, mode SocketMode) {
tc: textproto.NewConn(conn), tc: textproto.NewConn(conn),
mode: mode, mode: mode,
tlsConfig: s.tlsConfig, tlsConfig: s.tlsConfig,
onTLS: mode.TLS,
userDBs: s.userDBs, userDBs: s.userDBs,
aliasesR: s.aliasesR, aliasesR: s.aliasesR,
localDomains: s.localDomains, localDomains: s.localDomains,

View File

@@ -36,6 +36,7 @@ var (
// TODO: Don't hard-code the default. // TODO: Don't hard-code the default.
smtpAddr = "127.0.0.1:13444" smtpAddr = "127.0.0.1:13444"
submissionAddr = "127.0.0.1:13999" submissionAddr = "127.0.0.1:13999"
submissionTLSAddr = "127.0.0.1:13777"
// TLS configuration to use in the clients. // TLS configuration to use in the clients.
// Will contain the generated server certificate as root CA. // Will contain the generated server certificate as root CA.
@@ -46,14 +47,28 @@ var (
// === Tests === // === Tests ===
// //
func mustDial(tb testing.TB, mode SocketMode, useTLS bool) *smtp.Client { func mustDial(tb testing.TB, mode SocketMode, startTLS bool) *smtp.Client {
addr := "" addr := ""
if mode == ModeSMTP { switch mode {
case ModeSMTP:
addr = smtpAddr addr = smtpAddr
} else { case ModeSubmission:
addr = submissionAddr addr = submissionAddr
case ModeSubmissionTLS:
addr = submissionTLSAddr
} }
c, err := smtp.Dial(addr)
var err error
var conn net.Conn
if mode.TLS {
conn, err = tls.Dial("tcp", addr, tlsConfig)
} else {
conn, err = net.Dial("tcp", addr)
}
if err != nil {
tb.Fatalf("(net||tls).Dial: %v", err)
}
c, err := smtp.NewClient(conn, "127.0.0.1")
if err != nil { if err != nil {
tb.Fatalf("smtp.Dial: %v", err) tb.Fatalf("smtp.Dial: %v", err)
} }
@@ -62,7 +77,7 @@ func mustDial(tb testing.TB, mode SocketMode, useTLS bool) *smtp.Client {
tb.Fatalf("c.Hello: %v", err) tb.Fatalf("c.Hello: %v", err)
} }
if useTLS { if startTLS {
if ok, _ := c.Extension("STARTTLS"); !ok { if ok, _ := c.Extension("STARTTLS"); !ok {
tb.Fatalf("STARTTLS not advertised in EHLO") tb.Fatalf("STARTTLS not advertised in EHLO")
} }
@@ -153,6 +168,14 @@ func TestSubmissionWithoutAuth(t *testing.T) {
} }
} }
func TestAuthOnTLS(t *testing.T) {
c := mustDial(t, ModeSubmissionTLS, false)
defer c.Close()
auth := smtp.PlainAuth("", "testuser@localhost", "testpasswd", "127.0.0.1")
sendEmailWithAuth(t, c, auth)
}
func TestAuthOnSMTP(t *testing.T) { func TestAuthOnSMTP(t *testing.T) {
c := mustDial(t, ModeSMTP, true) c := mustDial(t, ModeSMTP, true)
defer c.Close() defer c.Close()
@@ -285,6 +308,16 @@ func TestRepeatedStartTLS(t *testing.T) {
} }
} }
// Test that STARTTLS fails on a TLS connection.
func TestStartTLSOnTLS(t *testing.T) {
c := mustDial(t, ModeSubmissionTLS, false)
defer c.Close()
if err := c.StartTLS(tlsConfig); err == nil {
t.Errorf("STARTTLS did not fail as expected")
}
}
// //
// === Benchmarks === // === Benchmarks ===
// //
@@ -440,6 +473,7 @@ func realMain(m *testing.M) int {
s.AddCerts(tmpDir+"/cert.pem", tmpDir+"/key.pem") s.AddCerts(tmpDir+"/cert.pem", tmpDir+"/key.pem")
s.AddAddr(smtpAddr, ModeSMTP) s.AddAddr(smtpAddr, ModeSMTP)
s.AddAddr(submissionAddr, ModeSubmission) s.AddAddr(submissionAddr, ModeSubmission)
s.AddAddr(submissionTLSAddr, ModeSubmissionTLS)
localC := &courier.Procmail{} localC := &courier.Procmail{}
remoteC := &courier.SMTP{} remoteC := &courier.SMTP{}

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -15,6 +15,10 @@ password secretpassword
account smtpport : default account smtpport : default
port 1025 port 1025
account subm_tls : default
port 1465
tls_starttls off
account baduser : default account baduser : default
user unknownuser@testserver user unknownuser@testserver
password secretpassword password secretpassword

View File

@@ -31,6 +31,11 @@ if ! run_msmtp -a smtpport someone@testserver < content 2> /dev/null; then
fail "failed auth on the SMTP port" fail "failed auth on the SMTP port"
fi fi
# Check deliver over the submission-over-TLS port.
if ! run_msmtp -a subm_tls someone@testserver < content 2> /dev/null; then
fail "failed submission over TLS"
fi
if run_msmtp nobody@testserver < content 2> /dev/null; then if run_msmtp nobody@testserver < content 2> /dev/null; then
fail "successfuly sent an email to a non-existent user" fail "successfuly sent an email to a non-existent user"
fi fi

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -2,6 +2,7 @@ hostname: "testserver"
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":2025" smtp_address: ":2025"
submission_address: ":2587" submission_address: ":2587"
submission_over_tls_address: ":2465"
monitoring_address: ":2099" monitoring_address: ":2099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":2025" smtp_address: ":2025"
submission_address: ":2587" submission_address: ":2587"
submission_over_tls_address: ":2465"
monitoring_address: ":2099" monitoring_address: ":2099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"

View File

@@ -1,5 +1,6 @@
smtp_address: ":1025" smtp_address: ":1025"
submission_address: ":1587" submission_address: ":1587"
submission_over_tls_address: ":1465"
monitoring_address: ":1099" monitoring_address: ":1099"
mail_delivery_agent_bin: "test-mda" mail_delivery_agent_bin: "test-mda"