initial commit

This commit is contained in:
Guilherme Rugai Freire 2024-02-18 01:26:53 -03:00
commit 369115d781
No known key found for this signature in database
GPG Key ID: AC1D9B6E48E16AC1
6 changed files with 161 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
main
*.db

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Nothing Mail
A temporary email service

129
cmd/mail_server/main.go Normal file
View 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
View 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
View 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
View 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)
);