From 312128159578ef94ab727fa961e6d9420d708c17 Mon Sep 17 00:00:00 2001 From: drew Date: Sun, 29 Mar 2026 21:57:00 +0400 Subject: [PATCH] feat: add multiple accounts at once (fetch email) Signed-off-by: drew --- main.go | 92 +++++++++++++++++++++++++++++++++++++--------------- tui/login.go | 4 +-- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/main.go b/main.go index 2c0ae46..a5b9ab7 100644 --- a/main.go +++ b/main.go @@ -187,27 +187,19 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, m.current.Init() case tui.Credentials: - // Add new account or update existing - account := config.Account{ - ID: uuid.New().String(), - Name: msg.Name, - Email: msg.Host, // login/email used for authentication comes from Host field in the form - Password: msg.Password, - ServiceProvider: msg.Provider, - FetchEmail: msg.FetchEmail, - AuthMethod: msg.AuthMethod, - } - - if msg.Provider == "custom" { - account.IMAPServer = msg.IMAPServer - account.IMAPPort = msg.IMAPPort - account.SMTPServer = msg.SMTPServer - account.SMTPPort = msg.SMTPPort - } - - // Ensure FetchEmail defaults to the login Email (Host) if not explicitly set - if account.FetchEmail == "" && account.Email != "" { - account.FetchEmail = account.Email + // Split FetchEmail by commas to support multiple fetch addresses. + // Each address creates a separate account sharing the same login credentials. + fetchEmails := []string{""} + if msg.FetchEmail != "" { + fetchEmails = fetchEmails[:0] + for _, fe := range strings.Split(msg.FetchEmail, ",") { + if trimmed := strings.TrimSpace(fe); trimmed != "" { + fetchEmails = append(fetchEmails, trimmed) + } + } + if len(fetchEmails) == 0 { + fetchEmails = []string{""} + } } if m.config == nil { @@ -216,13 +208,35 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // Check if we're editing an existing account isEdit := false + var lastAccount config.Account if login, ok := m.current.(*tui.Login); ok && login.IsEditMode() { isEdit = true - // Find and update the existing account, preserving S/MIME settings existingID := login.GetAccountID() + + account := config.Account{ + ID: existingID, + Name: msg.Name, + Email: msg.Host, + Password: msg.Password, + ServiceProvider: msg.Provider, + FetchEmail: fetchEmails[0], + AuthMethod: msg.AuthMethod, + } + + if msg.Provider == "custom" { + account.IMAPServer = msg.IMAPServer + account.IMAPPort = msg.IMAPPort + account.SMTPServer = msg.SMTPServer + account.SMTPPort = msg.SMTPPort + } + + if account.FetchEmail == "" && account.Email != "" { + account.FetchEmail = account.Email + } + + // Find and update the existing account, preserving S/MIME settings for i, acc := range m.config.Accounts { if acc.ID == existingID { - account.ID = existingID account.SMIMECert = acc.SMIMECert account.SMIMEKey = acc.SMIMEKey account.SMIMESignByDefault = acc.SMIMESignByDefault @@ -233,8 +247,34 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { break } } + lastAccount = account } else { - m.config.AddAccount(account) + // New account: create one account per fetch email address + for _, fe := range fetchEmails { + account := config.Account{ + ID: uuid.New().String(), + Name: msg.Name, + Email: msg.Host, + Password: msg.Password, + ServiceProvider: msg.Provider, + FetchEmail: fe, + AuthMethod: msg.AuthMethod, + } + + if msg.Provider == "custom" { + account.IMAPServer = msg.IMAPServer + account.IMAPPort = msg.IMAPPort + account.SMTPServer = msg.SMTPServer + account.SMTPPort = msg.SMTPPort + } + + if account.FetchEmail == "" && account.Email != "" { + account.FetchEmail = account.Email + } + + m.config.AddAccount(account) + lastAccount = account + } } if err := config.SaveConfig(m.config); err != nil { @@ -243,8 +283,8 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } // If OAuth2, launch the authorization flow after saving the account - if account.IsOAuth2() { - email := account.Email + if lastAccount.IsOAuth2() { + email := lastAccount.Email return m, func() tea.Msg { err := config.RunOAuth2Flow(email, "", "") return tui.OAuth2CompleteMsg{Email: email, Err: err} diff --git a/tui/login.go b/tui/login.go index ab03fce..d6c6bc8 100644 --- a/tui/login.go +++ b/tui/login.go @@ -61,7 +61,7 @@ func NewLogin(hideTips bool) *Login { t.Placeholder = "Username" t.Prompt = "🏠 > " case inputFetchEmail: - t.Placeholder = "Email Address" + t.Placeholder = "Email Address (comma-separated for multiple)" t.Prompt = "📧 > " case inputAuthMethod: t.Placeholder = "Auth Method (password or oauth2)" @@ -267,7 +267,7 @@ func (m *Login) View() tea.View { case inputEmail: tip = "Your full email address used to log in." case inputFetchEmail: - tip = "The email address to fetch messages from (often same as Username)." + tip = "The email address to fetch messages for (comma-separated for multiple, e.g. me@icloud.com,me@mac.com)." case inputAuthMethod: tip = "Type 'oauth2' for Gmail OAuth2 or 'password' for app password." case inputPassword: