nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: inbucket/inbucket
Pull request #296 (2022-10-02 20:39:41)

backport FROM <> fix from #291 for bug #283


Patch:
diff --git a/pkg/server/smtp/handler.go b/pkg/server/smtp/handler.go
index f9e9a55..baa8722 100644
--- a/pkg/server/smtp/handler.go
+++ b/pkg/server/smtp/handler.go
@@ -58,7 +58,7 @@ const (
 // as quoted pair and in double quoted strings (?i) makes the regex case insensitive, (?:) is
 // non-grouping sub-match.  Accepts empty angle bracket value in options for 'AUTH=<>'.
 var fromRegex = regexp.MustCompile(
-	`(?i)^FROM:\s*<((?:(?:\\>|[^>])+|"[^"]+"@[^>])+)?>( [\w= ]+(?:=<>)?)?$`)
+	`(?i)^FROM:\s*<((?:(?:\\>|[^>])+|"[^"]+"@[^>])+)?>( ([\w= ]|=<>)+)?$`)
 
 func (s State) String() string {
 	switch s {
@@ -619,7 +619,7 @@ func (s *Session) parseCmd(line string) (cmd string, arg string, ok bool) {
 // The leading space is mandatory.
 func (s *Session) parseArgs(arg string) (args map[string]string, ok bool) {
 	args = make(map[string]string)
-	re := regexp.MustCompile(` (\w+)=(\w+)`)
+	re := regexp.MustCompile(` (\w+)=(\w+|<>)`)
 	pm := re.FindAllStringSubmatch(arg, -1)
 	if pm == nil {
 		s.logger.Warn().Msgf("Failed to parse arg string: %q", arg)
diff --git a/shell.nix b/shell.nix
index b73e4f1..f95956f 100644
--- a/shell.nix
+++ b/shell.nix
@@ -11,7 +11,7 @@ stdenv.mkDerivation rec {
     elmPackages.elm-json
     elmPackages.elm-language-server
     elmPackages.elm-test
-    go
+    go_1_18
     golint
     nodejs-16_x
     nodePackages.yarn


Test patch:
diff --git a/pkg/server/smtp/handler_test.go b/pkg/server/smtp/handler_test.go
index 582dc42..2d77bfe 100644
--- a/pkg/server/smtp/handler_test.go
+++ b/pkg/server/smtp/handler_test.go
@@ -197,6 +197,8 @@ func TestReadyState(t *testing.T) {
 		{"RSET", 250},
 		{"MAIL FROM:<bounces@onmicrosoft.com> SIZE=4096 AUTH=<>", 250},
 		{"RSET", 250},
+		{"MAIL FROM:<b@o.com> SIZE=4096 AUTH=<> BODY=7BIT", 250},
+		{"RSET", 250},
 		{"MAIL FROM:<host!host!user/data@foo.com>", 250},
 		{"RSET", 250},
 		{"MAIL FROM:<\"first last\"@space.com>", 250},
Repository: inbucket/inbucket
Pull request #338 (2023-02-15 03:29:39)

file & mem stores should emit delete events on purge
For #332, #181

Signed-off-by: James Hillyerd <james@hillyerd.com>



Patch:
diff --git a/pkg/storage/file/fstore.go b/pkg/storage/file/fstore.go
index d1e6231..be805ed 100644
--- a/pkg/storage/file/fstore.go
+++ b/pkg/storage/file/fstore.go
@@ -11,6 +11,7 @@ import (
 
 	"github.com/inbucket/inbucket/pkg/config"
 	"github.com/inbucket/inbucket/pkg/extension"
+	"github.com/inbucket/inbucket/pkg/message"
 	"github.com/inbucket/inbucket/pkg/storage"
 	"github.com/inbucket/inbucket/pkg/stringutil"
 	"github.com/rs/zerolog/log"
@@ -186,6 +187,17 @@ func (fs *Store) PurgeMessages(mailbox string) error {
 	mb := fs.mbox(mailbox)
 	mb.Lock()
 	defer mb.Unlock()
+
+	// Emit delete events.
+	if !mb.indexLoaded {
+		if err := mb.readIndex(); err != nil {
+			return err
+		}
+	}
+	for _, m := range mb.messages {
+		fs.extHost.Events.AfterMessageDeleted.Emit(message.MakeMetadata(m))
+	}
+
 	return mb.purge()
 }
 
diff --git a/pkg/storage/mem/store.go b/pkg/storage/mem/store.go
index fd1ceae..7c1a78e 100644
--- a/pkg/storage/mem/store.go
+++ b/pkg/storage/mem/store.go
@@ -144,16 +144,25 @@ func (s *Store) MarkSeen(mailbox, id string) error {
 
 // PurgeMessages deletes the contents of a mailbox.
 func (s *Store) PurgeMessages(mailbox string) error {
+	// Grab lock, copy messages, clear, and drop lock.
 	var messages map[string]*Message
 	s.withMailbox(mailbox, true, func(mb *mbox) {
 		messages = mb.messages
 		mb.messages = make(map[string]*Message)
 	})
-	if len(messages) > 0 && s.remove != nil {
+
+	// Process size/quota.
+	if s.remove != nil {
 		for _, m := range messages {
 			s.enforcerRemove(m)
 		}
 	}
+
+	// Emit delete events.
+	for _, m := range messages {
+		s.extHost.Events.AfterMessageDeleted.Emit(message.MakeMetadata(m))
+	}
+
 	return nil
 }
 


Test patch:
diff --git a/pkg/test/storage_suite.go b/pkg/test/storage_suite.go
index fa13260..f22abb2 100644
--- a/pkg/test/storage_suite.go
+++ b/pkg/test/storage_suite.go
@@ -343,16 +343,33 @@ func testDelete(t *testing.T, store storage.Store, extHost *extension.Host) {
 func testPurge(t *testing.T, store storage.Store, extHost *extension.Host) {
 	mailbox := "fred"
 	subjects := []string{"alpha", "bravo", "charlie", "delta", "echo"}
+
+	// Subscribe to events.
+	eventListener := extHost.Events.AfterMessageDeleted.AsyncTestListener(len(subjects))
+
+	// Populate mailbox.
 	for _, subj := range subjects {
 		DeliverToStore(t, store, mailbox, subj, time.Now())
 	}
 	GetAndCountMessages(t, store, mailbox, len(subjects))
+
 	// Purge and verify.
 	err := store.PurgeMessages(mailbox)
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 	GetAndCountMessages(t, store, mailbox, 0)
+
+	// Confirm events emitted.
+	gotEvents := []*event.MessageMetadata{}
+	for range subjects {
+		ev, err := eventListener()
+		if err != nil {
+			t.Error(err)
+			break
+		}
+		gotEvents = append(gotEvents, ev)
+	}
+	assert.Equal(t, len(subjects), len(gotEvents),
+		"expected delete event for each message in mailbox")
 }
 
 // testMsgCap verifies the message cap is enforced.
Repository: inbucket/inbucket
Pull request #348 (2023-02-17 22:58:00)

msghub: Clear deleted messages instead of unlinking
For #332



Patch:
diff --git a/pkg/msghub/hub.go b/pkg/msghub/hub.go
index ba87df2..07bbefe 100644
--- a/pkg/msghub/hub.go
+++ b/pkg/msghub/hub.go
@@ -96,7 +96,7 @@ func (hub *Hub) Delete(mailbox string, id string) {
 		for {
 			if next, ok := p.Next().Value.(event.MessageMetadata); ok {
 				if mailbox == next.Mailbox && id == next.ID {
-					p.Unlink(1) // Remove next node.
+					p.Next().Value = nil
 					break
 				}
 			}


Test patch:
diff --git a/pkg/msghub/hub_test.go b/pkg/msghub/hub_test.go
index d357cf3..8304a6d 100644
--- a/pkg/msghub/hub_test.go
+++ b/pkg/msghub/hub_test.go
@@ -9,6 +9,8 @@ import (
 
 	"github.com/inbucket/inbucket/pkg/extension"
 	"github.com/inbucket/inbucket/pkg/extension/event"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 // testListener implements the Listener interface, mock for unit tests
@@ -302,6 +304,59 @@ func TestHubHistoryReplayWrap(t *testing.T) {
 	}
 }
 
+func TestHubHistoryReplayWrapAfterDelete(t *testing.T) {
+	bufferSize := 5
+
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+	hub := New(bufferSize, extension.NewHost())
+	go hub.Start(ctx)
+
+	waitForMessages := func(n int) {
+		l := newTestListener(n)
+		hub.AddListener(l)
+
+		select {
+		case <-l.done:
+		case <-time.After(time.Second):
+			t.Fatal("Timeout:", l)
+		}
+	}
+
+	// Broadcast more messages than the hub can hold.
+	msgs := make([]event.MessageMetadata, 10)
+	for i := 0; i < len(msgs); i++ {
+		msgs[i] = event.MessageMetadata{
+			Mailbox: "first",
+			ID:      strconv.Itoa(i),
+			Subject: fmt.Sprintf("subj %v", i),
+		}
+		hub.Dispatch(msgs[i])
+	}
+	waitForMessages(bufferSize)
+
+	// Buffer must be configured size.
+	require.Equal(t, bufferSize, hub.history.Len())
+
+	// Delete a message still present in buffer.
+	hub.Delete("first", "7")
+
+	// Broadcast another set of messages.
+	for i := 0; i < len(msgs); i++ {
+		msgs[i] = event.MessageMetadata{
+			Mailbox: "second",
+			ID:      strconv.Itoa(i),
+			Subject: fmt.Sprintf("subj %v", i),
+		}
+		hub.Dispatch(msgs[i])
+	}
+	waitForMessages(bufferSize)
+
+	// Ensure the buffer did not shrink after delete.
+	got := hub.history.Len()
+	assert.Equal(t, bufferSize, got, "got buffer size %d, wanted %d", got, bufferSize)
+}
+
 func TestHubContextCancel(t *testing.T) {
 	ctx, cancel := context.WithCancel(context.Background())
 	hub := New(5, extension.NewHost())
Repository: inbucket/inbucket
Pull request #446 (2023-11-23 00:53:35)

message: Prefer To header for BeforeMessageStored event
Signed-off-by: James Hillyerd <james@hillyerd.com>



Patch:
diff --git a/pkg/message/manager.go b/pkg/message/manager.go
index 25f748b..8388251 100644
--- a/pkg/message/manager.go
+++ b/pkg/message/manager.go
@@ -76,10 +76,12 @@ func (s *StoreManager) Deliver(
 
 	// Process inbound message through extensions.
 	mailboxes := make([]string, len(recipients))
-	toAddrs := make([]mail.Address, len(recipients))
 	for i, recip := range recipients {
 		mailboxes[i] = recip.Mailbox
-		toAddrs[i] = recip.Address
+	}
+	toAddrs := make([]mail.Address, len(toaddr))
+	for i, addr := range toaddr {
+		toAddrs[i] = *addr
 	}
 
 	inbound := &event.InboundMessage{


Test patch:
diff --git a/pkg/message/manager_test.go b/pkg/message/manager_test.go
index fcc2178..65d44c7 100644
--- a/pkg/message/manager_test.go
+++ b/pkg/message/manager_test.go
@@ -106,7 +106,7 @@ func TestDeliverRespectsRecipientPolicy(t *testing.T) {
 	assertMessageCount(t, sm, "u2@example.com", 1)
 }
 
-func TestDeliverEmitsBeforeMessageStoredEvent(t *testing.T) {
+func TestDeliverEmitsBeforeMessageStoredEventToHeader(t *testing.T) {
 	sm, extHost := testStoreManager()
 
 	// Register function to receive event.
@@ -118,7 +118,47 @@ func TestDeliverEmitsBeforeMessageStoredEvent(t *testing.T) {
 			return nil
 		})
 
-	// Deliver a message to trigger event.
+	// Deliver a message to trigger event, To header differs from RCPT TO.
+	origin, _ := sm.AddrPolicy.ParseOrigin("from@example.com")
+	recip1, _ := sm.AddrPolicy.NewRecipient("u1@example.com")
+	recip2, _ := sm.AddrPolicy.NewRecipient("u2@example.com")
+	if err := sm.Deliver(
+		origin,
+		[]*policy.Recipient{recip1, recip2},
+		"Received: xyz\n",
+		[]byte(`From: from@example.com
+To: u1@example.com, u3@external.com
+Subject: tsub
+
+test email`),
+	); err != nil {
+		t.Fatal(err)
+	}
+
+	require.NotNil(t, got, "BeforeMessageStored listener did not receive InboundMessage")
+	assert.Equal(t, []string{"u1@example.com", "u2@example.com"}, got.Mailboxes, "Mailboxes not equal")
+	assert.Equal(t, mail.Address{Name: "", Address: "from@example.com"}, got.From, "From not equal")
+	assert.Equal(t, []mail.Address{
+		{Name: "", Address: "u1@example.com"},
+		{Name: "", Address: "u3@external.com"},
+	}, got.To, "To not equal")
+	assert.Equal(t, "tsub", got.Subject, "Subject not equal")
+	assert.Equal(t, int64(84), got.Size, "Size not equal")
+}
+
+func TestDeliverEmitsBeforeMessageStoredEventRcptTo(t *testing.T) {
+	sm, extHost := testStoreManager()
+
+	// Register function to receive event.
+	var got *event.InboundMessage
+	extHost.Events.BeforeMessageStored.AddListener(
+		"test",
+		func(msg event.InboundMessage) *event.InboundMessage {
+			got = &msg
+			return nil
+		})
+
+	// Deliver a message to trigger event, lacks To header.
 	origin, _ := sm.AddrPolicy.ParseOrigin("from@example.com")
 	recip1, _ := sm.AddrPolicy.NewRecipient("u1@example.com")
 	recip2, _ := sm.AddrPolicy.NewRecipient("u2@example.com")
Repository: inbucket/inbucket
Pull request #464 (2024-01-25 17:51:03)

Rename client.WithOptTransport

coveralls: ## Pull Request Test Coverage Report for [Build 7658490479](https://coveralls.io/builds/65301365)


* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **55.481%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/65301365/badge)](https://coveralls.io/builds/65301365) |
| :-- | --: |
| Change from base [Build 7658428360](https://coveralls.io/builds/65301254): |  0.0% |
| Covered Lines: | 2647 |
| Relevant Lines: | 4771 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/pkg/rest/client/apiv1_client_opts.go b/pkg/rest/client/apiv1_client_opts.go
index 49fd67c..873db93 100644
--- a/pkg/rest/client/apiv1_client_opts.go
+++ b/pkg/rest/client/apiv1_client_opts.go
@@ -29,10 +29,10 @@ func (t transportOption) apply(opts *options) {
 	opts.transport = t.transport
 }
 
-// WithOptTransport sets the transport for the rest client.
+// WithTransport sets the transport for the rest client.
 // Transport specifies the mechanism by which individual
 // HTTP requests are made.
 // If nil, http.DefaultTransport is used.
-func WithOptTransport(transport http.RoundTripper) Option {
+func WithTransport(transport http.RoundTripper) Option {
 	return transportOption{transport}
 }


Test patch:
diff --git a/pkg/rest/client/apiv1_client_test.go b/pkg/rest/client/apiv1_client_test.go
index f7f84e2..3a40143 100644
--- a/pkg/rest/client/apiv1_client_test.go
+++ b/pkg/rest/client/apiv1_client_test.go
@@ -215,7 +215,7 @@ func TestClientV1GetMessageSource(t *testing.T) {
 func TestClientV1WithCustomTransport(t *testing.T) {
 	// Call setup, passing a custom roundtripper and make sure it was used during the request.
 	mockRoundTripper := &mockRoundTripper{ResponseBody: "Custom Transport"}
-	c, router, teardown := setup(client.WithOptTransport(mockRoundTripper))
+	c, router, teardown := setup(client.WithTransport(mockRoundTripper))
 
 	defer teardown()