diff --git a/Dockerfile b/Dockerfile index d3287a0424a6514c89eba4b880557c519f77d614..97b69907a0387aeb73f013cef1f110026aa79b1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,11 @@ -# Stage 1: build the tiny smtp server -FROM golang:1.16 AS build -WORKDIR /go/src -COPY go.mod . -COPY go.sum . -COPY smtpd.go . -RUN go build -o smtpd smtpd.go +# Stage 1: import the smtpd-pipe server +FROM registry.git.autistici.org/ai3/tools/smtpd-pipe:master AS smtpd # Stage 2: build the final container -FROM registry.git.autistici.org/ai3/docker/apache2-base:master -COPY start.sh /start.sh +FROM registry.git.autistici.org/ai3/docker/apache2-base:s6 COPY build.sh /tmp/build.sh COPY ai-lurker-ui.patch /tmp/ai-lurker-ui.patch COPY conf/ /etc/ -COPY --from=build /go/src/smtpd /usr/bin/smtpd +COPY --from=smtpd /smtpd /usr/bin/smtpd RUN /tmp/build.sh && rm /tmp/build.sh /tmp/ai-lurker-ui.patch COPY logo.png /var/lib/lurker-www-orig/logo.png -ENTRYPOINT ["/usr/local/bin/chaperone"] - diff --git a/build.sh b/build.sh index 7269705581611d3941910ad68cbd68360b1b87d4..126ba742a3de180d58f9efd1b295ab6dee76c84c 100755 --- a/build.sh +++ b/build.sh @@ -22,7 +22,7 @@ die() { set -x -# Install packages (aiosmtpd comes from backports in stretch). +# Install packages. apt-get -q update install_packages ${BUILD_PACKAGES} ${PACKAGES} \ || die "could not install packages" diff --git a/conf/chaperone.d/prune.conf b/conf/chaperone.d/prune.conf deleted file mode 100644 index e50cd00b241b5b4b861311ce71156ae1447d4935..0000000000000000000000000000000000000000 --- a/conf/chaperone.d/prune.conf +++ /dev/null @@ -1,5 +0,0 @@ -lurker-prune.service: { - type: cron, - interval: "*/15 * * * *", - command: "/usr/bin/lurker-prune", -} diff --git a/conf/chaperone.d/smtpd.conf b/conf/chaperone.d/smtpd.conf deleted file mode 100644 index 9943f2d23c966134b29617525f1488ca072bb3a0..0000000000000000000000000000000000000000 --- a/conf/chaperone.d/smtpd.conf +++ /dev/null @@ -1,5 +0,0 @@ -smtpd.service: { - command: "/usr/bin/smtpd", - exit_kills: true, -} - diff --git a/conf/chaperone.d/start.conf b/conf/chaperone.d/start.conf deleted file mode 100644 index 22550abae56b25aa95f7d2a675a87769ad359cc9..0000000000000000000000000000000000000000 --- a/conf/chaperone.d/start.conf +++ /dev/null @@ -1,7 +0,0 @@ -lurker_setup.service: { - type: oneshot, - stdout: inherit, - service_groups: INIT, - process_timeout: 60, - command: "/start.sh", -} diff --git a/start.sh b/conf/cont-init.d/90lurker-setup similarity index 100% rename from start.sh rename to conf/cont-init.d/90lurker-setup diff --git a/conf/services.d/prune/run b/conf/services.d/prune/run new file mode 100755 index 0000000000000000000000000000000000000000..c3490ec7e25c3a6e68ffe8712ea7b81a767e5ae1 --- /dev/null +++ b/conf/services.d/prune/run @@ -0,0 +1,8 @@ +#!/bin/sh + +period=900 + +while true; do + sleep $period + /usr/bin/lurker-prune +done diff --git a/conf/services.d/smtpd/finish b/conf/services.d/smtpd/finish new file mode 100755 index 0000000000000000000000000000000000000000..b6531b3ca574205c9e78650dbd7c38718683e57c --- /dev/null +++ b/conf/services.d/smtpd/finish @@ -0,0 +1,3 @@ +#!/usr/bin/execlineb -S0 + +s6-svscanctl -t /var/run/s6/services diff --git a/conf/services.d/smtpd/run b/conf/services.d/smtpd/run new file mode 100755 index 0000000000000000000000000000000000000000..2934c3bb2a8cd5eb92d627831c3fa6a296ccd255 --- /dev/null +++ b/conf/services.d/smtpd/run @@ -0,0 +1,12 @@ +#!/bin/sh + +# Build the SMTP_RULES env var based on the LURKER_ADDR_RX regexp. +export SMTP_RULES="${LURKER_ADDR_RX}:/usr/bin/lurker-index -m -l \\1" + +# Temporarily suspend incoming email when lurker is rebuilding its index. +export SMTP_GUARD_FILE="${LURKER_DATA_DIR:-/var/lib/lurker/data}/.tmp" + +# Allow large messages (50MB). +export SMTP_MAX_MESSAGE_SIZE=52428800 + +exec /usr/bin/smtpd diff --git a/go.mod b/go.mod deleted file mode 100644 index dcd5b8502bac1a64da4483e902a5e9ebfa78c2cf..0000000000000000000000000000000000000000 --- a/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module git.autistici.org/ai3/docker/lurker - -go 1.14 - -require github.com/chrj/smtpd v0.3.0 diff --git a/go.sum b/go.sum deleted file mode 100644 index a6779b97bdb3585dc6fd9f5779e0c5c23ac1ce3f..0000000000000000000000000000000000000000 --- a/go.sum +++ /dev/null @@ -1,3 +0,0 @@ -github.com/chrj/smtpd v0.3.0 h1:cw1LSHDOz7N3XbkcZSF/bue9dh7ATKk5ZksfBztV6b0= -github.com/chrj/smtpd v0.3.0/go.mod h1:1hmG9KbrE10JG1SmvG79Krh4F6713oUrw2+gRp1oSYk= -github.com/eaigner/dkim v0.0.0-20150301120808-6fe4a7ee9cfb/go.mod h1:FSCIHbrqk7D01Mj8y/jW+NS1uoCerr+ad+IckTHTFf4= diff --git a/smtpd.go b/smtpd.go deleted file mode 100644 index 51709f258eec98517a2064cb9c047a80e682e7ed..0000000000000000000000000000000000000000 --- a/smtpd.go +++ /dev/null @@ -1,118 +0,0 @@ -// Simple SMTP server that runs lurker-index. -// -// Use the --addr-rx command-line option to extract the list name from -// the recipient address. The same regexp defines valid recipient -// addresses (messages whose recipient do not match are rejected). -// -package main - -import ( - "bytes" - "flag" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" - - "github.com/chrj/smtpd" -) - -var ( - port = flag.Int("port", getenvInt("SMTP_PORT"), "smtp port") - hostname = flag.String("ehlo-hostname", os.Getenv("SMTP_EHLO_HOSTNAME"), "EHLO hostname") - lurkerDataDir = flag.String("lurker-data-dir", getenvDefault("LURKER_DATA_DIR", "/var/lib/lurker/data"), "lurker data dir") - addrPattern = flag.String("addr-rx", getenvDefault("LURKER_ADDR_RX", `lurker\+([^@]+)@.*`), "recipient address regular expression") -) - -var addrRx *regexp.Regexp - -func getenvInt(key string) int { - n, _ := strconv.Atoi(os.Getenv(key)) - return n -} - -func getenvDefault(key, dflt string) string { - if s := os.Getenv(key); s != "" { - return s - } - return dflt -} - -func isMaintenanceModeOn() bool { - _, err := os.Stat(filepath.Join(*lurkerDataDir, ".tmp")) - return !os.IsNotExist(err) -} - -func lurkerIndexMsg(listName string, data []byte) error { - cmd := exec.Command("lurker-index", "-m", "-l", listName) - cmd.Stdin = bytes.NewReader(data) - out, err := cmd.CombinedOutput() - if err != nil { - outStr := strings.Replace(strings.TrimSpace(string(out)), "\n", "; ", -1) - log.Printf("lurker-index error: %v, %s", err, outStr) - return smtpd.Error{550, outStr} - } - return nil -} - -func parseRecipientAddr(addr string) (string, error) { - m := addrRx.FindStringSubmatch(addr) - if len(m) == 0 { - return "", smtpd.Error{550, "Unknown recipient"} - } - listName := m[1] - if listName == "" { - return "", smtpd.Error{550, "No list name found"} - } - return listName, nil -} - -func checkRecipient(peer smtpd.Peer, addr string) error { - _, err := parseRecipientAddr(addr) - return err -} - -func handleMessage(peer smtpd.Peer, env smtpd.Envelope) error { - if isMaintenanceModeOn() { - return smtpd.Error{421, "Maintenance mode, retry later"} - } - - log.Printf("received msg: %s -> %s", env.Sender, strings.Join(env.Recipients, ",")) - for _, rcpt := range env.Recipients { - listName, err := parseRecipientAddr(rcpt) - if err != nil { - return err - } - if err := lurkerIndexMsg(listName, env.Data); err != nil { - return err - } - } - return nil -} - -func main() { - log.SetFlags(0) - flag.Parse() - - // Auto-anchor the addr regexp. - var err error - addrRx, err = regexp.Compile(fmt.Sprintf("^%s$", *addrPattern)) - if err != nil { - log.Fatalf("error in --addr-rx: %v", err) - } - - server := &smtpd.Server{ - Hostname: *hostname, - RecipientChecker: checkRecipient, - Handler: handleMessage, - //ProtocolLogger: log.New(os.Stderr, "smtp: ", 0), - } - - if err := server.ListenAndServe(fmt.Sprintf(":%d", *port)); err != nil { - log.Fatal(err) - } -}