mirror of
https://github.com/GRFreire/nthmail.git
synced 2026-01-10 21:29:38 +00:00
initial commit
This commit is contained in:
commit
369115d781
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
main
|
||||||
|
*.db
|
||||||
129
cmd/mail_server/main.go
Normal file
129
cmd/mail_server/main.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/emersion/go-smtp"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Backend struct {
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (backend *Backend) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
||||||
|
tx, err := backend.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Session{
|
||||||
|
tx: tx,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
tx *sql.Tx
|
||||||
|
from, rcpt string
|
||||||
|
rcpt_addr_id int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) AuthPlain(username, password string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) Mail(from string, opts *smtp.MailOptions) error {
|
||||||
|
session.from = from
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) Rcpt(to string, opts *smtp.RcptOptions) error {
|
||||||
|
session.rcpt = to
|
||||||
|
|
||||||
|
stmt, err := session.tx.Prepare("INSERT OR IGNORE INTO inboxes (addr) VALUES (?) RETURNING id")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
|
res, err := stmt.Exec(to)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// sometimes does not work and returns 0
|
||||||
|
// see https://github.com/mattn/go-sqlite3/issues/1140
|
||||||
|
id, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Last id: ", id)
|
||||||
|
|
||||||
|
session.rcpt_addr_id = id
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) Data(reader io.Reader) error {
|
||||||
|
if bytes, err := io.ReadAll(reader); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
|
||||||
|
stmt, err := session.tx.Prepare("INSERT INTO mails (inbox_id, from_addr, data) VALUES (?, ?, ?)")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = stmt.Exec(session.rcpt_addr_id, session.from, bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = session.tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("New mail from <", session.from, "> to <", session.rcpt, ">")
|
||||||
|
log.Println("Data:", string(bytes))
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) Reset() {}
|
||||||
|
|
||||||
|
func (session *Session) Logout() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
db, err := sql.Open("sqlite3", "./db.db")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
backend := &Backend{
|
||||||
|
db: db,
|
||||||
|
}
|
||||||
|
|
||||||
|
server := smtp.NewServer(backend)
|
||||||
|
|
||||||
|
server.Addr = "localhost:1025"
|
||||||
|
server.Domain = "localhost"
|
||||||
|
server.WriteTimeout = 60 * time.Second
|
||||||
|
server.ReadTimeout = 60 * time.Second
|
||||||
|
server.MaxMessageBytes = 1024 * 1024
|
||||||
|
server.MaxRecipients = 50
|
||||||
|
server.AllowInsecureAuth = true
|
||||||
|
|
||||||
|
log.Println("Starting server at", server.Addr)
|
||||||
|
if err := server.ListenAndServe(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
9
go.mod
Normal file
9
go.mod
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module github.com/GRFreire/nthmail
|
||||||
|
|
||||||
|
go 1.21.6
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
|
||||||
|
github.com/emersion/go-smtp v0.20.2 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
|
)
|
||||||
6
go.sum
Normal file
6
go.sum
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||||
|
github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4=
|
||||||
|
github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
12
migration.sql
Normal file
12
migration.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE inboxes (
|
||||||
|
id integer not null primary key,
|
||||||
|
addr text unique
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE mails (
|
||||||
|
id integer not null primary key,
|
||||||
|
inbox_id id,
|
||||||
|
from_addr text,
|
||||||
|
data blob,
|
||||||
|
FOREIGN KEY(inbox_id) REFERENCES inboxes(id)
|
||||||
|
);
|
||||||
Loading…
Reference in New Issue
Block a user