Skip to content

Commit 4a53464

Browse files
committed
fix(imap): fix parsing of optional date in APPEND command
The parser failed when the optional date was provided Refs: #948
1 parent ab289d8 commit 4a53464

2 files changed

Lines changed: 71 additions & 6 deletions

File tree

imap/append.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"bytes"
66
"encoding/base64"
77
"fmt"
8-
log "github.com/sirupsen/logrus"
98
"io"
109
"mime/multipart"
1110
"mime/quotedprintable"
@@ -15,6 +14,8 @@ import (
1514
"net/textproto"
1615
"strings"
1716
"time"
17+
18+
log "github.com/sirupsen/logrus"
1819
)
1920

2021
type AppendOptions struct {
@@ -36,7 +37,7 @@ func (c *conn) handleAppend(tag string, d *Decoder) error {
3637
}
3738
d.SP()
3839

39-
opt := AppendOptions{}
40+
opt := AppendOptions{Date: time.Now()}
4041
if d.IsList() {
4142
err = d.List(func() error {
4243
f, err := d.ReadFlag()
@@ -52,6 +53,14 @@ func (c *conn) handleAppend(tag string, d *Decoder) error {
5253
d.SP()
5354
}
5455

56+
if d.is("\"") {
57+
opt.Date, err = d.Date()
58+
if err != nil {
59+
return err
60+
}
61+
d.SP()
62+
}
63+
5564
if err := d.expect("{"); err != nil {
5665
return err
5766
}
@@ -63,7 +72,7 @@ func (c *conn) handleAppend(tag string, d *Decoder) error {
6372
return err
6473
}
6574

66-
c.tpc.PrintfLine("+ Ready for literal data")
75+
_ = c.tpc.PrintfLine("+ Ready for literal data")
6776

6877
r := io.LimitReader(c.tpc.R, size)
6978
data, err := io.ReadAll(r)

imap/append_test.go

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package imap_test
22

33
import (
44
"fmt"
5-
"github.com/stretchr/testify/require"
65
"mokapi/imap"
76
"mokapi/imap/imaptest"
87
"mokapi/smtp"
98
"mokapi/try"
109
"testing"
10+
"time"
11+
12+
"github.com/stretchr/testify/require"
1113
)
1214

1315
func TestAppend(t *testing.T) {
@@ -37,7 +39,7 @@ func TestAppend(t *testing.T) {
3739
}()
3840

3941
c := imap.NewClient(fmt.Sprintf("localhost:%v", p))
40-
defer c.Close()
42+
defer func() { _ = c.Close() }()
4143

4244
_, err := c.Dial()
4345
require.NoError(t, err)
@@ -73,6 +75,7 @@ func TestAppend_Flags(t *testing.T) {
7375
handler := &imaptest.Handler{
7476
AppendFunc: func(mailbox string, msg *smtp.Message, opt imap.AppendOptions) error {
7577
require.Equal(t, []imap.Flag{imap.FlagSeen}, opt.Flags)
78+
require.Greater(t, opt.Date, time.Time{})
7679
return nil
7780
},
7881
}
@@ -89,7 +92,7 @@ func TestAppend_Flags(t *testing.T) {
8992
}()
9093

9194
c := imap.NewClient(fmt.Sprintf("localhost:%v", p))
92-
defer c.Close()
95+
defer func() { _ = c.Close() }()
9396

9497
_, err := c.Dial()
9598
require.NoError(t, err)
@@ -119,3 +122,56 @@ func TestAppend_Flags(t *testing.T) {
119122
require.Equal(t, "A003 OK APPEND completed", res2)
120123

121124
}
125+
126+
func TestAppend_Flags_And_Time(t *testing.T) {
127+
128+
handler := &imaptest.Handler{
129+
AppendFunc: func(mailbox string, msg *smtp.Message, opt imap.AppendOptions) error {
130+
require.Equal(t, []imap.Flag{imap.FlagSeen}, opt.Flags)
131+
require.Equal(t, "2026-04-26T14:20:31+02:00", opt.Date.Format(time.RFC3339))
132+
return nil
133+
},
134+
}
135+
136+
p := try.GetFreePort()
137+
s := &imap.Server{
138+
Addr: fmt.Sprintf(":%v", p),
139+
Handler: handler,
140+
}
141+
defer s.Close()
142+
go func() {
143+
err := s.ListenAndServe()
144+
require.ErrorIs(t, err, imap.ErrServerClosed)
145+
}()
146+
147+
c := imap.NewClient(fmt.Sprintf("localhost:%v", p))
148+
defer func() { _ = c.Close() }()
149+
150+
_, err := c.Dial()
151+
require.NoError(t, err)
152+
153+
err = c.PlainAuth("", "", "")
154+
require.NoError(t, err)
155+
156+
res, err := c.SendRaw("A003 APPEND Sent (\\Seen) \"26-Apr-2026 14:20:31 +0200\" {310}")
157+
require.NoError(t, err)
158+
require.Equal(t, "+ Ready for literal data", res)
159+
160+
request := []string{
161+
"Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)",
162+
"From: Fred Foobar <foobar@Blurdybloop.COM>",
163+
"Subject: afternoon meeting",
164+
"To: mooch@owatagu.siam.edu",
165+
"Message-Id: <B27397-0100000@Blurdybloop.COM>",
166+
"MIME-Version: 1.0",
167+
"Content-Type: TEXT/PLAIN; CHARSET=US-ASCII",
168+
"",
169+
"Hello Joe, do you think we can meet at 3:30 tomorrow?",
170+
"",
171+
}
172+
173+
res2, err := c.SendRawLines(request)
174+
require.NoError(t, err)
175+
require.Equal(t, "A003 OK APPEND completed", res2)
176+
177+
}

0 commit comments

Comments
 (0)