From 807e74c8cb04b834e82d73da036ca9585b559201 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Wed, 15 Jan 2025 01:48:18 +0800 Subject: Add an IMAP stub --- main.go | 1 + serve_imap.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 serve_imap.go diff --git a/main.go b/main.go index 51540f9..60082da 100644 --- a/main.go +++ b/main.go @@ -18,6 +18,7 @@ func main() { } go serve_mx() + go serve_imap() deadlock := make(chan struct{}) deadlock <- struct{}{} diff --git a/serve_imap.go b/serve_imap.go new file mode 100644 index 0000000..742bb0f --- /dev/null +++ b/serve_imap.go @@ -0,0 +1,79 @@ +package main + +import ( + "bufio" + "context" + "crypto/tls" + "net" + + "github.com/jackc/pgx/v5/pgxpool" + "go.lindenii.runxiyu.org/lindenii-common/clog" +) + +type imap_server_state_t uint + +const ( + imap_server_state_begin imap_server_state_t = iota + imap_server_state_helo + imap_server_state_mail + imap_server_state_rcpt +) + +type imap_recv_session struct { + buf_conn *bufio.ReadWriter + net_conn net.Conn + tls_conn *tls.Conn + my_server_name string + db *pgxpool.Pool +} + +func (session *imap_recv_session) handle(ctx context.Context) error { + session.buf_conn = bufio.NewReadWriter(bufio.NewReader(session.net_conn), bufio.NewWriter(session.net_conn)) + session.buf_conn.WriteString("Not implemented\r\n") + session.buf_conn.Flush() + return nil +} + +func imap_new_session(ctx context.Context, net_conn net.Conn) error { + session := imap_recv_session{ + net_conn: net_conn, + } + return session.handle(ctx) +} + +func serve_imap() { + var imap_net, imap_addr string + config_consistent_run(func() { + imap_net = config.IMAP.Net + imap_addr = config.IMAP.Addr + }) + listener, err := net.Listen(imap_net, imap_addr) + if err != nil { + clog.Fatal(1, "IMAP: Cannot listen: "+err.Error()) + } + defer listener.Close() + clog.Info("IMAP: Listening via " + imap_net + " on " + imap_addr) + + for { + conn, err := listener.Accept() + if err != nil { + clog.Error("IMAP: Cannot accept connection: " + err.Error()) + } + clog.Info("IMAP: Accepted connection from " + conn.RemoteAddr().String()) + + go func() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err := imap_new_session(ctx, conn) + if err != nil { + if err == err_connection_handler_eof { + clog.Info("IMAP: Connection for " + conn.RemoteAddr().String() + " closed with EOF") + } else { + clog.Error("IMAP: Connection handler for " + conn.RemoteAddr().String() + " returned error: " + err.Error()) + } + } else { + clog.Info("IMAP: Connection for " + conn.RemoteAddr().String() + " closed gracefully") + } + }() + } +} -- cgit v1.2.3