62 lines
2.3 KiB
Go
62 lines
2.3 KiB
Go
package services
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func NewIMAPHandler(log LoggerFunc) Handler {
|
|
return func(conn net.Conn) {
|
|
defer conn.Close()
|
|
remote := conn.RemoteAddr().String()
|
|
_, _ = conn.Write([]byte("* OK IMAP4rev1 Service Ready\r\n"))
|
|
conn.SetDeadline(time.Now().Add(2 * time.Minute))
|
|
scanner := bufio.NewScanner(conn)
|
|
selected := false
|
|
mailbox := "INBOX"
|
|
for scanner.Scan() {
|
|
line := strings.TrimSpace(scanner.Text())
|
|
if line == "" { continue }
|
|
parts := strings.Fields(line)
|
|
if len(parts) < 2 { continue }
|
|
tag := parts[0]
|
|
cmd := strings.ToUpper(parts[1])
|
|
switch cmd {
|
|
case "LOGIN":
|
|
if len(parts) >= 4 {
|
|
user := strings.Trim(parts[2], "\"")
|
|
pass := strings.Trim(parts[3], "\"")
|
|
log(Record{Timestamp: Now(), RemoteAddr: remoteIP(remote), RemotePort: remotePort(remote), Service: "imap", Details: map[string]string{"event":"login_attempt","username":user,"password":pass}})
|
|
}
|
|
_, _ = conn.Write([]byte(tag + " OK LOGIN completed\r\n"))
|
|
case "CAPABILITY":
|
|
_, _ = conn.Write([]byte("* CAPABILITY IMAP4rev1 AUTH=PLAIN IDLE\r\n"))
|
|
_, _ = conn.Write([]byte(tag + " OK CAPABILITY completed\r\n"))
|
|
case "NOOP":
|
|
_, _ = conn.Write([]byte(tag + " OK NOOP completed\r\n"))
|
|
case "SELECT", "EXAMINE":
|
|
if len(parts) >= 3 { mailbox = strings.Trim(parts[2], "\"") }
|
|
selected = true
|
|
// fake mailbox with 2 messages
|
|
_, _ = conn.Write([]byte("* 2 EXISTS\r\n"))
|
|
_, _ = conn.Write([]byte("* OK [UIDVALIDITY 1] UIDs valid\r\n"))
|
|
_, _ = conn.Write([]byte(tag + " OK [READ-WRITE] SELECT completed (" + mailbox + ")\r\n"))
|
|
log(Record{Timestamp: Now(), RemoteAddr: remoteIP(remote), RemotePort: remotePort(remote), Service: "imap", Details: map[string]string{"event":"select","mailbox":mailbox}})
|
|
case "FETCH":
|
|
if !selected { _, _ = conn.Write([]byte(tag + " BAD No mailbox selected\r\n")); continue }
|
|
// minimal fake fetch
|
|
_, _ = conn.Write([]byte("* 1 FETCH (FLAGS (\\Seen) RFC822.SIZE 1234)\r\n"))
|
|
_, _ = conn.Write([]byte(tag + " OK FETCH completed\r\n"))
|
|
case "LOGOUT":
|
|
_, _ = conn.Write([]byte("* BYE IMAP4rev1 Server logging out\r\n"))
|
|
_, _ = conn.Write([]byte(tag + " OK LOGOUT completed\r\n"))
|
|
return
|
|
default:
|
|
_, _ = conn.Write([]byte(tag + " BAD Command not recognized\r\n"))
|
|
}
|
|
}
|
|
}
|
|
}
|