13 stateNew state = iota // Before EHOL.
20 type connection struct {
28 mailFrom *mail.Address
32 func AcceptConnection(netConn net.Conn, server Server) error {
34 tp: textproto.NewConn(netConn),
35 remoteAddr: netConn.RemoteAddr(),
41 conn.writeReply(250, fmt.Sprintf("%s ESMTP [%s] mailpopbox", server.Name(), netConn.LocalAddr().String()))
44 conn.line, err = conn.tp.ReadLine()
46 conn.writeReply(500, "line too long")
51 if _, err = fmt.Sscanf(conn.line, "%s", &cmd); err != nil {
75 conn.writeReply(550, "access denied")
79 conn.writeReply(250, "https://tools.ietf.org/html/rfc5321")
81 conn.writeReply(500, "unrecognized command")
88 func (conn *connection) writeReply(code int, msg string) {
90 conn.tp.PrintfLine("%d %s", code, msg)
92 conn.tp.PrintfLine("%d", code)
96 func (conn *connection) writeOK() {
97 conn.writeReply(250, "OK")
100 func (conn *connection) writeBadSyntax() {
101 conn.writeReply(501, "syntax error")
104 func (conn *connection) writeBadSequence() {
105 conn.writeReply(503, "bad sequence of commands")
108 func (conn *connection) doEHLO() {
112 _, err := fmt.Sscanf(conn.line, "%s %s", &cmd, &conn.ehlo)
114 conn.writeBadSyntax()
118 conn.writeReply(250, fmt.Sprintf("Hello %s, I am glad to meet you", conn.ehlo))
120 conn.state = stateInitial
123 func (conn *connection) doMAIL() {
124 if conn.state != stateInitial {
125 conn.writeBadSequence()
130 _, err := fmt.Sscanf(conn.line, "MAIL FROM:%s", &mailFrom)
132 conn.writeBadSyntax()
136 conn.mailFrom, err = mail.ParseAddress(mailFrom)
138 conn.writeBadSyntax()
142 conn.state = stateMail
146 func (conn *connection) doRCPT() {
147 if conn.state != stateMail && conn.state != stateRecipient {
148 conn.writeBadSequence()
153 _, err := fmt.Sscanf(conn.line, "RCPT TO:%s", &rcptTo)
155 conn.writeBadSyntax()
159 address, err := mail.ParseAddress(rcptTo)
161 conn.writeBadSyntax()
164 conn.rcptTo = append(conn.rcptTo, *address)
166 conn.state = stateRecipient
170 func (conn *connection) doDATA() {
171 if conn.state != stateRecipient {
172 conn.writeBadSequence()
176 conn.writeReply(354, "Start mail input; end with <CRLF>.<CRLF>")
178 data, err := conn.tp.ReadDotBytes()
181 conn.writeReply(552, "transaction failed")
185 fmt.Println(string(data))
187 conn.state = stateInitial
191 func (conn *connection) doVRFY() {
194 func (conn *connection) doRSET() {
195 conn.state = stateInitial
200 func (conn *connection) resetBuffers() {
202 conn.rcptTo = make([]mail.Address, 0)