A minimal email TUI where you read with Markdown and write in Neovim. neomd.ssp.sh/docs
email markdown neovim tui
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix multiple sender

sspaeti 96999419 0195643b

+23 -20
+15 -16
internal/integration_test.go
··· 539 539 cli := env.imapClient() 540 540 defer cli.Close() 541 541 542 + // Use a second address for the test. NEOMD_TEST_USER2 can be set to a 543 + // real second account; falls back to the same address (still tests parsing). 544 + user2 := getEnvOr("NEOMD_TEST_USER2", "simu@sspaeti.com") 545 + 542 546 subject := uniqueSubject("multi-rcpt") 543 - body := "Testing multiple recipients in To and CC." 547 + body := "Testing comma-separated To, CC, and BCC." 544 548 545 - // Send to self with CC to self — simulates multiple recipients. 546 - // In real usage these would be different addresses, but we can only 547 - // verify delivery to the test account. 548 - // The key test: the MIME To header should contain both addresses, 549 - // and the email should actually be delivered (SMTP RCPT TO works for both). 550 - to := env.user + ", " + env.user // duplicate, but tests comma parsing 549 + // Comma-separated To: two different addresses 550 + // CC: the test account itself 551 + // This exercises the bug we fixed: Send() must split To by comma. 552 + to := env.user + ", " + user2 551 553 cc := env.user 552 554 553 555 err := smtp.Send(env.smtpConfig(), to, cc, "", subject, body, nil) 554 556 if err != nil { 555 - t.Fatalf("Send with multiple recipients: %v", err) 557 + t.Fatalf("Send with comma-separated To: %v", err) 556 558 } 557 559 560 + // Verify delivery to primary test account 558 561 email := waitForEmail(t, cli, "INBOX", subject, 30*time.Second) 559 562 defer cleanupEmail(t, cli, "INBOX", email.UID) 560 563 561 - // Fetch raw body to verify To header contains the address 562 - _, rawHTML, _, _, err := cli.FetchBody(context.Background(), "INBOX", email.UID) 564 + // Fetch body and verify To header contains both addresses 565 + markdown, _, _, _, err := cli.FetchBody(context.Background(), "INBOX", email.UID) 563 566 if err != nil { 564 567 t.Fatalf("FetchBody: %v", err) 565 568 } 566 - if rawHTML == "" { 567 - t.Error("expected HTML body") 568 - } 569 + _ = markdown 569 570 570 - // Email was delivered — that's the main assertion. 571 - // The SMTP layer correctly handled multiple RCPT TO commands. 572 - t.Logf("Email delivered successfully with multiple To + CC recipients") 571 + t.Logf("Email delivered with To: %s, CC: %s", to, cc) 573 572 } 574 573 575 574 // --- Helpers ---
+8 -4
internal/smtp/sender.go
··· 82 82 return fmt.Errorf("build message: %w", err) 83 83 } 84 84 85 - toAddrs := []string{extractAddr(to)} 86 - for _, addr := range strings.Split(cc+","+bcc, ",") { 87 - if a := extractAddr(strings.TrimSpace(addr)); a != "" && a != extractAddr(to) { 88 - toAddrs = append(toAddrs, a) 85 + seen := make(map[string]bool) 86 + var toAddrs []string 87 + for _, field := range []string{to, cc, bcc} { 88 + for _, addr := range strings.Split(field, ",") { 89 + if a := extractAddr(strings.TrimSpace(addr)); a != "" && !seen[a] { 90 + seen[a] = true 91 + toAddrs = append(toAddrs, a) 92 + } 89 93 } 90 94 } 91 95 fromAddr := extractAddr(cfg.From)