package main import ( "bytes" "fmt" "os" "path/filepath" "strings" "time" ) func writeMaildir(folderPath string, msg []byte) error { for _, dir := range []string{"tmp", "new"} { if err := os.MkdirAll(filepath.Join(folderPath, dir), 0755); err != nil { return err } } now := time.Now() filename := fmt.Sprintf("%d.M%06dP%d.%s", now.Unix(), now.Nanosecond()/1000, os.Getpid(), maildirHostname(), ) tmpPath := filepath.Join(folderPath, "tmp", filename) newPath := filepath.Join(folderPath, "new", filename) if err := os.WriteFile(tmpPath, msg, 0600); err != nil { return err } return os.Rename(tmpPath, newPath) } func maildirHostname() string { h, err := os.Hostname() if err != nil { return "localhost" } return h } // maildirHasMessageID reports whether any file in folderPath/new or folderPath/cur // contains msgID in its headers. func maildirHasMessageID(folderPath, msgID string) bool { needle := []byte(msgID) for _, sub := range []string{"new", "cur"} { dir := filepath.Join(folderPath, sub) entries, err := os.ReadDir(dir) if err != nil { continue } for _, e := range entries { if e.IsDir() { continue } if fileContainsInHeaders(filepath.Join(dir, e.Name()), needle) { return true } } } return false } // headerBytes returns the header section of an RFC 5322 message (everything // before the first blank line). Returns the full slice if no blank line found. func headerBytes(b []byte) []byte { if i := bytes.Index(b, []byte("\r\n\r\n")); i >= 0 { return b[:i] } if i := bytes.Index(b, []byte("\n\n")); i >= 0 { return b[:i] } return b } // fileContainsInHeaders reads only the header section of an RFC 5322 message // (up to the first blank line) and reports whether needle appears in it. func fileContainsInHeaders(path string, needle []byte) bool { f, err := os.Open(path) if err != nil { return false } defer f.Close() buf := make([]byte, 8192) n, _ := f.Read(buf) return bytes.Contains(headerBytes(buf[:n]), needle) } // extractMessageID returns the value of the Message-ID header, or "" if absent. func extractMessageID(msg []byte) string { for _, line := range bytes.Split(headerBytes(msg), []byte("\n")) { line = bytes.TrimRight(line, "\r") key, val, ok := bytes.Cut(line, []byte(":")) if !ok { continue } if strings.EqualFold(strings.TrimSpace(string(key)), "message-id") { return strings.TrimSpace(string(val)) } } return "" }