aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go1
-rw-r--r--serve_imap.go79
2 files changed, 80 insertions, 0 deletions
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")
+ }
+ }()
+ }
+}