feat: add imap service interface

This commit is contained in:
thibaud-leclere 2026-04-10 11:11:01 +02:00
parent 0406630e03
commit 00fa0699f5
3 changed files with 96 additions and 0 deletions

View file

@ -0,0 +1,27 @@
package imapclient
import (
"context"
"email-mcp/internal/secretstore"
)
type Service struct {
backend Backend
}
func NewService(backend Backend) Service {
return Service{backend: backend}
}
func (s Service) ListMailboxes(ctx context.Context, cred secretstore.Credential) ([]Mailbox, error) {
return s.backend.ListMailboxes(ctx, cred)
}
func (s Service) ListMessages(ctx context.Context, cred secretstore.Credential, mailbox string, limit int) ([]MessageSummary, error) {
return s.backend.ListMessages(ctx, cred, mailbox, limit)
}
func (s Service) GetMessage(ctx context.Context, cred secretstore.Credential, mailbox string, id string) (Message, error) {
return s.backend.GetMessage(ctx, cred, mailbox, id)
}

View file

@ -0,0 +1,38 @@
package imapclient
import (
"context"
"testing"
"email-mcp/internal/secretstore"
)
type backendStub struct{}
func (backendStub) ListMailboxes(context.Context, secretstore.Credential) ([]Mailbox, error) {
return []Mailbox{{Name: "INBOX"}}, nil
}
func (backendStub) ListMessages(context.Context, secretstore.Credential, string, int) ([]MessageSummary, error) {
return nil, nil
}
func (backendStub) GetMessage(context.Context, secretstore.Credential, string, string) (Message, error) {
return Message{}, nil
}
func TestServiceListMailboxesUsesBackend(t *testing.T) {
svc := NewService(backendStub{})
boxes, err := svc.ListMailboxes(context.Background(), secretstore.Credential{
Host: "imap.example.com",
Username: "alice",
Password: "secret",
})
if err != nil {
t.Fatalf("ListMailboxes returned error: %v", err)
}
if len(boxes) != 1 || boxes[0].Name != "INBOX" {
t.Fatalf("unexpected mailboxes: %#v", boxes)
}
}

View file

@ -0,0 +1,31 @@
package imapclient
import (
"context"
"email-mcp/internal/secretstore"
)
type Mailbox struct {
Name string `json:"name"`
}
type MessageSummary struct {
ID string `json:"id"`
Subject string `json:"subject"`
From string `json:"from"`
UID uint32 `json:"uid"`
}
type Message struct {
ID string `json:"id"`
Mailbox string `json:"mailbox"`
Headers map[string]string `json:"headers"`
Body string `json:"body"`
}
type Backend interface {
ListMailboxes(context.Context, secretstore.Credential) ([]Mailbox, error)
ListMessages(context.Context, secretstore.Credential, string, int) ([]MessageSummary, error)
GetMessage(context.Context, secretstore.Credential, string, string) (Message, error)
}