diff --git a/config/config.go b/config/config.go index 500e522..7b266db 100644 --- a/config/config.go +++ b/config/config.go @@ -15,6 +15,9 @@ type Account struct { Email string `json:"email"` Password string `json:"password"` ServiceProvider string `json:"service_provider"` // "gmail", "icloud", or "custom" + // FetchEmail is the single email address for which messages should be fetched. + // If empty, it will default to `Email` when accounts are added. + FetchEmail string `json:"fetch_email,omitempty"` // Custom server settings (used when ServiceProvider is "custom") IMAPServer string `json:"imap_server,omitempty"` @@ -144,6 +147,8 @@ func LoadConfig() (*Config, error) { Email: legacyConfig.Email, Password: legacyConfig.Password, ServiceProvider: legacyConfig.ServiceProvider, + // Default FetchEmail to the legacy Email value + FetchEmail: legacyConfig.Email, }, }, } @@ -171,6 +176,10 @@ func (c *Config) AddAccount(account Account) { if account.ID == "" { account.ID = uuid.New().String() } + // Ensure FetchEmail defaults to the login Email if not explicitly set. + if account.FetchEmail == "" && account.Email != "" { + account.FetchEmail = account.Email + } c.Accounts = append(c.Accounts, account) } diff --git a/fetcher/fetcher.go b/fetcher/fetcher.go index 0ba0790..ed50c26 100644 --- a/fetcher/fetcher.go +++ b/fetcher/fetcher.go @@ -164,9 +164,33 @@ func FetchEmails(account *config.Account, limit, offset uint32) ([]Email, error) } var toAddrList []string + // Build recipient list from To and Cc for matching and display for _, addr := range msg.Envelope.To { toAddrList = append(toAddrList, addr.Address()) } + for _, addr := range msg.Envelope.Cc { + toAddrList = append(toAddrList, addr.Address()) + } + + // Determine which email to filter on: prefer Account.FetchEmail, fallback to Account.Email + fetchEmail := strings.ToLower(strings.TrimSpace(account.FetchEmail)) + if fetchEmail == "" { + fetchEmail = strings.ToLower(strings.TrimSpace(account.Email)) + } + + // Check if any recipient matches the fetchEmail + matched := false + for _, r := range toAddrList { + if strings.EqualFold(strings.TrimSpace(r), fetchEmail) { + matched = true + break + } + } + + if !matched { + // Skip messages not addressed to the configured fetch email + continue + } emails = append(emails, Email{ UID: msg.Uid, diff --git a/main.go b/main.go index 5fd9bde..4cd9f56 100644 --- a/main.go +++ b/main.go @@ -140,9 +140,10 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { account := config.Account{ ID: uuid.New().String(), Name: msg.Name, - Email: msg.Email, + Email: msg.Host, // login/email used for authentication comes from Host field in the form Password: msg.Password, ServiceProvider: msg.Provider, + FetchEmail: msg.FetchEmail, } if msg.Provider == "custom" { @@ -152,6 +153,11 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 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 + } + if m.config == nil { m.config = &config.Config{} } diff --git a/tui/login.go b/tui/login.go index c7e473d..0337423 100644 --- a/tui/login.go +++ b/tui/login.go @@ -23,6 +23,7 @@ const ( inputProvider = iota inputName inputEmail + inputFetchEmail inputPassword inputIMAPServer inputIMAPPort @@ -52,6 +53,9 @@ func NewLogin() *Login { t.Placeholder = "Display Name" t.Prompt = "👤 > " case inputEmail: + t.Placeholder = "Host" + t.Prompt = "🏠 > " + case inputFetchEmail: t.Placeholder = "Email Address" t.Prompt = "✉️ > " case inputPassword: @@ -130,7 +134,8 @@ func (m *Login) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return Credentials{ Provider: m.inputs[inputProvider].Value(), Name: m.inputs[inputName].Value(), - Email: m.inputs[inputEmail].Value(), + Host: m.inputs[inputEmail].Value(), + FetchEmail: m.inputs[inputFetchEmail].Value(), Password: m.inputs[inputPassword].Value(), IMAPServer: m.inputs[inputIMAPServer].Value(), IMAPPort: imapPort, @@ -218,6 +223,7 @@ func (m *Login) View() string { m.inputs[inputProvider].View(), m.inputs[inputName].View(), m.inputs[inputEmail].View(), + m.inputs[inputFetchEmail].View(), m.inputs[inputPassword].View(), } @@ -238,12 +244,13 @@ func (m *Login) View() string { } // SetEditMode sets the login form to edit an existing account. -func (m *Login) SetEditMode(accountID, provider, name, email, imapServer string, imapPort int, smtpServer string, smtpPort int) { +func (m *Login) SetEditMode(accountID, provider, name, email, fetchEmail, imapServer string, imapPort int, smtpServer string, smtpPort int) { m.isEditMode = true m.accountID = accountID m.inputs[inputProvider].SetValue(provider) m.inputs[inputName].SetValue(name) m.inputs[inputEmail].SetValue(email) + m.inputs[inputFetchEmail].SetValue(fetchEmail) m.showCustom = provider == "custom" if m.showCustom { diff --git a/tui/messages.go b/tui/messages.go index e2a7cac..acc74fc 100644 --- a/tui/messages.go +++ b/tui/messages.go @@ -24,7 +24,8 @@ type SendEmailMsg struct { type Credentials struct { Provider string Name string - Email string + Host string // Host (this was the previous \"Email Address\" field in the UI) + FetchEmail string // Single email address to fetch messages for. If empty, code should default this to Host when creating the account. Password string IMAPServer string IMAPPort int