13 stateAuth state = iota
19 errStateAuth = "not in AUTHORIZATION"
20 errStateTxn = "not in TRANSACTION"
21 errSyntax = "syntax error"
24 type connection struct {
37 func AcceptConnection(netConn net.Conn, po PostOffice) {
40 tp: textproto.NewConn(netConn),
45 conn.ok(fmt.Sprintf("POP3 (mailpopbox) server %s", po.Name()))
48 conn.line, err = conn.tp.ReadLine()
50 conn.err("did't catch that")
55 if _, err := fmt.Sscanf(conn.line, "%s", &cmd); err != nil {
56 conn.err("invalid command")
81 conn.err("unknown command")
86 func (conn *connection) ok(msg string) {
90 conn.tp.PrintfLine("+OK%s", msg)
93 func (conn *connection) err(msg string) {
96 conn.tp.PrintfLine("-ERR%s", msg)
100 func (conn *connection) doQUIT() {
101 defer conn.tp.Close()
104 err := conn.mb.Close()
106 conn.err("failed to remove some messages")
113 func (conn *connection) doUSER() {
114 if conn.state != stateAuth {
115 conn.err(errStateAuth)
119 if _, err := fmt.Sscanf(conn.line, "USER %s", &conn.user); err != nil {
127 func (conn *connection) doPASS() {
128 if conn.state != stateAuth {
129 conn.err(errStateAuth)
133 if len(conn.user) == 0 {
138 pass := strings.TrimPrefix(conn.line, "PASS ")
139 if mbox, err := conn.po.OpenMailbox(conn.user, pass); err == nil {
140 conn.state = stateTxn
144 conn.err(err.Error())
148 func (conn *connection) doSTAT() {
149 if conn.state != stateTxn {
150 conn.err(errStateTxn)
155 func (conn *connection) doLIST() {
156 if conn.state != stateTxn {
157 conn.err(errStateTxn)
162 func (conn *connection) doRETR() {
163 if conn.state != stateTxn {
164 conn.err(errStateTxn)
169 func (conn *connection) doDELE() {
170 if conn.state != stateTxn {
171 conn.err(errStateTxn)
176 func (conn *connection) doRSET() {
177 if conn.state != stateTxn {
178 conn.err(errStateTxn)