package cmd import ( "fmt" "os" "strconv" "github.com/frenocorp/pop/internal/api" "github.com/frenocorp/pop/internal/config" internalmail "github.com/frenocorp/pop/internal/mail" "github.com/spf13/cobra" ) func mailDraftCmd() *cobra.Command { cmd := &cobra.Command{ Use: "draft", Short: "Manage draft messages", Long: `Save, list, edit, and send draft messages.`, } cmd.AddCommand(draftSaveCmd()) cmd.AddCommand(draftListCmd()) cmd.AddCommand(draftEditCmd()) cmd.AddCommand(draftSendCmd()) return cmd } func draftSaveCmd() *cobra.Command { var to, cc, bcc, subject, bodyFile, body string cmd := &cobra.Command{ Use: "save", Short: "Save a draft message", Long: `Save a message as a draft in ProtonMail.`, RunE: func(cmd *cobra.Command, args []string) error { if to == "" { return fmt.Errorf("recipient is required (--to)") } msgBody := body if bodyFile != "" { data, err := os.ReadFile(bodyFile) if err != nil { return fmt.Errorf("failed to read body file: %w", err) } msgBody = string(data) } recipients := parseRecipients(to) var ccRecipients []internalmail.Recipient if cc != "" { ccRecipients = parseRecipients(cc) } var bccRecipients []internalmail.Recipient if bcc != "" { bccRecipients = parseRecipients(bcc) } cfgMgr := config.NewConfigManager() cfg, err := cfgMgr.Load() if err != nil { return fmt.Errorf("failed to load config: %w", err) } session, sessionMgr, err := checkAuthenticatedWithManager() if err != nil { return fmt.Errorf("not authenticated: %w", err) } client := api.NewProtonMailClient(cfg, sessionMgr) client.SetAuthHeader(session.AccessToken) mailClient := internalmail.NewClient(client) draft := internalmail.Draft{ To: recipients, CC: ccRecipients, BCC: bccRecipients, Subject: subject, Body: msgBody, } messageID, err := mailClient.SaveDraft(draft, session.MailPassphrase) if err != nil { return fmt.Errorf("failed to save draft: %w", err) } fmt.Printf("Draft saved with ID: %s\n", messageID) return nil }, } cmd.Flags().StringVarP(&to, "to", "t", "", "Recipient addresses (comma-separated)") cmd.Flags().StringVarP(&cc, "cc", "c", "", "CC addresses (comma-separated)") cmd.Flags().StringVarP(&bcc, "bcc", "b", "", "BCC addresses (comma-separated)") cmd.Flags().StringVarP(&subject, "subject", "s", "", "Draft subject") cmd.Flags().StringVarP(&bodyFile, "body-file", "f", "", "File containing draft body") cmd.Flags().StringVar(&body, "body", "", "Inline draft body") return cmd } func draftListCmd() *cobra.Command { var page, pageSize string cmd := &cobra.Command{ Use: "list", Short: "List draft messages", Long: `List all draft messages in ProtonMail.`, RunE: func(cmd *cobra.Command, args []string) error { pageVal, err := strconv.Atoi(page) if err != nil || pageVal < 1 { pageVal = 1 } pageSizeVal, err := strconv.Atoi(pageSize) if err != nil || pageSizeVal < 1 { pageSizeVal = 20 } cfgMgr := config.NewConfigManager() cfg, err := cfgMgr.Load() if err != nil { return fmt.Errorf("failed to load config: %w", err) } session, sessionMgr, err := checkAuthenticatedWithManager() if err != nil { return fmt.Errorf("not authenticated: %w", err) } client := api.NewProtonMailClient(cfg, sessionMgr) client.SetAuthHeader(session.AccessToken) mailClient := internalmail.NewClient(client) result, err := mailClient.ListDrafts(pageVal, pageSizeVal, session.MailPassphrase) if err != nil { return fmt.Errorf("failed to list drafts: %w", err) } return printMessages(result.Messages) }, } cmd.Flags().StringVar(&page, "page", "1", "Page number") cmd.Flags().StringVar(&pageSize, "page-size", "20", "Drafts per page (max 100)") return cmd } func draftEditCmd() *cobra.Command { var to, cc, bcc, subject, bodyFile, body string cmd := &cobra.Command{ Use: "edit ", Short: "Edit a draft message", Long: `Edit an existing draft message in ProtonMail.`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { messageID := args[0] var recipients []internalmail.Recipient if to != "" { recipients = parseRecipients(to) } var ccRecipients []internalmail.Recipient if cc != "" { ccRecipients = parseRecipients(cc) } var bccRecipients []internalmail.Recipient if bcc != "" { bccRecipients = parseRecipients(bcc) } msgBody := body if bodyFile != "" { data, err := os.ReadFile(bodyFile) if err != nil { return fmt.Errorf("failed to read body file: %w", err) } msgBody = string(data) } cfgMgr := config.NewConfigManager() cfg, err := cfgMgr.Load() if err != nil { return fmt.Errorf("failed to load config: %w", err) } session, sessionMgr, err := checkAuthenticatedWithManager() if err != nil { return fmt.Errorf("not authenticated: %w", err) } client := api.NewProtonMailClient(cfg, sessionMgr) client.SetAuthHeader(session.AccessToken) mailClient := internalmail.NewClient(client) draft := internalmail.Draft{ To: recipients, CC: ccRecipients, BCC: bccRecipients, Subject: subject, Body: msgBody, } if err := mailClient.UpdateDraft(messageID, draft, session.MailPassphrase); err != nil { return fmt.Errorf("failed to update draft: %w", err) } fmt.Println("Draft updated successfully") return nil }, } cmd.Flags().StringVarP(&to, "to", "t", "", "New recipient addresses (comma-separated)") cmd.Flags().StringVarP(&cc, "cc", "c", "", "New CC addresses (comma-separated)") cmd.Flags().StringVarP(&bcc, "bcc", "b", "", "New BCC addresses (comma-separated)") cmd.Flags().StringVarP(&subject, "subject", "s", "", "New draft subject") cmd.Flags().StringVarP(&bodyFile, "body-file", "f", "", "File containing new draft body") cmd.Flags().StringVar(&body, "body", "", "New inline draft body") return cmd } func draftSendCmd() *cobra.Command { cmd := &cobra.Command{ Use: "send ", Short: "Send a draft message", Long: `Send an existing draft message from ProtonMail.`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { messageID := args[0] cfgMgr := config.NewConfigManager() cfg, err := cfgMgr.Load() if err != nil { return fmt.Errorf("failed to load config: %w", err) } session, sessionMgr, err := checkAuthenticatedWithManager() if err != nil { return fmt.Errorf("not authenticated: %w", err) } client := api.NewProtonMailClient(cfg, sessionMgr) client.SetAuthHeader(session.AccessToken) mailClient := internalmail.NewClient(client) if err := mailClient.SendDraft(messageID, session.MailPassphrase); err != nil { return fmt.Errorf("failed to send draft: %w", err) } fmt.Println("Draft sent successfully") return nil }, } return cmd }