package main import ( "encoding/json" "fmt" "io" "log" "os" "strings" "time" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" "github.com/emersion/go-message/mail" ) func main() { host := os.Getenv("IMAP_HOST") username := os.Getenv("IMAP_USERNAME") password := os.Getenv("IMAP_PASSWORD") if host == "" || username == "" || password == "" { log.Fatal("Environment variables IMAP_HOST, IMAP_USERNAME, and IMAP_PASSWORD must be set") } log.Println("Connecting to server...") // Connect to the IMAP server c, err := client.DialTLS(host, nil) if err != nil { log.Fatalf("Failed to connect to IMAP server: %v", err) } log.Println("Connected") defer c.Logout() // Login if err := c.Login(username, password); err != nil { log.Fatalf("Failed to log in: %v", err) } log.Println("Logged in") // Select INBOX _, err = c.Select("INBOX", false) if err != nil { log.Fatalf("Failed to select INBOX: %v", err) } // Set up criteria to search for new unseen emails criteria := imap.NewSearchCriteria() criteria.WithoutFlags = []string{imap.SeenFlag} ids, err := c.Search(criteria) if err != nil { log.Fatalf("Failed to search emails: %v", err) } if len(ids) == 0 { log.Println("No new emails") return } seqset := new(imap.SeqSet) seqset.AddNum(ids...) section := &imap.BodySectionName{} items := []imap.FetchItem{section.FetchItem(), imap.FetchEnvelope} messages := make(chan *imap.Message) go func() { if err := c.Fetch(seqset, items, messages); err != nil { log.Fatalf("Failed to fetch emails: %v", err) } }() counter := 0 for msg := range messages { if msg == nil { continue } body := msg.GetBody(section) if body == nil { log.Println("No body fetched for this message") continue } r, err := mail.CreateReader(body) if err != nil { log.Fatalf("Failed to create mail reader: %v", err) } var emailBody strings.Builder for { p, err := r.NextPart() if err == io.EOF { break } if err != nil { log.Fatalf("Failed to read part: %v", err) } switch h := p.Header.(type) { case *mail.InlineHeader: _, params, _ := h.ContentType() if params["charset"] != "" { _, err = io.Copy(&emailBody, p.Body) if err != nil { log.Fatalf("Failed to read body: %v", err) } } } } emailData := map[string]interface{}{ "subject": msg.Envelope.Subject, "from": msg.Envelope.From, "to": msg.Envelope.To, "date": msg.Envelope.Date, "body": emailBody.String(), } emailJSON, err := json.MarshalIndent(emailData, "", " ") if err != nil { log.Fatalf("Failed to marshal JSON: %v", err) } timestamp := time.Now().Format("20060102-150405") fileName := fmt.Sprintf("email-%s-%d.json", timestamp, counter) counter++ err = os.WriteFile(fileName, emailJSON, 0644) if err != nil { log.Fatalf("Failed to write file %s: %v", fileName, err) } log.Printf("Saved %s", fileName) } }