143 lines
2.8 KiB
Go
143 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/emersion/go-imap"
|
|
"github.com/emersion/go-imap/backend"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type User struct {
|
|
username string
|
|
sub uuid.UUID
|
|
openMessages map[*Message]struct{}
|
|
}
|
|
|
|
func (u *User) Username() string {
|
|
return u.username
|
|
}
|
|
|
|
func (u *User) ListMailboxes(subscribed bool) (mailboxes []backend.Mailbox, err error) {
|
|
mailboxQuery, err := Database.DB.Query("SELECT mailbox, subscribed FROM mailboxes")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
defer func() {
|
|
err := mailboxQuery.Close()
|
|
if err != nil {
|
|
log("Failed to close rows: "+err.Error()+", resource leaks may occur", 1)
|
|
}
|
|
}()
|
|
|
|
for mailboxQuery.Next() {
|
|
var name string
|
|
var subscribed bool
|
|
err := mailboxQuery.Scan(&name, &subscribed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mbox := &Mailbox{
|
|
name: name,
|
|
user: u,
|
|
}
|
|
mbox.Subscribed = subscribed
|
|
|
|
err = Database.DB.QueryRow("SELECT id FROM mailboxes WHERE mailbox = $1", name).Scan(&mbox.id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mailboxes = append(mailboxes, mbox)
|
|
}
|
|
|
|
return mailboxes, nil
|
|
}
|
|
|
|
func (u *User) GetRawMailbox(name string) (mailbox *Mailbox, err error) {
|
|
mailbox = &Mailbox{
|
|
name: name,
|
|
user: u,
|
|
}
|
|
|
|
err = Database.DB.QueryRow("SELECT id, subscribed FROM mailboxes WHERE mailbox = $1", name).Scan(&mailbox.id, &mailbox.Subscribed)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return mailbox, nil
|
|
}
|
|
|
|
func (u *User) GetMailbox(name string) (mailbox backend.Mailbox, err error) {
|
|
return u.GetRawMailbox(name)
|
|
}
|
|
|
|
func (u *User) CreateMailbox(name string) error {
|
|
_, err := Database.DB.Exec("INSERT INTO mailboxes (mailbox, id, owner) VALUES ($1, $2, $3)", name, uuid.New(), u.sub[:])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *User) DeleteMailbox(name string) error {
|
|
if name == "INBOX" {
|
|
return errors.New("cannot delete INBOX")
|
|
}
|
|
|
|
_, err := Database.DB.Exec("DELETE FROM mailboxes WHERE mailbox = $1", name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *User) RenameMailbox(existingName, newName string) error {
|
|
if existingName != "INBOX" {
|
|
_, err := Database.DB.Exec("UPDATE mailboxes SET mailbox = $1 WHERE mailbox = $2", newName, existingName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
// INBOX is a special case, we need to create a new mailbox and copy the contents
|
|
err := u.CreateMailbox(newName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
inbox, err := u.GetRawMailbox(newName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
set := new(imap.SeqSet)
|
|
set.AddRange(1, 4294967295) // uint32 maximum value, essentially means all messages
|
|
|
|
err = inbox.CopyMessages(true, set, newName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = inbox.Expunge()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *User) Logout() error {
|
|
for msg := range u.openMessages {
|
|
err := msg.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|