package main import ( "errors" "flag" "fmt" "io" "mime" "mime/multipart" "net/mail" "os" "strings" ) func main() { flag.Usage = func() { fmt.Fprintf(flag.CommandLine.Output(), "Usage: mimeslicer [options]\n\n") fmt.Fprintf(flag.CommandLine.Output(), "Commands:\n") os.Exit(0) } if len(os.Args) < 2 { fmt.Println("Error: Command missing.") flag.Usage() } inspectCmd := flag.NewFlagSet("inspect", flag.ExitOnError) inspectCmdInputFile := inspectCmd.String("i", "", "input file") switch os.Args[1] { case "inspect": inspectCmd.Parse(os.Args[2:]) if err := inspect(*inspectCmdInputFile); err != nil { fmt.Printf("Error: %s", err.Error()) os.Exit(1) } case "-h", "--help", "help": flag.Usage() default: fmt.Printf("Error: unknown command %q\n\n", os.Args[1]) flag.Usage() } } func inspect(file string) error { fd, err := os.Open(file) if err != nil { return err } defer fd.Close() msg, err := mail.ReadMessage(fd) if err != nil { return err } for k, v := range msg.Header { for _, val := range v { fmt.Printf("%s: %s\n", k, val) } } contentType := msg.Header.Get("Content-Type") mediaType, params, err := mime.ParseMediaType(contentType) if err != nil { return errors.Join(err, errors.New("failed to parse mediate type from contentType")) } if !strings.HasPrefix(mediaType, "multipart/") { return errors.New("expected multipler/ TOOD") } boundary, ok := params["boundary"] if !ok { return errors.New("Error: no boundary in Content-Type header for multipart media type") } mr := multipart.NewReader(msg.Body, boundary) partIndex := 0 fmt.Printf("\nMIME body parts\n\n") for { part, err := mr.NextPart() if err == io.EOF { break } fmt.Printf("[%d]\n", partIndex) fmt.Printf("Headers:\n") for k, v := range part.Header { for _, val := range v { fmt.Printf(" %s: %s\n", k, val) } } partIndex++ } return nil }