feat: add imap service interface
This commit is contained in:
parent
0406630e03
commit
00fa0699f5
3 changed files with 96 additions and 0 deletions
27
internal/imapclient/service.go
Normal file
27
internal/imapclient/service.go
Normal 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)
|
||||||
|
}
|
||||||
38
internal/imapclient/service_test.go
Normal file
38
internal/imapclient/service_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
31
internal/imapclient/types.go
Normal file
31
internal/imapclient/types.go
Normal 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)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue