Skip to content

Commit

Permalink
Merge pull request #329 from wneessen/feature/327_simplify-message-id…
Browse files Browse the repository at this point in the history
…-generation-and-get-rid-of-randnum

Simplify message id generation and get rid of randnum
  • Loading branch information
wneessen authored Oct 7, 2024
2 parents a94e721 + 5874911 commit 8faac3d
Show file tree
Hide file tree
Showing 7 changed files with 20 additions and 137 deletions.
18 changes: 7 additions & 11 deletions msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -972,12 +972,12 @@ func (m *Msg) Subject(subj string) {

// SetMessageID generates and sets a unique "Message-ID" header for the Msg.
//
// This method creates a "Message-ID" string using the current process ID, random numbers, and the hostname
// of the machine. The generated ID helps uniquely identify the message in email systems, facilitating tracking
// and preventing duplication. If the hostname cannot be retrieved, it defaults to "localhost.localdomain".
// This method creates a "Message-ID" string using a randomly generated string and the hostname of the machine.
// The generated ID helps uniquely identify the message in email systems, facilitating tracking and preventing
// duplication. If the hostname cannot be retrieved, it defaults to "localhost.localdomain".
//
// The generated Message-ID follows the format
// "<processID.randomNumberPrimary.randomNumberSecondary.randomString@hostname>".
// "<randomString@hostname>".
//
// References:
// - https://datatracker.ietf.org/doc/html/rfc5322#section-3.6.4
Expand All @@ -986,13 +986,9 @@ func (m *Msg) SetMessageID() {
if err != nil {
hostname = "localhost.localdomain"
}
randNumPrimary := randNum(100000000)
randNumSecondary := randNum(10000)
randString, _ := randomStringSecure(17)
procID := os.Getpid() * randNumSecondary
messageID := fmt.Sprintf("%d.%d%d.%s@%s", procID, randNumPrimary, randNumSecondary,
randString, hostname)
m.SetMessageIDWithValue(messageID)
// We have 64 possible characters, which for a 22 character string, provides approx. 132 bits of entropy.
randString, _ := randomStringSecure(22)
m.SetMessageIDWithValue(fmt.Sprintf("%s@%s", randString, hostname))
}

// GetMessageID retrieves the "Message-ID" header from the Msg.
Expand Down
2 changes: 1 addition & 1 deletion msg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -786,8 +786,8 @@ func TestMsg_SetMessageIDWithValue(t *testing.T) {
// TestMsg_SetMessageIDRandomness tests the randomness of Msg.SetMessageID methods
func TestMsg_SetMessageIDRandomness(t *testing.T) {
var mids []string
m := NewMsg()
for i := 0; i < 50_000; i++ {
m := NewMsg()
m.SetMessageID()
mid := m.GetMessageID()
mids = append(mids, mid)
Expand Down
9 changes: 5 additions & 4 deletions random.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import (
)

// Range of characters for the secure string generation
const cr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
const cr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"

// Bitmask sizes for the string generators (based on 93 chars total)
//
// These constants define bitmask-related values used for efficient random string generation.
// The bitmask operates over 93 possible characters, and the constants help determine the
// The bitmask operates over 66 possible characters, and the constants help determine the
// number of bits and indices used in the process.
const (
// letterIdxBits: Number of bits (7) needed to represent a letter index.
letterIdxBits = 7
// letterIdxBits: Number of bits needed to represent a letter index. We have 64 possible characters
// which fit into 6 bits.
letterIdxBits = 6
// letterIdxMask: Bitmask to extract letter indices (all 1-bits for letterIdxBits).
letterIdxMask = 1<<letterIdxBits - 1
// letterIdxMax: The maximum number of letter indices that fit in 63 bits.
Expand Down
32 changes: 0 additions & 32 deletions random_119.go

This file was deleted.

30 changes: 0 additions & 30 deletions random_121.go

This file was deleted.

30 changes: 0 additions & 30 deletions random_122.go

This file was deleted.

36 changes: 7 additions & 29 deletions random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,12 @@ func TestRandomStringSecure(t *testing.T) {
}
}

// TestRandomNum tests the randomNum method
func TestRandomNum(t *testing.T) {
tt := []struct {
testName string
max int
}{
{"Max: 1", 1},
{"Max: 20", 20},
{"Max: 50", 50},
{"Max: 100", 100},
{"Max: 1000", 1000},
{"Max: 10000", 10000},
{"Max: 100000000", 100000000},
}

for _, tc := range tt {
t.Run(tc.testName, func(t *testing.T) {
rn := randNum(tc.max)
if rn > tc.max {
t.Errorf("random number generation failed: %d is bigger than given value %d", rn, tc.max)
}
})
}
}

func TestRandomNumZero(t *testing.T) {
rn := randNum(0)
if rn != 0 {
t.Errorf("random number generation failed: %d is not zero", rn)
func BenchmarkGenerator_RandomStringSecure(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, err := randomStringSecure(22)
if err != nil {
b.Errorf("RandomStringFromCharRange() failed: %s", err)
}
}
}

0 comments on commit 8faac3d

Please sign in to comment.