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

Implement couriers

This patch introduces the couriers, which the queue uses to deliver mail.

We have a local courier (using procmail), a remote courier (uses SMTP), and a
router courier that decides which of the two to use based on a list of local
domains.

There are still a few things pending, but they all have their basic
functionality working and tested.
This commit is contained in:
Alberto Bertogli
2015-11-06 02:03:21 +00:00
parent e5c2676f83
commit 77d547288f
10 changed files with 639 additions and 25 deletions

View File

@@ -17,6 +17,7 @@ import (
"time"
"blitiri.com.ar/go/chasquid/internal/config"
"blitiri.com.ar/go/chasquid/internal/courier"
"blitiri.com.ar/go/chasquid/internal/queue"
"blitiri.com.ar/go/chasquid/internal/systemd"
"blitiri.com.ar/go/chasquid/internal/trace"
@@ -55,21 +56,28 @@ func main() {
s.MaxDataSize = conf.MaxDataSizeMb * 1024 * 1024
// Load domains.
domains, err := filepath.Glob(*configDir + "/domains/*")
domainDirs, err := ioutil.ReadDir(*configDir + "/domains/")
if err != nil {
glog.Fatalf("Error in glob: %v", err)
}
if len(domains) == 0 {
if len(domainDirs) == 0 {
glog.Warningf("No domains found in config, using test certs")
s.AddCerts(*testCert, *testKey)
} else {
glog.Infof("Domain config paths:")
for _, d := range domains {
glog.Infof(" %s", d)
s.AddCerts(d+"/cert.pem", d+"/key.pem")
for _, info := range domainDirs {
glog.Infof(" %s", info.Name())
s.AddDomain(info.Name())
dir := filepath.Join(*configDir, "domains", info.Name())
s.AddCerts(dir+"/cert.pem", dir+"/key.pem")
}
}
// Always include localhost as local domain.
// This can prevent potential trouble if we were to accidentally treat it
// as a remote domain (for loops, alias resolutions, etc.).
s.AddDomain("localhost")
// Load addresses.
acount := 0
for _, addr := range conf.Address {
@@ -115,6 +123,9 @@ type Server struct {
// TLS config.
tlsConfig *tls.Config
// Local domains.
localDomains map[string]bool
// Time before we give up on a connection, even if it's sending data.
connTimeout time.Duration
@@ -129,7 +140,7 @@ func NewServer() *Server {
return &Server{
connTimeout: 20 * time.Minute,
commandTimeout: 1 * time.Minute,
queue: queue.New(),
localDomains: map[string]bool{},
}
}
@@ -146,6 +157,10 @@ func (s *Server) AddListeners(ls []net.Listener) {
s.listeners = append(s.listeners, ls...)
}
func (s *Server) AddDomain(d string) {
s.localDomains[d] = true
}
func (s *Server) getTLSConfig() (*tls.Config, error) {
var err error
conf := &tls.Config{}
@@ -172,6 +187,15 @@ func (s *Server) ListenAndServe() {
glog.Fatalf("Error loading TLS config: %v", err)
}
// Create the queue, giving it a routing courier for delivery.
// We need to do this early, before accepting connections.
courier := &courier.Router{
Local: &courier.Procmail{},
Remote: &courier.SMTP{},
LocalDomains: s.localDomains,
}
s.queue = queue.New(courier)
for _, addr := range s.addrs {
// Listen.
l, err := net.Listen("tcp", addr)
@@ -420,6 +444,10 @@ func (c *Conn) RCPT(params string) (code int, msg string) {
return 500, "unknown command"
}
// TODO: Write our own parser (we have different needs, mail.ParseAddress
// is useful for other things).
// Allow utf8, but prevent "control" characters.
e, err := mail.ParseAddress(sp[1])
if err != nil || e.Address == "" {
return 501, "malformed address"