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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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"},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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"},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user