aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-01-16 11:16:03 +0800
committerRunxi Yu <me@runxiyu.org>2025-01-16 11:16:03 +0800
commit298ccb9a95bca9af93eca335214ac4bf452af7c1 (patch)
treee1850e7e29f0a76c25602a6640af85b40bca6a33
parentRemove imap_server_state (diff)
downloadmaild-298ccb9a95bca9af93eca335214ac4bf452af7c1.tar.gz
maild-298ccb9a95bca9af93eca335214ac4bf452af7c1.tar.zst
maild-298ccb9a95bca9af93eca335214ac4bf452af7c1.zip
IMAP: Add CAPABILITY, and a stub for AUTHENTICATE
-rw-r--r--serve_imap.go41
1 files 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
+ }
+ }
}
}