From c1d5d49126ee72295930924b45326e155ed636f8 Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Wed, 22 Nov 2023 17:28:33 -0800 Subject: [PATCH] event: Use pointers for InboundMessage addresses (#447) * event: Use pointers for InboundMessage addresses To ease conversions to/from MessageMetadata Signed-off-by: James Hillyerd * message: test StoreManager.MailboxForAddress() Signed-off-by: James Hillyerd --------- Signed-off-by: James Hillyerd --- pkg/extension/event/events.go | 4 +- pkg/extension/luahost/bind_inboundmessage.go | 10 ++--- .../luahost/bind_inboundmessage_test.go | 8 ++-- pkg/extension/luahost/lua_test.go | 8 ++-- pkg/message/manager.go | 37 +++++++++---------- pkg/message/manager_test.go | 23 +++++++++--- 6 files changed, 49 insertions(+), 41 deletions(-) diff --git a/pkg/extension/event/events.go b/pkg/extension/event/events.go index 554a8a7..c59f6bf 100644 --- a/pkg/extension/event/events.go +++ b/pkg/extension/event/events.go @@ -14,8 +14,8 @@ type AddressParts struct { // InboundMessage contains the basic header and mailbox data for a message being received. type InboundMessage struct { Mailboxes []string - From mail.Address - To []mail.Address + From *mail.Address + To []*mail.Address Subject string Size int64 } diff --git a/pkg/extension/luahost/bind_inboundmessage.go b/pkg/extension/luahost/bind_inboundmessage.go index 2b3d242..32bdca8 100644 --- a/pkg/extension/luahost/bind_inboundmessage.go +++ b/pkg/extension/luahost/bind_inboundmessage.go @@ -73,12 +73,12 @@ func inboundMessageIndex(ls *lua.LState) int { } ls.Push(lt) case "from": - ls.Push(wrapMailAddress(ls, &m.From)) + ls.Push(wrapMailAddress(ls, m.From)) case "to": lt := &lua.LTable{} for _, v := range m.To { addr := v - lt.Append(wrapMailAddress(ls, &addr)) + lt.Append(wrapMailAddress(ls, addr)) } ls.Push(lt) case "subject": @@ -110,15 +110,15 @@ func inboundMessageNewIndex(ls *lua.LState) int { }) m.Mailboxes = mailboxes case "from": - m.From = *checkMailAddress(ls, 3) + m.From = checkMailAddress(ls, 3) case "to": lt := ls.CheckTable(3) - to := make([]mail.Address, 0, 16) + to := make([]*mail.Address, 0, 16) lt.ForEach(func(k, lv lua.LValue) { if ud, ok := lv.(*lua.LUserData); ok { // TODO should fail if wrong type + test. if entry, ok := unwrapMailAddress(ud); ok { - to = append(to, *entry) + to = append(to, entry) } } }) diff --git a/pkg/extension/luahost/bind_inboundmessage_test.go b/pkg/extension/luahost/bind_inboundmessage_test.go index 715f4b3..657577c 100644 --- a/pkg/extension/luahost/bind_inboundmessage_test.go +++ b/pkg/extension/luahost/bind_inboundmessage_test.go @@ -31,8 +31,8 @@ const LuaInit = ` func TestInboundMessageGetters(t *testing.T) { want := &event.InboundMessage{ Mailboxes: []string{"mb1", "mb2"}, - From: mail.Address{Name: "name1", Address: "addr1"}, - To: []mail.Address{ + From: &mail.Address{Name: "name1", Address: "addr1"}, + To: []*mail.Address{ {Name: "name2", Address: "addr2"}, {Name: "name3", Address: "addr3"}, }, @@ -66,8 +66,8 @@ func TestInboundMessageGetters(t *testing.T) { func TestInboundMessageSetters(t *testing.T) { want := &event.InboundMessage{ Mailboxes: []string{"mb1", "mb2"}, - From: mail.Address{Name: "name1", Address: "addr1"}, - To: []mail.Address{ + From: &mail.Address{Name: "name1", Address: "addr1"}, + To: []*mail.Address{ {Name: "name2", Address: "addr2"}, {Name: "name3", Address: "addr3"}, }, diff --git a/pkg/extension/luahost/lua_test.go b/pkg/extension/luahost/lua_test.go index c72ddd0..dc16937 100644 --- a/pkg/extension/luahost/lua_test.go +++ b/pkg/extension/luahost/lua_test.go @@ -179,8 +179,8 @@ func TestBeforeMessageStored(t *testing.T) { // Event to send. msg := event.InboundMessage{ Mailboxes: []string{"one", "two"}, - From: mail.Address{Name: "From Name", Address: "from@example.com"}, - To: []mail.Address{ + From: &mail.Address{Name: "From Name", Address: "from@example.com"}, + To: []*mail.Address{ {Name: "To1 Name", Address: "to1@example.com"}, {Name: "To2 Name", Address: "to2@example.com"}, }, @@ -233,8 +233,8 @@ func TestBeforeMessageStored(t *testing.T) { // Verify response values. want := &event.InboundMessage{ Mailboxes: []string{"resone", "restwo"}, - From: mail.Address{Name: "Res From", Address: "res@example.com"}, - To: []mail.Address{ + From: &mail.Address{Name: "Res From", Address: "res@example.com"}, + To: []*mail.Address{ {Name: "To1 Res", Address: "res1@example.com"}, {Name: "To2 Res", Address: "res2@example.com"}, }, diff --git a/pkg/message/manager.go b/pkg/message/manager.go index 8388251..25dedf9 100644 --- a/pkg/message/manager.go +++ b/pkg/message/manager.go @@ -57,20 +57,24 @@ func (s *StoreManager) Deliver( if err != nil { return err } - fromaddr, err := enmime.ParseAddressList(header.Get("From")) - if err != nil || len(fromaddr) == 0 { - fromaddr = make([]*mail.Address, 1) - fromaddr[0] = &from.Address + + fromAddrs, err := enmime.ParseAddressList(header.Get("From")) + if err != nil || len(fromAddrs) == 0 { + // Failed to parse From header, use SMTP MAIL FROM instead. + fromAddrs = make([]*mail.Address, 1) + fromAddrs[0] = &from.Address } - toaddr, err := enmime.ParseAddressList(header.Get("To")) + + toAddrs, err := enmime.ParseAddressList(header.Get("To")) if err != nil { - toaddr = make([]*mail.Address, len(recipients)) + // Failed to parse To header, use SMTP RCPT TO instead. + toAddrs = make([]*mail.Address, len(recipients)) for i, torecip := range recipients { - toaddr[i] = &torecip.Address + toAddrs[i] = &torecip.Address } } - subject := header.Get("Subject") + subject := header.Get("Subject") now := time.Now() tstamp := now.UTC().Format(recvdTimeFmt) @@ -79,14 +83,11 @@ func (s *StoreManager) Deliver( for i, recip := range recipients { mailboxes[i] = recip.Mailbox } - toAddrs := make([]mail.Address, len(toaddr)) - for i, addr := range toaddr { - toAddrs[i] = *addr - } + // Construct InboundMessage event and process through extensions. inbound := &event.InboundMessage{ Mailboxes: mailboxes, - From: *fromaddr[0], + From: fromAddrs[0], To: toAddrs, Subject: subject, Size: int64(len(source)), @@ -105,13 +106,9 @@ func (s *StoreManager) Deliver( } else { // Event response overrides destination mailboxes and address policy. inbound = extResult - toaddr = make([]*mail.Address, len(inbound.To)) - for i := range inbound.To { - toaddr[i] = &inbound.To[i] - } } - // Deliver to mailboxes. + // Deliver to each mailbox. for _, mb := range inbound.Mailboxes { // Append recipient and timestamp to generated Recieved header. recvd := fmt.Sprintf("%s for <%s>; %s\r\n", recvdHeader, mb, tstamp) @@ -121,8 +118,8 @@ func (s *StoreManager) Deliver( delivery := &Delivery{ Meta: event.MessageMetadata{ Mailbox: mb, - From: &inbound.From, - To: toaddr, + From: inbound.From, + To: inbound.To, Date: now, Subject: inbound.Subject, }, diff --git a/pkg/message/manager_test.go b/pkg/message/manager_test.go index 65d44c7..f2ae1a0 100644 --- a/pkg/message/manager_test.go +++ b/pkg/message/manager_test.go @@ -137,8 +137,8 @@ test email`), 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{ + 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") @@ -173,8 +173,8 @@ func TestDeliverEmitsBeforeMessageStoredEventRcptTo(t *testing.T) { 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{ + 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: "u2@example.com"}, }, got.To, "To not equal") @@ -256,10 +256,10 @@ func TestDeliverUsesBeforeMessageStoredEventResponseFields(t *testing.T) { func(msg event.InboundMessage) *event.InboundMessage { // Listener rewrites destination mailboxes. msg.Subject = "event subj" - msg.From = mail.Address{Address: "from@event.com", Name: "From Event"} + msg.From = &mail.Address{Address: "from@event.com", Name: "From Event"} // Changing To does not affect destination mailbox(es). - msg.To = []mail.Address{ + msg.To = []*mail.Address{ {Address: "to@event.com", Name: "To Event"}, {Address: "to2@event.com", Name: "To 2 Event"}, } @@ -479,6 +479,17 @@ test email` assert.Contains(t, got, msgSource, "Source should contain original message source") } +func TestMailboxForAddress(t *testing.T) { + // Configured for FullNaming. + sm, _ := testStoreManager() + + addr := "u1@example.com" + got, err := sm.MailboxForAddress(addr) + require.NoError(t, err) + + assert.Equal(t, addr, got, "FullNaming mode should return a full address for mailbox") +} + // Returns an empty StoreManager and extension Host pair, configured for testing. func testStoreManager() (*message.StoreManager, *extension.Host) { extHost := extension.NewHost()