From 00f3cb9fb48cfb9768b695bd0d9eb8367ad84782 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Thu, 2 Jan 2025 19:30:51 +0000 Subject: Deliver to inbox --- config.go | 29 ++++++++++++++++++++++++++++- errors.go | 9 +++++++++ incoming.go | 20 ++++++++++++++++++-- maild.scfg | 1 + main.go | 15 ++++++--------- mta_recv.go | 10 +++++++--- 6 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 errors.go diff --git a/config.go b/config.go index 1a89987..c4b5579 100644 --- a/config.go +++ b/config.go @@ -1,7 +1,34 @@ package main +import ( + "bufio" + "go.lindenii.runxiyu.org/lindenii-common/scfg" + "os" + "sync" +) + var config struct { Server_name string `scfg:"server_name"` + Inbox_path string `scfg:"inbox_path"` } +var config_mutex sync.RWMutex -// TODO: edit scfg to require fields to exist unless explicitly marked optional. +func load_config(path string) error { + config_file, err := os.Open(path) + if err != nil { + return err + } + decoder := scfg.NewDecoder(bufio.NewReader(config_file)) + if func() error { + config_mutex.Lock() + defer config_mutex.Unlock() + err = decoder.Decode(&config) + if err != nil { + return err + } + return nil + }() != nil { + return err + } + return nil +} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..0d6a8d7 --- /dev/null +++ b/errors.go @@ -0,0 +1,9 @@ +package main + +import ( + "errors" +) + +var ( + err_deliver_write = errors.New("unable to write to filesystem while attempting to deliver message") +) diff --git a/incoming.go b/incoming.go index f915ac0..169bde5 100644 --- a/incoming.go +++ b/incoming.go @@ -1,12 +1,28 @@ package main -import "go.lindenii.runxiyu.org/lindenii-common/clog" +import ( + "go.lindenii.runxiyu.org/lindenii-common/clog" + "os" + "path" + "time" +) -func deliver_incoming(envelope_from string, envelope_recipients []string, data []byte) { +func deliver_incoming(envelope_from string, envelope_recipients []string, data []byte) error { clog.Debug( "incoming_mail", "envelope_from", envelope_from, "envelope_recipients", envelope_recipients, "data", string(data), ) + t := time.Now() + fd, err := os.OpenFile(path.Join(config.Inbox_path, envelope_from+" "+t.Format(time.RFC3339Nano)+".eml"), os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0660) // TODO: vulnerability + if err != nil { + // TODO: handle fs.ErrExist + return err_deliver_write + } + _, err = fd.Write(data) + if err != nil { + return err_deliver_write + } + return nil } diff --git a/maild.scfg b/maild.scfg index 24f7b84..84c613e 100644 --- a/maild.scfg +++ b/maild.scfg @@ -1 +1,2 @@ server_name mail.andrewyu.org +inbox_path /home/runxiyu/inbox diff --git a/main.go b/main.go index 8d6b797..052deec 100644 --- a/main.go +++ b/main.go @@ -3,21 +3,18 @@ package main import ( "bufio" "net" - "os" + "flag" + "errors" + "io" "go.lindenii.runxiyu.org/lindenii-common/clog" - "go.lindenii.runxiyu.org/lindenii-common/scfg" ) const VERSION = "lindenii-maild v0.0.0" func main() { - config_file, err := os.Open("maild.scfg") - if err != nil { - panic(err) - } - - err = scfg.NewDecoder(bufio.NewReader(config_file)).Decode(&config) + config_path := flag.String("config", "maild.scfg", "path to configuration file") + err := load_config(*config_path) if err != nil { panic(err) } @@ -36,7 +33,7 @@ func main() { go func() { err := handle_incoming_server_connection(bufio.NewReader(conn), bufio.NewWriter(conn)) - if err != nil { + if err != nil && !errors.Is(err, io.EOF) { clog.Error("connection handler returned error", "err", err) } }() diff --git a/mta_recv.go b/mta_recv.go index 2b4679a..c77c46d 100644 --- a/mta_recv.go +++ b/mta_recv.go @@ -129,10 +129,14 @@ func handle_incoming_server_connection(reader *bufio.Reader, writer *bufio.Write if err != nil { return err } - deliver_incoming(current_mail_from, current_rcpt_to, current_data) - server_state = server_state_helo - _, _ = writer.WriteString("250 2.0.0 Ok: Accepted\r\n") + err = deliver_incoming(current_mail_from, current_rcpt_to, current_data) + if err == nil { + _, _ = writer.WriteString("250 2.0.0 Ok: Accepted\r\n") + } else { + _, _ = writer.WriteString("500 2.0.0 Funderscore\r\n") + } _ = writer.Flush() + server_state = server_state_helo case "QUIT": _, _ = writer.WriteString("221 2.0.0 Bye\r\n") _ = writer.Flush() -- cgit v1.2.3