1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 10:07:02 +00:00

event: Use pointers for InboundMessage addresses (#447)

* event: Use pointers for InboundMessage addresses

To ease conversions to/from MessageMetadata

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

* message: test StoreManager.MailboxForAddress()

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

---------

Signed-off-by: James Hillyerd <james@hillyerd.com>
This commit is contained in:
James Hillyerd
2023-11-22 17:28:33 -08:00
committed by GitHub
parent d2121a52a9
commit c1d5d49126
6 changed files with 49 additions and 41 deletions

View File

@@ -14,8 +14,8 @@ type AddressParts struct {
// InboundMessage contains the basic header and mailbox data for a message being received. // InboundMessage contains the basic header and mailbox data for a message being received.
type InboundMessage struct { type InboundMessage struct {
Mailboxes []string Mailboxes []string
From mail.Address From *mail.Address
To []mail.Address To []*mail.Address
Subject string Subject string
Size int64 Size int64
} }

View File

@@ -73,12 +73,12 @@ func inboundMessageIndex(ls *lua.LState) int {
} }
ls.Push(lt) ls.Push(lt)
case "from": case "from":
ls.Push(wrapMailAddress(ls, &m.From)) ls.Push(wrapMailAddress(ls, m.From))
case "to": case "to":
lt := &lua.LTable{} lt := &lua.LTable{}
for _, v := range m.To { for _, v := range m.To {
addr := v addr := v
lt.Append(wrapMailAddress(ls, &addr)) lt.Append(wrapMailAddress(ls, addr))
} }
ls.Push(lt) ls.Push(lt)
case "subject": case "subject":
@@ -110,15 +110,15 @@ func inboundMessageNewIndex(ls *lua.LState) int {
}) })
m.Mailboxes = mailboxes m.Mailboxes = mailboxes
case "from": case "from":
m.From = *checkMailAddress(ls, 3) m.From = checkMailAddress(ls, 3)
case "to": case "to":
lt := ls.CheckTable(3) lt := ls.CheckTable(3)
to := make([]mail.Address, 0, 16) to := make([]*mail.Address, 0, 16)
lt.ForEach(func(k, lv lua.LValue) { lt.ForEach(func(k, lv lua.LValue) {
if ud, ok := lv.(*lua.LUserData); ok { if ud, ok := lv.(*lua.LUserData); ok {
// TODO should fail if wrong type + test. // TODO should fail if wrong type + test.
if entry, ok := unwrapMailAddress(ud); ok { if entry, ok := unwrapMailAddress(ud); ok {
to = append(to, *entry) to = append(to, entry)
} }
} }
}) })

View File

