package main import ( "fmt" "io" "log" "net/http" "regexp" "strings" ) const port = "8280" var emailRegex = regexp.MustCompile(`(?i)([^<]+)`) func main() { http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprint(w, "OK") }) http.HandleFunc("/autodiscover/autodiscover.xml", handleAutodiscover) // Outlook sendet manchmal mit Großbuchstaben http.HandleFunc("/Autodiscover/Autodiscover.xml", handleAutodiscover) http.HandleFunc("/AutoDiscover/AutoDiscover.xml", handleAutodiscover) log.Printf("[autodiscover] Listening on port %s", port) if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatal(err) } } func handleAutodiscover(w http.ResponseWriter, r *http.Request) { var email string if r.Method == http.MethodPost { body, err := io.ReadAll(r.Body) if err == nil { if match := emailRegex.FindStringSubmatch(string(body)); len(match) > 1 { email = strings.TrimSpace(match[1]) } } r.Body.Close() } var domain string if email != "" { parts := strings.SplitN(email, "@", 2) if len(parts) == 2 { domain = parts[1] } } if domain == "" { domain = extractDomainFromHost(r.Host) } log.Printf("[autodiscover] %s from %s - email=%q domain=%s", r.Method, r.RemoteAddr, email, domain) w.Header().Set("Content-Type", "application/xml") w.WriteHeader(http.StatusOK) fmt.Fprint(w, buildResponse(domain, email)) } func extractDomainFromHost(host string) string { // Strip port if idx := strings.Index(host, ":"); idx >= 0 { host = host[:idx] } parts := strings.Split(host, ".") if len(parts) >= 3 && strings.EqualFold(parts[0], "autodiscover") { return strings.Join(parts[1:], ".") } if len(parts) >= 2 { return strings.Join(parts[len(parts)-2:], ".") } return host } func buildResponse(domain, loginName string) string { return fmt.Sprintf(` email settings IMAP imap.%s 993 off %s off on on SMTP smtp.%s 465 off %s off on on `, domain, loginName, domain, loginName) }