/* * Copyright (c) 2026 Kaiy Ragur * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package local import ( "bytes" "io" "log" "os" "github.com/neilalexander/yggmail/internal/storage" "github.com/neilalexander/yggmail/internal/storage/types" ) type LocalStorage struct { storage.Storage db storage.MailStore blobs storage.BlobStore threshold int64 log log.Logger } func NewLocalStorage(store storage.MailStore, blobs storage.BlobStore, threshold int64) storage.Storage { if threshold <= 0 { threshold = 65536 // Default 64KB } return &LocalStorage{ Storage: store, db: store, blobs: blobs, threshold: threshold, log: *log.New(os.Stdout, "DB :: ", 0555), } } type body struct { io.ReadCloser io.Seeker } func (l *LocalStorage) MailSelect(pk string, mailbox string, id int) (int, *types.Mail, error) { seq, mail, err := l.db.MailSelect(pk, mailbox, id) if err != nil { return 0, nil, err } if mail.MailFile != "" { l.log.Println("Message Blob large take from ", mail.MailFile) rc, err := l.blobs.ReadMail(mail.MailFile) if err != nil { return 0, nil, err } mail.Body = rc } else { l.log.Println("Message Blob less take from DB") br := bytes.NewReader(mail.RawData) mail.Body = body{io.NopCloser(br), br} } return seq, mail, nil } func (l *LocalStorage) MailCreate(pk string, mailbox string, r io.Reader, size int) (int, error) { if int64(size) > l.threshold { location, written, err := l.blobs.StoreMail(pk, mailbox, r) if err != nil { return 0, err } l.log.Println("Message Blob large save in ", location) return l.db.MailCreateRaw(pk, mailbox, nil, location, written) } l.log.Println("Message Blob less save in DB") return l.db.MailCreateRaw(pk, mailbox, r, "", int64(size)) } func (l *LocalStorage) MailMove(pk string, mailbox string, id int, destination string) (int, error) { _, mail, err := l.MailSelect(pk, mailbox, id) if err != nil { return 0, err } id, err = l.db.MailMove(pk, mailbox, id, destination) if err != nil { return 0, err } if mail.MailFile != "" { _, err := l.blobs.MoveMail(mail.MailFile, destination) if err != nil { return 0, err } } return id, nil } func (s *LocalStorage) MailDelete(pk string, mailbox string, id int) error { log.Println("Delete: ", pk, mailbox, id) _, mail, err := s.Storage.MailSelect(pk, mailbox, id) if err == nil && mail.MailFile != "" { _ = s.blobs.DeleteMail(mail.MailFile) } return s.Storage.MailDelete(pk, mailbox, id) }