Commit 0b8788ea authored by ale's avatar ale
Browse files

Use ai3/tools/smtpd-pipe instead of the builtin smtpd.go

The smtpd-pipe tool has been built explicitly to take over this
little binary.

Fixes issue #2.
parent 7ff3316d
Pipeline #22327 passed with stage
in 37 seconds
# 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: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
......@@ -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"
......
#!/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
// 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)
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment