package proton
import (
"encoding/json"
"fmt"
"log/slog"
"net/http"
)
type Handlers struct {
monitor *Monitor
username string
logger *slog.Logger
}
func NewHandlers(monitor *Monitor, username string, logger *slog.Logger) *Handlers {
return &Handlers{
monitor: monitor,
username: username,
logger: logger,
}
}
func (h *Handlers) HandleFragment(w http.ResponseWriter, r *http.Request) {
if h.monitor == nil {
return // Proton not enabled
}
w.Header().Set("Content-Type", "text/html")
statusBadge := `Unlinked`
var content string
var openAttr string
if h.monitor.IsConnected() {
statusBadge = fmt.Sprintf(`Linked%s`, h.username)
content = `
Unlink Instructions:
- Run:
docker compose run protonmail-bridge init
- In the bridge CLI, use:
logout
- Then:
exit to close the bridge
`
openAttr = ""
} else {
content = `
Setup Instructions:
- Run:
docker compose run --rm protonmail-bridge init
- At the prompt, use:
login and enter your Proton Mail credentials
- Run:
info to get your IMAP username and password
- Add credentials to
.env and restart
See full setup guide
`
openAttr = " open"
}
html := fmt.Sprintf(`
%s
`, openAttr, statusBadge, content)
_, _ = fmt.Fprint(w, html)
}
func (h *Handlers) IsEnabled() bool {
return h.monitor != nil
}
func (h *Handlers) GetMonitor() *Monitor {
return h.monitor
}
type markReadRequest struct {
UID uint32 `json:"uid"`
}
func (h *Handlers) HandleMarkRead(w http.ResponseWriter, r *http.Request) {
var req markReadRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]string{"error": "invalid request body"})
return
}
if req.UID == 0 {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]string{"error": "uid (number) is required"})
return
}
if h.monitor == nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_ = json.NewEncoder(w).Encode(map[string]string{"error": "Proton integration not enabled"})
return
}
if err := h.monitor.MarkAsRead(req.UID); err != nil {
h.logger.Error("failed to mark email as read", "uid", req.UID, "error", err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
_ = json.NewEncoder(w).Encode(map[string]string{"error": "failed to mark as read"})
return
}
h.logger.Info("marked email as read", "uid", req.UID)
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(map[string]bool{"success": true}); err != nil {
h.logger.Error("failed to encode response", "error", err)
}
}