@@ -31,8 +31,8 @@ const LuaInit = `
func TestInboundMessageGetters(t *testing.T) { func TestInboundMessageGetters(t *testing.T) {
want := &event.InboundMessage{ want := &event.InboundMessage{
Mailboxes: []string{"mb1", "mb2"}, Mailboxes: []string{"mb1", "mb2"},
From: mail.Address{Name: "name1", Address: "addr1"}, From: &mail.Address{Name: "name1", Address: "addr1"},
To: []mail.Address{ To: []*mail.Address{
{Name: "name2", Address: "addr2"}, {Name: "name2", Address: "addr2"},
{Name: "name3", Address: "addr3"}, {Name: "name3", Address: "addr3"},
}, },
@@ -66,8 +66,8 @@ func TestInboundMessageGetters(t *testing.T) {
func TestInboundMessageSetters(t *testing.T) { func TestInboundMessageSetters(t *testing.T) {
want := &event.InboundMessage{ want := &event.InboundMessage{
Mailboxes: []string{"mb1", "mb2"}, Mailboxes: []string{"mb1", "mb2"},
From: mail.Address{Name: "name1", Address: "addr1"}, From: &mail.Address{Name: "name1", Address: "addr1"},
To: []mail.Address{ To: []*mail.Address{
{Name: "name2", Address: "addr2"}, {Name: "name2", Address: "addr2"},
{Name: "name3", Address: "addr3"}, {Name: "name3", Address: "addr3"},
}, },

View File

@@ -179,8 +179,8 @@ func TestBeforeMessageStored(t *testing.T) {
// Event to send. // Event to send.
msg := event.InboundMessage{ msg := event.InboundMessage{
Mailboxes: []string{"one", "two"}, Mailboxes: []string{"one", "two"},
From: mail.Address{Name: "From Name", Address: "from@example.com"}, From: &mail.Address{Name: "From Name", Address: "from@example.com"},
To: []mail.Address{ To: []*mail.Address{
{Name: "To1 Name", Address: "to1@example.com"}, {Name: "To1 Name", Address: "to1@example.com"},
{Name: "To2 Name", Address: "to2@example.com"}, {Name: "To2 Name", Address: "to2@example.com"},
}, },
@@ -233,8 +233,8 @@ func TestBeforeMessageStored(t *testing.T) {
// Verify response values. // Verify response values.
want := &event.InboundMessage{ want := &event.InboundMessage{
Mailboxes: []string{"resone", "restwo"}, Mailboxes: []string{"resone", "restwo"},
From: mail.Address{Name: "Res From", Address: "res@example.com"}, From: &mail.Address{Name: "Res From", Address: "res@example.com"},
To: []mail.Address{ To: []*mail.Address{
{Name: "To1 Res", Address: "res1@example.com"}, {Name: "To1 Res", Address: "res1@example.com"},
{Name: "To2 Res", Address: "res2@example.com"}, {Name: "To2 Res", Address: "res2@example.com"},
}, },

View File

@@ -57,20 +57,24 @@ func (s *StoreManager) Deliver(
if err != nil { if err != nil {
return err return err
} }
fromaddr, err := enmime.ParseAddressList(header.Get("From"))
if err != nil || len(fromaddr) == 0 { fromAddrs, err := enmime.ParseAddressList(header.Get("From"))
fromaddr = make([]*mail.Address, 1) if err != nil || len(fromAddrs) == 0 {
fromaddr[0] = &from.Address // 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 { 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 { for i, torecip := range recipients {
toaddr[i] = &torecip.Address toAddrs[i] = &torecip.Address
} }
} }
subject := header.Get("Subject")
subject := header.Get("Subject")
now := time.Now() now := time.Now()
tstamp := now.UTC().Format(recvdTimeFmt) tstamp := now.UTC().Format(recvdTimeFmt)
@@ -79,14 +83,11 @@ func (s *StoreManager) Deliver(
for i, recip := range recipients { for i, recip := range recipients {
mailboxes[i] = recip.Mailbox 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{ inbound := &event.InboundMessage{
Mailboxes: mailboxes, Mailboxes: mailboxes,
From: *fromaddr[0], From: fromAddrs[0],
To: toAddrs, To: toAddrs,
Subject: subject, Subject: subject,
Size: int64(len(source)), Size: int64(len(source)),
@@ -105,13 +106,9 @@ func (s *StoreManager) Deliver(
} else { } else {
// Event response overrides destination mailboxes and address policy. // Event response overrides destination mailboxes and address policy.
inbound = extResult 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 { for _, mb := range inbound.Mailboxes {
// Append recipient and timestamp to generated Recieved header. // Append recipient and timestamp to generated Recieved header.
recvd := fmt.Sprintf("%s for <%s>; %s\r\n", recvdHeader, mb, tstamp) recvd := fmt.Sprintf("%s for <%s>; %s\r\n", recvdHeader, mb, tstamp)
@@ -121,8 +118,8 @@ func (s *StoreManager) Deliver(
delivery := &Delivery{ delivery := &Delivery{
Meta: event.MessageMetadata{ Meta: event.MessageMetadata{
Mailbox: mb, Mailbox: mb,
From: &inbound.From, From: inbound.From,
To: toaddr, To: inbound.To,
Date: now, Date: now,
Subject: inbound.Subject, Subject: inbound.Subject,
}, },

View File

@@ -137,8 +137,8 @@ test email`),
require.NotNil(t, got, "BeforeMessageStored listener did not receive InboundMessage") 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, []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: "from@example.com"}, got.From, "From not equal")
assert.Equal(t, []mail.Address{ assert.Equal(t, []*mail.Address{
{Name: "", Address: "u1@example.com"}, {Name: "", Address: "u1@example.com"},
{Name: "", Address: "u3@external.com"}, {Name: "", Address: "u3@external.com"},
}, got.To, "To not equal") }, got.To, "To not equal")
@@ -173,8 +173,8 @@ func TestDeliverEmitsBeforeMessageStoredEventRcptTo(t *testing.T) {
require.NotNil(t, got, "BeforeMessageStored listener did not receive InboundMessage") 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, []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: "from@example.com"}, got.From, "From not equal")
assert.Equal(t, []mail.Address{ assert.Equal(t, []*mail.Address{
{Name: "", Address: "u1@example.com"}, {Name: "", Address: "u1@example.com"},
{Name: "", Address: "u2@example.com"}, {Name: "", Address: "u2@example.com"},
}, got.To, "To not equal") }, got.To, "To not equal")
@@ -256,10 +256,10 @@ func TestDeliverUsesBeforeMessageStoredEventResponseFields(t *testing.T) {
func(msg event.InboundMessage) *event.InboundMessage { func(msg event.InboundMessage) *event.InboundMessage {
// Listener rewrites destination mailboxes. // Listener rewrites destination mailboxes.
msg.Subject = "event subj" 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). // Changing To does not affect destination mailbox(es).
msg.To = []mail.Address{ msg.To = []*mail.Address{
{Address: "to@event.com", Name: "To Event"}, {Address: "to@event.com", Name: "To Event"},
{Address: "to2@event.com", Name: "To 2 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") 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. // Returns an empty StoreManager and extension Host pair, configured for testing.
func testStoreManager() (*message.StoreManager, *extension.Host) { func testStoreManager() (*message.StoreManager, *extension.Host) {
extHost := extension.NewHost() extHost := extension.NewHost()