diff --git a/Dockerfile b/Dockerfile index f0b2d58..682bac5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,7 @@ COPY . . RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /bin/aws-smtp-relay FROM scratch -COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=build /bin/aws-smtp-relay /bin/ -USER 65534 +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +USER 1001 ENTRYPOINT ["aws-smtp-relay"] diff --git a/main.go b/main.go index 10797a6..fce1b41 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "os" "regexp" "strings" + "strconv" + "log" "github.com/blueimp/aws-smtp-relay/internal/auth" "github.com/blueimp/aws-smtp-relay/internal/relay" @@ -16,19 +18,19 @@ import ( ) var ( - addr = flag.String("a", ":1025", "TCP listen address") - name = flag.String("n", "AWS SMTP Relay", "SMTP service name") - host = flag.String("h", "", "Server hostname") - certFile = flag.String("c", "", "TLS cert file") - keyFile = flag.String("k", "", "TLS key file") - startTLS = flag.Bool("s", false, "Require TLS via STARTTLS extension") - onlyTLS = flag.Bool("t", false, "Listen for incoming TLS connections only") - relayAPI = flag.String("r", "ses", "Relay API to use (ses|pinpoint)") - setName = flag.String("e", "", "Amazon SES Configuration Set Name") - ips = flag.String("i", "", "Allowed client IPs (comma-separated)") - user = flag.String("u", "", "Authentication username") - allowFrom = flag.String("l", "", "Allowed sender emails regular expression") - denyTo = flag.String("d", "", "Denied recipient emails regular expression") + addr = flag.String("a", LookupEnvOrString("LISTEN_ADDRESS", ":1025"), "TCP listen address") + name = flag.String("n", LookupEnvOrString("SMTP_SERVICE_NAME", "AWS SMTP Relay"), "SMTP service name") + host = flag.String("h", LookupEnvOrString("HOSTNAME", ""), "Server hostname") + certFile = flag.String("c", LookupEnvOrString("CERT_FILE", ""), "TLS cert file") + keyFile = flag.String("k", LookupEnvOrString("KEY_FILE", ""), "TLS key file") + startTLS = flag.Bool("s", LookupEnvOrBool("REQUIRE_STARTTLS", false), "Require TLS via STARTTLS extension (TCP PASSTHROUGH)") + onlyTLS = flag.Bool("t", LookupEnvOrBool("REQUIRE_TLS", false), "Listen for incoming TLS connections only (false by default)") + relayAPI = flag.String("r", LookupEnvOrString("RELAY_API", "ses"), "Relay API to use (ses|pinpoint)") + setName = flag.String("e", LookupEnvOrString("SES_CONFIGURATION_SET_NAME", ""), "Amazon SES Configuration Set Name") + ips = flag.String("i", LookupEnvOrString("ALLOWED_IPS", ""), "Allowed client IPs (comma-separated)") + user = flag.String("u", LookupEnvOrString("AUTH_USERNAME", ""), "Authentication username") + allowFrom = flag.String("l", LookupEnvOrString("ALLOWED_SENDERS_REGEX", ""), "Allowed sender emails regular expression") + denyTo = flag.String("d", LookupEnvOrString("DENIED_RECIPIENTS_REGEX", ""), "Denied recipient emails regular expression") ) var ipMap map[string]bool @@ -41,6 +43,18 @@ func server() (srv *smtpd.Server, err error) { if *user != "" && len(bcryptHash) > 0 && len(password) == 0 { authMechs["CRAM-MD5"] = false } + + // force-enable the login mechanism: only needed if there is no external routing and TLS is not configured + if LookupEnvOrString("ENABLE_LOGIN", "") == "true" { + authMechs["LOGIN"] = true + } + + version := LookupEnvOrString("GIT_REV", "") + if version == "" { + log.Printf("Listening on %v\r\n", *addr) + }else{ + log.Printf("(Revision: %s) Listening on %v\r\n", version, *addr) + } srv = &smtpd.Server{ Addr: *addr, Handler: relayClient.Send, @@ -98,6 +112,38 @@ func configure() error { return nil } +// returns the value of an environment variable or the default value +func LookupEnvOrString(key string, defaultVal string) string { + if val, ok := os.LookupEnv(key); ok { + return val + } + return defaultVal +} + +func LookupEnvOrInt(key string, defaultVal int) int { + if val, ok := os.LookupEnv(key); ok { + v, err := strconv.Atoi(val) + if err != nil { + log.Fatalf("LookupEnvOrInt[%s]: %v", key, err) + } + return v + } + return defaultVal +} + +func LookupEnvOrBool(key string, defaultVal bool) bool { + if val, ok := os.LookupEnv(key); ok { + val = strings.ToLower(val) + if val == "true" { + return true + }else if val == "false" { + return false + } + log.Fatalf("LookupEnvOrBool[%s]: invalid value %v", key, val) + } + return defaultVal +} + func main() { flag.Parse() var srv *smtpd.Server