Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify message id generation and get rid of randnum #329

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}
}
Loading