parse mail subject when receiving and saving to db

this way, when the inbox route is called, there is no need to parse all
mails neither request them from db just so it can have their subject
This commit is contained in:
Guilherme Rugai Freire 2024-07-18 22:07:53 -03:00
parent b01e6776dc
commit a88e5e90dc
No known key found for this signature in database
GPG Key ID: AC1D9B6E48E16AC1
4 changed files with 24 additions and 16 deletions

View File

@ -41,5 +41,4 @@ Available env variables:
- Restart when either mail or web server dies - Restart when either mail or web server dies
- Handle attachments - Handle attachments
- Do not store the raw mail data in the DB, maybe use block storage (the provider can be a disk provider at first) - Do not store the raw mail data in the DB, maybe use block storage (the provider can be a disk provider at first)
- Cache subject parsed from email. Then when listing the email it is not necessary to parse all mails and retrieve them.
- Cache in general? - Cache in general?

View File

@ -5,5 +5,6 @@ CREATE TABLE mails (
arrived_at integer not null, arrived_at integer not null,
rcpt_addr text not null, rcpt_addr text not null,
from_addr text not null, from_addr text not null,
subject text,
data blob not null data blob not null
); );

View File

@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/GRFreire/nthmail/pkg/mail_utils"
"github.com/emersion/go-smtp" "github.com/emersion/go-smtp"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@ -58,13 +59,19 @@ func (session *Session) Data(reader io.Reader) error {
return err return err
} else { } else {
stmt, err := session.tx.Prepare("INSERT INTO mails (arrived_at, rcpt_addr, from_addr, data) VALUES (?, ?, ?, ?)") stmt, err := session.tx.Prepare("INSERT INTO mails (arrived_at, rcpt_addr, from_addr, subject, data) VALUES (?, ?, ?, ?, ?)")
if err != nil { if err != nil {
println(err)
return err return err
} }
defer stmt.Close() defer stmt.Close()
_, err = stmt.Exec(session.arrived_at, session.rcpt, session.from, bytes) mail_obj, err := mail_utils.Parse_mail(bytes, true)
if err != nil {
return err
}
_, err = stmt.Exec(session.arrived_at, session.rcpt, session.from, mail_obj.Subject, bytes)
if err != nil { if err != nil {
return err return err
} }

View File

@ -59,6 +59,12 @@ type ServerResouces struct {
domain string domain string
} }
type db_mail_header struct {
Id int
Arrived_at int64
Rcpt_addr, From_addr string
Subject string
}
type db_mail struct { type db_mail struct {
Id int Id int
Arrived_at int64 Arrived_at int64
@ -105,7 +111,7 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request)
} }
defer tx.Commit() defer tx.Commit()
stmt, err := tx.Prepare("SELECT mails.id, mails.arrived_at, mails.rcpt_addr, mails.from_addr, mails.data FROM mails WHERE mails.rcpt_addr = ?") stmt, err := tx.Prepare("SELECT mails.id, mails.arrived_at, mails.rcpt_addr, mails.from_addr, mails.subject FROM mails WHERE mails.rcpt_addr = ?")
if err != nil { if err != nil {
res.WriteHeader(500) res.WriteHeader(500)
res.Write([]byte("internal server error")) res.Write([]byte("internal server error"))
@ -127,8 +133,8 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request)
var mails []mail_utils.Mail_obj var mails []mail_utils.Mail_obj
for rows.Next() { for rows.Next() {
var m db_mail var m db_mail_header
err = rows.Scan(&m.Id, &m.Arrived_at, &m.Rcpt_addr, &m.From_addr, &m.Data) err = rows.Scan(&m.Id, &m.Arrived_at, &m.Rcpt_addr, &m.From_addr, &m.Subject)
if err != nil { if err != nil {
res.WriteHeader(500) res.WriteHeader(500)
res.Write([]byte("internal server error")) res.Write([]byte("internal server error"))
@ -137,17 +143,12 @@ func (sr ServerResouces) handleInbox(res http.ResponseWriter, req *http.Request)
return return
} }
mail_obj, err := mail_utils.Parse_mail(m.Data, true) var mail_obj mail_utils.Mail_obj
mail_obj.Date = time.Unix(m.Arrived_at, 0)
mail_obj.Id = m.Id mail_obj.Id = m.Id
if err != nil { mail_obj.Date = time.Unix(m.Arrived_at, 0)
res.WriteHeader(500) mail_obj.To = m.Rcpt_addr
res.Write([]byte("internal server error")) mail_obj.From = m.From_addr
mail_obj.Subject = m.Subject
log.Println("could not parse mail")
log.Println(err)
return
}
mails = append(mails, mail_obj) mails = append(mails, mail_obj)
} }