diff --git a/msg.go b/msg.go index 11d8ab1..b66bffe 100644 --- a/msg.go +++ b/msg.go @@ -467,8 +467,8 @@ func (m *Msg) SetMessageID() { if err != nil { hostname = "localhost.localdomain" } - randNumPrimary, _ := randNum(100000000) - randNumSecondary, _ := randNum(10000) + randNumPrimary := randNum(100000000) + randNumSecondary := randNum(10000) randString, _ := randomStringSecure(17) procID := os.Getpid() * randNumSecondary messageID := fmt.Sprintf("%d.%d%d.%s@%s", procID, randNumPrimary, randNumSecondary, diff --git a/msg_nowin_test.go b/msg_nowin_test.go index 820be24..6cde71a 100644 --- a/msg_nowin_test.go +++ b/msg_nowin_test.go @@ -61,3 +61,25 @@ func TestMsg_WriteToSendmail(t *testing.T) { t.Errorf("WriteToSendmail failed: %s", err) } } + +func TestMsg_WriteToTempFileFailed(t *testing.T) { + m := NewMsg() + _ = m.From("Toni Tester ") + _ = m.To("Ellenor Tester ") + m.SetBodyString(TypeTextPlain, "This is a test") + + curTmpDir := os.Getenv("TMPDIR") + defer func() { + if err := os.Setenv("TMPDIR", curTmpDir); err != nil { + t.Errorf("failed to set TMPDIR environment variable: %s", err) + } + }() + + if err := os.Setenv("TMPDIR", "/invalid/directory/that/does/not/exist"); err != nil { + t.Errorf("failed to set TMPDIR environment variable: %s", err) + } + _, err := m.WriteToTempFile() + if err == nil { + t.Errorf("WriteToTempFile() did not fail as expected") + } +} diff --git a/msg_test.go b/msg_test.go index 0656ff2..f570b02 100644 --- a/msg_test.go +++ b/msg_test.go @@ -786,13 +786,11 @@ func TestMsg_SetMessageIDWithValue(t *testing.T) { // TestMsg_SetMessageIDRandomness tests the randomness of Msg.SetMessageID methods func TestMsg_SetMessageIDRandomness(t *testing.T) { var mids []string - for i := 0; i < 100; i++ { + for i := 0; i < 50_000; i++ { m := NewMsg() m.SetMessageID() - mid := m.GetGenHeader(HeaderMessageID) - if len(mid) > 0 { - mids = append(mids, mid[0]) - } + mid := m.GetMessageID() + mids = append(mids, mid) } c := make(map[string]int) for i := range mids { diff --git a/random.go b/random.go index 831b118..3a3f16b 100644 --- a/random.go +++ b/random.go @@ -7,8 +7,6 @@ package mail import ( "crypto/rand" "encoding/binary" - "fmt" - "math/big" "strings" ) @@ -52,23 +50,3 @@ func randomStringSecure(length int) (string, error) { return randString.String(), nil } - -// randNum returns a random number with a maximum value of length -func randNum(length int) (int, error) { - if length <= 0 { - return 0, fmt.Errorf("provided number is <= 0: %d", length) - } - length64 := big.NewInt(int64(length)) - if !length64.IsUint64() { - return 0, fmt.Errorf("big.NewInt() generation returned negative value: %d", length64) - } - randNum64, err := rand.Int(rand.Reader, length64) - if err != nil { - return 0, err - } - randomNum := int(randNum64.Int64()) - if randomNum < 0 { - return 0, fmt.Errorf("generated random number does not fit as int64: %d", randNum64) - } - return randomNum, nil -} diff --git a/random_119.go b/random_119.go new file mode 100644 index 0000000..b084305 --- /dev/null +++ b/random_119.go @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2022-2023 The go-mail Authors +// +// SPDX-License-Identifier: MIT + +//go:build go1.19 && !go1.20 +// +build go1.19,!go1.20 + +package mail + +import ( + "math/rand" + "time" +) + +// randNum returns a random number with a maximum value of length +func randNum(maxval int) int { + if maxval <= 0 { + return 0 + } + rand.Seed(time.Now().UnixNano()) + return rand.Intn(maxval) +} diff --git a/random_121.go b/random_121.go new file mode 100644 index 0000000..b401bc8 --- /dev/null +++ b/random_121.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2022-2023 The go-mail Authors +// +// SPDX-License-Identifier: MIT + +//go:build go1.20 && !go1.22 +// +build go1.20,!go1.22 + +package mail + +import ( + "math/rand" +) + +// randNum returns a random number with a maximum value of length +func randNum(maxval int) int { + if maxval <= 0 { + return 0 + } + return rand.Intn(maxval) +} diff --git a/random_122.go b/random_122.go new file mode 100644 index 0000000..9a6132b --- /dev/null +++ b/random_122.go @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2022-2023 The go-mail Authors +// +// SPDX-License-Identifier: MIT + +//go:build go1.22 +// +build go1.22 + +package mail + +import ( + "math/rand/v2" +) + +// randNum returns a random number with a maximum value of maxval. +// go-mail compiled with Go 1.22+ will make use of the novel math/rand/v2 interface +// Older versions of Go will use math/rand +func randNum(maxval int) int { + if maxval <= 0 { + return 0 + } + return rand.IntN(maxval) +} diff --git a/random_test.go b/random_test.go index 51e3ba6..e69b4e7 100644 --- a/random_test.go +++ b/random_test.go @@ -55,16 +55,17 @@ func TestRandomNum(t *testing.T) { for _, tc := range tt { t.Run(tc.testName, func(t *testing.T) { - rn, err := randNum(tc.max) - if err != nil { - t.Errorf("random number generation failed: %s", err) - } - if rn < 0 { - t.Errorf("random number generation failed: %d is smaller than zero", rn) - } + 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) + } +} diff --git a/senderror_test.go b/senderror_test.go index 8b7bfb3..e04b7ee 100644 --- a/senderror_test.go +++ b/senderror_test.go @@ -108,6 +108,13 @@ func TestSendError_MessageID(t *testing.T) { } } +func TestSendError_MessageIDNil(t *testing.T) { + var se *SendError + if se.MessageID() != "" { + t.Error("expected empty string on nil-senderror") + } +} + func TestSendError_Msg(t *testing.T) { var se *SendError err := returnSendError(ErrAmbiguous, false) @@ -131,6 +138,33 @@ func TestSendError_Msg(t *testing.T) { } } +func TestSendError_MsgNil(t *testing.T) { + var se *SendError + if se.Msg() != nil { + t.Error("expected nil on nil-senderror") + } +} + +func TestSendError_IsFail(t *testing.T) { + err1 := returnSendError(ErrAmbiguous, false) + err2 := returnSendError(ErrSMTPMailFrom, false) + if errors.Is(err1, err2) { + t.Errorf("error mismatch, ErrAmbiguous should not be equal to ErrSMTPMailFrom") + } +} + +func TestSendError_ErrorMulti(t *testing.T) { + expected := `ambiguous reason, check Msg.SendError for message specific reasons, ` + + `affected recipient(s): , ` + err := &SendError{ + Reason: ErrAmbiguous, isTemp: false, affectedMsg: nil, + rcpt: []string{"", ""}, + } + if err.Error() != expected { + t.Errorf("error mismatch, expected: %s, got: %s", expected, err.Error()) + } +} + // returnSendError is a helper method to retunr a SendError with a specific reason func returnSendError(r SendErrReason, t bool) error { message := NewMsg()