conn.ok("")
case "RSET":
conn.doRSET()
+ case "UIDL":
+ conn.doUIDL()
default:
conn.log.Error("unknown command")
conn.err("unknown command")
conn.ok("")
}
+func (conn *connection) doUIDL() {
+ if conn.state != stateTxn {
+ conn.err(errStateTxn)
+ return
+ }
+
+ msgs, err := conn.mb.ListMessages()
+ if err != nil {
+ conn.log.Error("failed to list messages", zap.Error(err))
+ conn.err(err.Error())
+ return
+ }
+
+ conn.ok("unique-id listing")
+ for _, msg := range msgs {
+ if msg.Deleted() {
+ continue
+ }
+ conn.tp.PrintfLine("%d %s", msg.ID(), msg.UniqueID())
+ }
+ conn.tp.PrintfLine(".")
+}
+
func (conn *connection) getRequestedMessage() Message {
var cmd string
var idx int
body string
}
+func (m *testMessage) UniqueID() string {
+ return fmt.Sprintf("%p", m)
+}
+
func (m *testMessage) ID() int {
return m.id
}
{"STAT", responseOK},
{"RETR 1", func(t testing.TB, tp *textproto.Conn) string {
responseOK(t, tp)
+ if t.Failed() {
+ return ""
+ }
+
resp, err := tp.ReadDotLines()
if err != nil {
t.Error(err)
}},
{"RETR 2", func(t testing.TB, tp *textproto.Conn) string {
responseOK(t, tp)
+ if t.Failed() {
+ return ""
+ }
+
resp, err := tp.ReadDotLines()
if err != nil {
t.Error(err)
{"QUIT", responseOK},
})
}
+
+func TestUidl(t *testing.T) {
+ s := newTestServer()
+ s.mb.msgs[1] = &testMessage{1, 3, false, "abc"}
+ s.mb.msgs[2] = &testMessage{2, 1, true, "Z"}
+ s.mb.msgs[3] = &testMessage{3, 4, false, "test"}
+
+ clientServerTest(t, s, []requestResponse{
+ {"USER u", responseOK},
+ {"PASS p", responseOK},
+ {"UIDL", func(t testing.TB, tp *textproto.Conn) string {
+ responseOK(t, tp)
+ if t.Failed() {
+ return ""
+ }
+
+ resp, err := tp.ReadDotLines()
+ if err != nil {
+ t.Error(err)
+ return ""
+ }
+
+ expected := []string{
+ fmt.Sprintf("1 %p", s.mb.msgs[1]),
+ fmt.Sprintf("3 %p", s.mb.msgs[3]),
+ }
+ if !reflect.DeepEqual(resp, expected) {
+ t.Errorf("Expected %v, got %v", expected, resp)
+ }
+
+ return ""
+ }},
+ {"QUIT", responseOK},
+ })
+}