mirror of
https://github.com/neilalexander/yggmail.git
synced 2026-05-03 18:46:29 +03:00
Add types.Mail
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/emersion/go-imap"
|
||||
"github.com/emersion/go-imap/backend/backendutil"
|
||||
"github.com/emersion/go-message/textproto"
|
||||
"github.com/neilalexander/yggmail/internal/storage/types"
|
||||
)
|
||||
|
||||
type Mailbox struct {
|
||||
@@ -115,17 +116,17 @@ func (mbox *Mailbox) ListMessages(uid bool, seqSet *imap.SeqSet, items []imap.Fe
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
mseq, mid, body, seen, answered, flagged, deleted, datetime, err := mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
mseq, mail, err := mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
fetched := imap.NewMessage(uint32(id), items)
|
||||
fetched.SeqNum = uint32(mseq)
|
||||
fetched.Uid = uint32(mid)
|
||||
fetched.Uid = uint32(mail.ID)
|
||||
|
||||
get := func() (io.Reader, textproto.Header, error) {
|
||||
bodyreader := bufio.NewReader(bytes.NewReader(body))
|
||||
bodyreader := bufio.NewReader(bytes.NewReader(mail.Mail))
|
||||
hdr, err := textproto.ReadHeader(bodyreader)
|
||||
if err != nil {
|
||||
return nil, textproto.Header{}, fmt.Errorf("textproto.ReadHeader: %w", err)
|
||||
@@ -155,24 +156,24 @@ func (mbox *Mailbox) ListMessages(uid bool, seqSet *imap.SeqSet, items []imap.Fe
|
||||
|
||||
case imap.FetchFlags:
|
||||
fetched.Flags = []string{}
|
||||
if seen {
|
||||
if mail.Seen {
|
||||
fetched.Flags = append(fetched.Flags, "\\Seen")
|
||||
}
|
||||
if answered {
|
||||
if mail.Answered {
|
||||
fetched.Flags = append(fetched.Flags, "\\Answered")
|
||||
}
|
||||
if flagged {
|
||||
if mail.Flagged {
|
||||
fetched.Flags = append(fetched.Flags, "\\Flagged")
|
||||
}
|
||||
if deleted {
|
||||
if mail.Deleted {
|
||||
fetched.Flags = append(fetched.Flags, "\\Deleted")
|
||||
}
|
||||
|
||||
case imap.FetchInternalDate:
|
||||
fetched.InternalDate = datetime
|
||||
fetched.InternalDate = mail.Date
|
||||
|
||||
case imap.FetchRFC822Size:
|
||||
fetched.Size = uint32(len(body))
|
||||
fetched.Size = uint32(len(mail.Mail))
|
||||
|
||||
case imap.FetchUid:
|
||||
fetched.Uid = uint32(id)
|
||||
@@ -241,11 +242,10 @@ func (mbox *Mailbox) UpdateMessagesFlags(uid bool, seqSet *imap.SeqSet, op imap.
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
var seen, answered, flagged, deleted bool
|
||||
var mid int
|
||||
var mail *types.Mail
|
||||
if op != imap.SetFlags {
|
||||
var err error
|
||||
_, mid, _, seen, answered, flagged, deleted, _, err = mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
_, mail, err = mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
if err != nil {
|
||||
return fmt.Errorf("mbox.backend.Storage.MailSelect: %w", err)
|
||||
}
|
||||
@@ -253,18 +253,19 @@ func (mbox *Mailbox) UpdateMessagesFlags(uid bool, seqSet *imap.SeqSet, op imap.
|
||||
for _, flag := range flags {
|
||||
switch flag {
|
||||
case "\\Seen":
|
||||
seen = op != imap.RemoveFlags
|
||||
mail.Seen = op != imap.RemoveFlags
|
||||
case "\\Answered":
|
||||
answered = op != imap.RemoveFlags
|
||||
mail.Answered = op != imap.RemoveFlags
|
||||
case "\\Flagged":
|
||||
flagged = op != imap.RemoveFlags
|
||||
mail.Flagged = op != imap.RemoveFlags
|
||||
case "\\Deleted":
|
||||
deleted = op != imap.RemoveFlags
|
||||
mail.Deleted = op != imap.RemoveFlags
|
||||
}
|
||||
}
|
||||
|
||||
if err := mbox.backend.Storage.MailUpdateFlags(
|
||||
mbox.name, int(mid), seen, answered, flagged, deleted,
|
||||
mbox.name, int(mail.ID), mail.Seen,
|
||||
mail.Answered, mail.Flagged, mail.Deleted,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -283,15 +284,17 @@ func (mbox *Mailbox) CopyMessages(uid bool, seqSet *imap.SeqSet, destName string
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
_, _, body, seen, answered, flagged, deleted, _, err := mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
_, mail, err := mbox.backend.Storage.MailSelect(mbox.name, int(id))
|
||||
if err != nil {
|
||||
return fmt.Errorf("mbox.backend.Storage.MailSelect: %w", err)
|
||||
}
|
||||
pid, err := mbox.backend.Storage.MailCreate(destName, body)
|
||||
pid, err := mbox.backend.Storage.MailCreate(destName, mail.Mail)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mbox.backend.Storage.MailCreate: %w", err)
|
||||
}
|
||||
if err = mbox.backend.Storage.MailUpdateFlags(mbox.name, pid, seen, answered, flagged, deleted); err != nil {
|
||||
if err = mbox.backend.Storage.MailUpdateFlags(
|
||||
mbox.name, pid, mail.Seen, mail.Answered, mail.Flagged, mail.Deleted,
|
||||
); err != nil {
|
||||
return fmt.Errorf("mbox.backend.Storage.MailUpdateFlags: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/neilalexander/yggmail/internal/storage/types"
|
||||
)
|
||||
|
||||
type TableMails struct {
|
||||
@@ -35,7 +37,6 @@ const mailsSchema = `
|
||||
FOREIGN KEY (mailbox) REFERENCES mailboxes(mailbox) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
DROP VIEW IF EXISTS inboxes;
|
||||
CREATE VIEW IF NOT EXISTS inboxes AS SELECT * FROM (
|
||||
SELECT ROW_NUMBER() OVER (PARTITION BY mailbox) AS seq, * FROM mails
|
||||
)
|
||||
@@ -160,13 +161,14 @@ func (t *TableMails) MailCreate(mailbox string, data []byte) (int, error) {
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (t *TableMails) MailSelect(mailbox string, id int) (int, int, []byte, bool, bool, bool, bool, time.Time, error) {
|
||||
var data []byte
|
||||
var seen, answered, flagged, deleted bool
|
||||
var ts int64
|
||||
var seq, pid int
|
||||
err := t.selectMail.QueryRow(mailbox, id).Scan(&seq, &pid, &data, &ts, &seen, &answered, &flagged, &deleted)
|
||||
return seq, pid, data, seen, answered, flagged, deleted, time.Unix(ts, 0), err
|
||||
func (t *TableMails) MailSelect(mailbox string, id int) (int, *types.Mail, error) {
|
||||
var seq int
|
||||
mail := &types.Mail{}
|
||||
err := t.selectMail.QueryRow(mailbox, id).Scan(
|
||||
&seq, &mail.ID, &mail.Mail, &mail.Date,
|
||||
&mail.Seen, &mail.Answered, &mail.Flagged, &mail.Deleted,
|
||||
)
|
||||
return seq, mail, err
|
||||
}
|
||||
|
||||
func (t *TableMails) MailSearch(mailbox string) ([]uint32, error) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package storage
|
||||
|
||||
import "time"
|
||||
import "github.com/neilalexander/yggmail/internal/storage/types"
|
||||
|
||||
type Storage interface {
|
||||
ConfigGet(key string) (string, error)
|
||||
@@ -19,7 +19,7 @@ type Storage interface {
|
||||
MailboxSubscribe(name string, subscribed bool) error
|
||||
|
||||
MailCreate(mailbox string, data []byte) (int, error)
|
||||
MailSelect(mailbox string, id int) (int, int, []byte, bool, bool, bool, bool, time.Time, error)
|
||||
MailSelect(mailbox string, id int) (int, *types.Mail, error)
|
||||
MailSearch(mailbox string) ([]uint32, error)
|
||||
MailUpdateFlags(mailbox string, id int, seen, answered, flagged, deleted bool) error
|
||||
MailDelete(mailbox, id string) error
|
||||
|
||||
14
internal/storage/types/types.go
Normal file
14
internal/storage/types/types.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
type Mail struct {
|
||||
Mailbox string
|
||||
ID int
|
||||
Mail []byte
|
||||
Date time.Time
|
||||
Seen bool
|
||||
Answered bool
|
||||
Flagged bool
|
||||
Deleted bool
|
||||
}
|
||||
Reference in New Issue
Block a user