rss email digests over ssh because you're a cool kid herald.dunkirk.sh
go rss rss-reader ssh charm

feat: add more fancy headers to email

dunkirk.sh 73a97f1a d390ee28

verified
+45 -1
+11 -1
email/send.go
··· 138 138 headers["MIME-Version"] = "1.0" 139 139 headers["Content-Type"] = fmt.Sprintf("multipart/alternative; boundary=%q", boundary) 140 140 141 - // Add RFC 8058 unsubscribe headers 141 + // RFC 2369 list headers 142 + headers["List-Id"] = fmt.Sprintf("<herald.%s>", m.cfg.Host) 143 + headers["List-Archive"] = fmt.Sprintf("<%s>", dashboardURL) 144 + headers["List-Post"] = "NO" 145 + 146 + // RFC 8058 unsubscribe headers 142 147 if unsubToken != "" { 143 148 unsubURL := m.unsubBaseURL + "/unsubscribe/" + unsubToken 144 149 headers["List-Unsubscribe"] = fmt.Sprintf("<%s>", unsubURL) 145 150 headers["List-Unsubscribe-Post"] = "List-Unsubscribe=One-Click" 146 151 } 152 + 153 + // Bulk mail and auto-generated headers for better deliverability 154 + headers["Precedence"] = "bulk" 155 + headers["Auto-Submitted"] = "auto-generated" 156 + headers["X-Mailer"] = "Herald" 147 157 148 158 var msg strings.Builder 149 159 for k, v := range headers {
+34
web/handlers.go
··· 514 514 return 515 515 } 516 516 517 + // RFC 8058: Check for one-click unsubscribe format 518 + oneClick := r.FormValue("List-Unsubscribe") 519 + if oneClick == "One-Click" { 520 + // One-click unsubscribe: deactivate config without rendering HTML 521 + cfg, err := s.store.GetConfigByToken(ctx, token) 522 + if err != nil { 523 + if errors.Is(err, sql.ErrNoRows) { 524 + http.Error(w, "Invalid token", http.StatusNotFound) 525 + return 526 + } 527 + s.logger.Error("get config by token", "err", err) 528 + http.Error(w, "Internal Server Error", http.StatusInternalServerError) 529 + return 530 + } 531 + 532 + if err := s.store.DeactivateConfig(ctx, cfg.ID); err != nil { 533 + s.logger.Error("deactivate config", "err", err) 534 + http.Error(w, "Internal Server Error", http.StatusInternalServerError) 535 + return 536 + } 537 + 538 + if err := s.store.DeleteToken(ctx, token); err != nil { 539 + s.logger.Warn("delete token", "err", err) 540 + } 541 + 542 + s.logger.Info("config deactivated via one-click", "config_id", cfg.ID, "filename", cfg.Filename) 543 + 544 + // RFC 8058: Return success without redirect 545 + w.WriteHeader(http.StatusOK) 546 + _, _ = w.Write([]byte("Unsubscribed")) 547 + return 548 + } 549 + 550 + // Manual unsubscribe flow 517 551 action := r.FormValue("action") 518 552 if action != "deactivate" && action != "delete" { 519 553 http.Error(w, "Invalid action", http.StatusBadRequest)