From 298ccb9a95bca9af93eca335214ac4bf452af7c1 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Thu, 16 Jan 2025 11:16:03 +0800 Subject: IMAP: Add CAPABILITY, and a stub for AUTHENTICATE --- serve_imap.go | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/serve_imap.go b/serve_imap.go index 86a2db9..58da901 100644 --- a/serve_imap.go +++ b/serve_imap.go @@ -3,10 +3,12 @@ package main import ( "bufio" "context" - "crypto/tls" "fmt" + "crypto/tls" + "encoding/base64" "io" "net" + "strings" "github.com/jackc/pgx/v5/pgxpool" "go.lindenii.runxiyu.org/lindenii-common/clog" @@ -20,9 +22,11 @@ type imap_recv_session struct { db *pgxpool.Pool } +const IMAP_CAPABILITIES = "CAPABILITY IMAP4rev2 AUTH=PLAIN" + 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("* OK [CAPABILITY IMAP4rev2 AUTH=PLAIN] " + VERSION + "\r\n") + _, _ = session.buf_conn.WriteString("* OK [" + IMAP_CAPABILITIES + "] " + VERSION + "\r\n") _ = session.buf_conn.Flush() for { @@ -39,7 +43,38 @@ func (session *imap_recv_session) handle(ctx context.Context) error { _ = session.buf_conn.Flush() continue } - fmt.Printf("received tag=%s, cmd=%s, param=%s\n", tag, cmd, param) + fmt.Printf("tag=%#v, cmd=%#v, param=%#v\n", tag, cmd, param) + switch_cmd: + switch cmd { + case "CAPABILITY": + _, _ = session.buf_conn.WriteString("* CAPABILITY " + IMAP_CAPABILITIES + "\r\n") + _, _ = session.buf_conn.WriteString(tag + " OK CAPABILITY completed\r\n") + _ = session.buf_conn.Flush() + case "AUTHENTICATE": + space_that_ends_the_method := strings.IndexByte(param, ' ') + method := param[:space_that_ends_the_method] + switch method { + case "PLAIN": + argument_base64 := param[space_that_ends_the_method+1:] + if strings.IndexByte(argument_base64, ' ') != -1 { + _, _ = session.buf_conn.WriteString(tag + " TODO too many parameters\r\n") + _ = session.buf_conn.Flush() + break switch_cmd + } + argument := make([]byte, base64.StdEncoding.DecodedLen(len(argument_base64))) + _, err := base64.StdEncoding.Decode(argument, []byte(argument_base64)); + if err != nil { + _, _ = session.buf_conn.WriteString(tag + " TODO cannot decode base64\r\n") + _ = session.buf_conn.Flush() + break switch_cmd + } + fmt.Printf("argumetn=%#v\n", string(argument)) + default: + _, _ = session.buf_conn.WriteString(line + " TODO i don't know this authentication method\r\n") + _ = session.buf_conn.Flush() + break switch_cmd + } + } } } -- cgit v1.2.3