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