diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index 9c5bcaff..fa69ea1f 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -451,6 +451,65 @@ func TestBridge_User_DropConn_NoBadEvent(t *testing.T) { }, server.WithListener(dropListener)) } +func TestBridge_User_UpdateDraft(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a bridge user. + _, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Initially sync the user. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userLoginAndSync(ctx, t, bridge, "user", password) + }) + + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + user, err := c.GetUser(ctx) + require.NoError(t, err) + + addrs, err := c.GetAddresses(ctx) + require.NoError(t, err) + + salts, err := c.GetSalts(ctx) + require.NoError(t, err) + + keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) + require.NoError(t, err) + + _, addrKRs, err := proton.Unlock(user, addrs, keyPass, async.NoopPanicHandler{}) + require.NoError(t, err) + + // Create a draft (generating a "create draft message" event). + draft, err := c.CreateDraft(ctx, addrKRs[addrs[0].ID], proton.CreateDraftReq{ + Message: proton.DraftTemplate{ + Subject: "subject", + Sender: &mail.Address{Name: "sender", Address: addrs[0].Email}, + Body: "body", + MIMEType: rfc822.TextPlain, + }, + }) + require.NoError(t, err) + require.Empty(t, draft.ReplyTos) + + // Process those events + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + }) + + // Update the draft (generating an "update draft message" event). + draft2, err := c.UpdateDraft(ctx, draft.ID, addrKRs[addrs[0].ID], proton.UpdateDraftReq{ + Message: proton.DraftTemplate{ + Subject: "subject 2", + Sender: &mail.Address{Name: "sender", Address: addrs[0].Email}, + Body: "body 2", + MIMEType: rfc822.TextPlain, + }, + }) + require.NoError(t, err) + require.Empty(t, draft2.ReplyTos) + }) + }) +} + func TestBridge_User_UpdateDraftAndCreateOtherMessage(t *testing.T) { withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { // Create a bridge user. diff --git a/pkg/message/build.go b/pkg/message/build.go index b67503e2..5e7e44bb 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -441,7 +441,7 @@ func getMessageHeader(msg proton.Message, opts JobOptions) message.Header { hdr.Set("From", msg.Sender.String()) } - if len(msg.ReplyTos) > 0 { + if len(msg.ReplyTos) > 0 && !msg.IsDraft() { if !(len(msg.ReplyTos) == 1 && addressEmpty(msg.ReplyTos[0])) { hdr.Set("Reply-To", toAddressList(msg.ReplyTos)) } diff --git a/tests/bdd_test.go b/tests/bdd_test.go index cad4a1fc..d854fb12 100644 --- a/tests/bdd_test.go +++ b/tests/bdd_test.go @@ -209,6 +209,7 @@ func TestFeatures(testingT *testing.T) { ctx.Step(`^IMAP client "([^"]*)" appends "([^"]*)" to "([^"]*)"$`, s.imapClientAppendsToMailbox) ctx.Step(`^IMAP clients "([^"]*)" and "([^"]*)" move message with subject "([^"]*)" of "([^"]*)" to "([^"]*)" by ([^"]*) ([^"]*) ([^"]*)`, s.imapClientsMoveMessageWithSubjectUserFromToByOrderedOperations) ctx.Step(`^IMAP client "([^"]*)" sees header "([^"]*)" in message with subject "([^"]*)" in "([^"]*)"$`, s.imapClientSeesHeaderInMessageWithSubject) + ctx.Step(`^IMAP client "([^"]*)" does not see header "([^"]*)" in message with subject "([^"]*)" in "([^"]*)"$`, s.imapClientDoesNotSeeHeaderInMessageWithSubject) // ==== SMTP ==== ctx.Step(`^user "([^"]*)" connects SMTP client "([^"]*)"$`, s.userConnectsSMTPClient) diff --git a/tests/features/imap/message/drafts.feature b/tests/features/imap/message/drafts.feature index e4644d43..2c8e6ae7 100644 --- a/tests/features/imap/message/drafts.feature +++ b/tests/features/imap/message/drafts.feature @@ -34,6 +34,7 @@ Feature: IMAP Draft messages | to | subject | body | | someone@example.com | Basic Draft | This is a draft, but longer | And IMAP client "1" eventually sees 1 messages in "Drafts" + And IMAP client "1" does not see header "Reply-To" in message with subject "Basic Draft" in "Drafts" Scenario: Draft edited remotely When the following fields were changed in draft 1 for address "[user:user]@[domain]" of account "[user:user]": @@ -43,6 +44,7 @@ Feature: IMAP Draft messages | to | subject | body | | someone@example.com | Basic Draft | This is a draft body, but longer | And IMAP client "1" eventually sees 1 messages in "Drafts" + And IMAP client "1" does not see header "Reply-To" in message with subject "Basic Draft" in "Drafts" Scenario: Draft moved to trash remotely When draft 1 for address "[user:user]@[domain]" of account "[user:user]" was moved to trash diff --git a/tests/features/smtp/send/send_reply.feature b/tests/features/smtp/send/send_reply.feature index 47f9acf4..a3c17143 100644 --- a/tests/features/smtp/send/send_reply.feature +++ b/tests/features/smtp/send/send_reply.feature @@ -5,9 +5,9 @@ Feature: SMTP send reply And there exists an account with username "[user:user2]" and password "password" And bridge starts And the user logs in with username "[user:user1]" and password "password" + And user "[user:user1]" finishes syncing And user "[user:user1]" connects and authenticates SMTP client "1" And user "[user:user1]" connects and authenticates IMAP client "1" - And user "[user:user1]" finishes syncing @long-black Scenario: Reply with In-Reply-To but no References @@ -33,8 +33,8 @@ Feature: SMTP send reply And user "[user:user2]" finishes syncing # User2 receive the message. Then IMAP client "2" eventually sees the following messages in "INBOX": - | from | subject | message-id | - | [user:user1]@[domain] | Please Reply | | + | from | subject | message-id | reply-to | + | [user:user1]@[domain] | Please Reply | | [user:user1]@[domain] | # User2 reply to it. When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": """ @@ -53,8 +53,8 @@ Feature: SMTP send reply | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | # User1 receive the reply.| And IMAP client "1" eventually sees the following messages in "INBOX": - | from | subject | body | in-reply-to | references | - | [user:user2]@[domain] | FW - Please Reply | Heya | | | + | from | subject | body | in-reply-to | references | reply-to | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | [user:user2]@[domain] | @long-black Scenario: Reply with References but no In-Reply-To @@ -80,8 +80,8 @@ Feature: SMTP send reply And user "[user:user2]" finishes syncing # User2 receive the message. Then IMAP client "2" eventually sees the following messages in "INBOX": - | from | subject | message-id | - | [user:user1]@[domain] | Please Reply | | + | from | subject | message-id | reply-to | + | [user:user1]@[domain] | Please Reply | | [user:user1]@[domain] | # User2 reply to it. When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": """ @@ -100,8 +100,8 @@ Feature: SMTP send reply | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | # User1 receive the reply.| And IMAP client "1" eventually sees the following messages in "INBOX": - | from | subject | body | in-reply-to | references | - | [user:user2]@[domain] | FW - Please Reply | Heya | | | + | from | subject | body | in-reply-to | references | reply-to | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | [user:user2]@[domain] | @long-black @@ -128,8 +128,8 @@ Feature: SMTP send reply And user "[user:user2]" finishes syncing # User2 receive the message. Then IMAP client "2" eventually sees the following messages in "INBOX": - | from | subject | message-id | - | [user:user1]@[domain] | Please Reply | | + | from | subject | message-id | reply-to | + | [user:user1]@[domain] | Please Reply | | [user:user1]@[domain] | # User2 reply to it. When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": """ @@ -149,5 +149,5 @@ Feature: SMTP send reply | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | # User1 receive the reply.| And IMAP client "1" eventually sees the following messages in "INBOX": - | from | subject | body | in-reply-to | references | - | [user:user2]@[domain] | FW - Please Reply | Heya | | | \ No newline at end of file + | from | subject | body | in-reply-to | references | reply-to | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | [user:user2]@[domain] | \ No newline at end of file diff --git a/tests/imap_test.go b/tests/imap_test.go index 8cae5707..155b6e37 100644 --- a/tests/imap_test.go +++ b/tests/imap_test.go @@ -297,7 +297,6 @@ func (s *scenario) imapClientSeesTheFollowingMessagesInMailbox(clientID, mailbox if err != nil { return err } - return matchMessages(haveMessages, wantMessages) } @@ -575,6 +574,14 @@ func (s *scenario) imapClientSeesHeaderInMessageWithSubject(clientID, headerStri return fmt.Errorf("could not find message with given subject '%v'", subject) } +func (s *scenario) imapClientDoesNotSeeHeaderInMessageWithSubject(clientID, headerString, subject, mailbox string) error { + err := s.imapClientSeesHeaderInMessageWithSubject(clientID, headerString, subject, mailbox) + if err == nil { + return fmt.Errorf("message header contains '%v'", headerString) + } + return nil +} + func clientList(client *client.Client) []*imap.MailboxInfo { resCh := make(chan *imap.MailboxInfo) diff --git a/tests/types_test.go b/tests/types_test.go index c59b13dc..183637d6 100644 --- a/tests/types_test.go +++ b/tests/types_test.go @@ -43,10 +43,11 @@ type Message struct { MessageID string `bdd:"message-id"` Date string `bdd:"date"` - From string `bdd:"from"` - To string `bdd:"to"` - CC string `bdd:"cc"` - BCC string `bdd:"bcc"` + From string `bdd:"from"` + To string `bdd:"to"` + CC string `bdd:"cc"` + BCC string `bdd:"bcc"` + ReplyTo string `bdd:"reply-to"` Unread bool `bdd:"unread"` Deleted bool `bdd:"deleted"` @@ -158,6 +159,10 @@ func newMessageFromIMAP(msg *imap.Message) Message { message.BCC = msg.Envelope.Bcc[0].Address() } + if len(msg.Envelope.ReplyTo) > 0 { + message.ReplyTo = msg.Envelope.ReplyTo[0].Address() + } + return message }