Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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,
},
},
}
Expand Down Expand Up @@ -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)
}

Expand Down
24 changes: 24 additions & 0 deletions fetcher/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 7 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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{}
}
Expand Down
11 changes: 9 additions & 2 deletions tui/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
inputProvider = iota
inputName
inputEmail
inputFetchEmail
inputPassword
inputIMAPServer
inputIMAPPort
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(),
}

Expand All @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion tui/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading