mirror of
https://github.com/axllent/mailpit.git
synced 2025-01-18 03:22:06 +02:00
185 lines
3.6 KiB
Go
185 lines
3.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"database/sql"
|
|
"os"
|
|
|
|
"github.com/axllent/mailpit/internal/logger"
|
|
"github.com/axllent/mailpit/internal/tools"
|
|
"github.com/jhillyerd/enmime"
|
|
"github.com/leporo/sqlf"
|
|
)
|
|
|
|
// ReindexAll will regenerate the search text and snippet for a message
|
|
// and update the database.
|
|
func ReindexAll() {
|
|
ids := []string{}
|
|
var i string
|
|
chunkSize := 1000
|
|
|
|
finished := 0
|
|
|
|
err := sqlf.Select("ID").To(&i).
|
|
From("mailbox").
|
|
OrderBy("Created DESC").
|
|
QueryAndClose(nil, db, func(row *sql.Rows) {
|
|
ids = append(ids, i)
|
|
})
|
|
|
|
if err != nil {
|
|
logger.Log().Error(err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
total := len(ids)
|
|
|
|
chunks := chunkBy(ids, chunkSize)
|
|
|
|
logger.Log().Infof("Reindexing %d messages", total)
|
|
|
|
// fmt.Println(len(ids), " = ", len(chunks), "chunks")
|
|
|
|
type updateStruct struct {
|
|
ID string
|
|
SearchText string
|
|
Snippet string
|
|
}
|
|
|
|
for _, ids := range chunks {
|
|
updates := []updateStruct{}
|
|
|
|
for _, id := range ids {
|
|
raw, err := GetMessageRaw(id)
|
|
if err != nil {
|
|
logger.Log().Error(err)
|
|
continue
|
|
}
|
|
|
|
r := bytes.NewReader(raw)
|
|
|
|
env, err := enmime.ReadEnvelope(r)
|
|
if err != nil {
|
|
logger.Log().Error(err)
|
|
continue
|
|
}
|
|
|
|
searchText := createSearchText(env)
|
|
snippet := tools.CreateSnippet(env.Text, env.HTML)
|
|
|
|
u := updateStruct{}
|
|
u.ID = id
|
|
u.SearchText = searchText
|
|
u.Snippet = snippet
|
|
|
|
updates = append(updates, u)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
tx, err := db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
logger.Log().Error(err)
|
|
continue
|
|
}
|
|
|
|
// roll back if it fails
|
|
defer tx.Rollback()
|
|
|
|
// insert mail summary data
|
|
for _, u := range updates {
|
|
_, err = tx.Exec("UPDATE mailbox SET SearchText = ?, Snippet = ? WHERE ID = ?", u.SearchText, u.Snippet, u.ID)
|
|
if err != nil {
|
|
logger.Log().Error(err)
|
|
continue
|
|
}
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
logger.Log().Error(err)
|
|
continue
|
|
}
|
|
|
|
finished += len(updates)
|
|
|
|
logger.Log().Printf("Reindexed: %d / %d (%d%%)", finished, total, finished*100/total)
|
|
}
|
|
}
|
|
|
|
// Reindex will regenerate the search text and snippet for a message
|
|
// and update the database.
|
|
func Reindex(id string) error {
|
|
// ids := []string{}
|
|
// var i string
|
|
// // chunkSize := 100
|
|
|
|
// err := sqlf.Select("ID").To(&i).From("mailbox_data").QueryAndClose(nil, db, func(row *sql.Rows) {
|
|
// ids = append(ids, id)
|
|
// })
|
|
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// chunks := chunkBy(ids, 100)
|
|
|
|
// fmt.Println(len(ids), " = ", len(chunks), "chunks")
|
|
|
|
// return nil
|
|
|
|
raw, err := GetMessageRaw(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r := bytes.NewReader(raw)
|
|
|
|
env, err := enmime.ReadEnvelope(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
searchText := createSearchText(env)
|
|
snippet := tools.CreateSnippet(env.Text, env.HTML)
|
|
|
|
// return nil
|
|
|
|
// ctx := context.Background()
|
|
// tx, err := db.BeginTx(ctx, nil)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// // roll back if it fails
|
|
// defer tx.Rollback()
|
|
|
|
// // insert mail summary data
|
|
// _, err = tx.Exec("UPDATE mailbox SET SearchText = ?, Snippet = ? WHERE ID = ?", searchText, snippet, id)
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// return tx.Commit()
|
|
|
|
_, err = sqlf.Update("mailbox").
|
|
Set("SearchText", searchText).
|
|
Set("Snippet", snippet).
|
|
Where("ID = ?", id).
|
|
ExecAndClose(context.Background(), db)
|
|
|
|
return err
|
|
}
|
|
|
|
// ctx := context.Background()
|
|
// tx, err := db.BeginTx(ctx, nil)
|
|
// if err != nil {
|
|
// return "", err
|
|
// }
|
|
|
|
func chunkBy[T any](items []T, chunkSize int) (chunks [][]T) {
|
|
for chunkSize < len(items) {
|
|
items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
|
|
}
|
|
return append(chunks, items)
|
|
}
|