Skip to content

Commit

Permalink
Merge pull request #162 from mocktools/develop
Browse files Browse the repository at this point in the history
Golang smtpmock v2.2.0
  • Loading branch information
bestwebua authored Dec 27, 2023
2 parents d29f933 + ce0d8aa commit 12fc9a5
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 17 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ version: 2.1
defaults: &defaults
working_directory: ~/go-smtp-mock
docker:
- image: cimg/go:1.19
- image: cimg/go:1.21.5

jobs:
linters:
docker:
- image: golangci/golangci-lint:v1.50.1-alpine
- image: golangci/golangci-lint:v1.55.2-alpine

steps:
- checkout
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
golang 1.15.6
golang 1.21.5
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.2.0] - 2023-12-27

### Added

- Added ability to use `localhost` as valid domain name for `MAIL FROM` and `RCPT TO` commands. Thanks [@Deracination](https://github.com/Deracination) for request

## [2.1.0] - 2023-06-14

### Added

- Added ability to use `NOOP` command, following [RFC 2821](https://datatracker.ietf.org/doc/html/rfc2821#section-4.1.1.9) (section 4.1.1.9). Thanks [@rehleinBo](https://github.com/rehleinBo) for PR

## [2.0.5] - 2023-01-11
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,8 @@ Available not configuration `smtpmock` options:
| --- | --- | --- | --- | --- |
| `1` | `HELO` | no | `domain name`, `localhost`, `ip address`, `[ip address]` | `HELO example.com` |
| `1` | `EHLO` | no | `domain name`, `localhost`, `ip address`, `[ip address]` | `EHLO example.com` |
| `2` | `MAIL FROM` | can be used after command with id `1` and greater | `email address`, `<email address>` | `MAIL FROM: user@domain.com` |
| `3` | `RCPT TO` | can be used after command with id `2` and greater | `email address`, `<email address>` | `RCPT TO: user@domain.com` |
| `2` | `MAIL FROM` | can be used after command with id `1` and greater | `email address`, `<email address>`, `localhost email address`, `<localhost email address>` | `MAIL FROM: user@domain.com` |
| `3` | `RCPT TO` | can be used after command with id `2` and greater | `email address`, `<email address>`, `localhost email address`, `<localhost email address>` | `RCPT TO: user@domain.com` |
| `4` | `DATA` | can be used after command with id `3` | - | `DATA` |
| `5` | `RSET` | can be used after command with id `1` and greater | - | `RSET` |
| `6` | `NOOP` | no | - | `NOOP` |
Expand Down
8 changes: 4 additions & 4 deletions consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ const (
defaultShutdownTimeout = 1 // in seconds
defaultSessionResponseDelay = 0 // in seconds
serverStartMsg = "SMTP mock server started on port"
serverStartErrorMsg = "unable to start SMTP mock server. Server must be inactive"
serverStartErrorMsg = "Unable to start SMTP mock server. Server must be inactive"
serverErrorMsg = "Failed to start SMTP mock server on port"
serverStopErrorMsg = "unable to stop SMTP mock server. Server must be active"
serverStopErrorMsg = "Unable to stop SMTP mock server. Server must be active"
serverNotAcceptNewConnectionsMsg = "SMTP mock server is in the shutdown mode and won't accept new connections"
serverStopMsg = "SMTP mock server was stopped successfully"
serverForceStopMsg = "SMTP mock server was force stopped by timeout"

// Regex patterns
availableCmdsRegexPattern = `(?i)helo|ehlo|mail from:|rcpt to:|data|rset|noop|quit`
domainRegexPattern = `(?i)([\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63})`
domainRegexPattern = `(?i)([\p{L}0-9]+([\-.]{1}[\p{L}0-9]+)*\.\p{L}{2,63}|localhost)`
emailRegexPattern = `(?i)<?((.+)@` + domainRegexPattern + `)>?`
ipAddressRegexPattern = `(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`
addressLiteralRegexPattern = `|\[` + ipAddressRegexPattern + `\]`
Expand All @@ -64,7 +64,7 @@ const (
validRsetCmdRegexPattern = `\A(?i)rset\z`
validNoopCmdRegexPattern = `\A(?i)noop\z`
validQuitCmdRegexPattern = `\A(?i)quit\z`
validHeloComplexCmdRegexPattern = `\A(` + validHeloCmdsRegexPattern + `) (` + domainRegexPattern + `|localhost|` + ipAddressRegexPattern + addressLiteralRegexPattern + `)\z`
validHeloComplexCmdRegexPattern = `\A(` + validHeloCmdsRegexPattern + `) (` + domainRegexPattern + `|` + ipAddressRegexPattern + addressLiteralRegexPattern + `)\z`
validMailromComplexCmdRegexPattern = `\A(` + validMailfromCmdRegexPattern + `) ?(` + emailRegexPattern + `)\z`
validRcpttoComplexCmdRegexPattern = `\A(` + validRcpttoCmdRegexPattern + `) ?(` + emailRegexPattern + `)\z`

Expand Down
12 changes: 7 additions & 5 deletions handler_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ func TestHandlerDataClearMessage(t *testing.T) {
}

func TestHandlerDataProcessIncomingMessage(t *testing.T) {
handlerMessage := &handlerMessageMock{}
handler := &handlerData{handlerMessage: handlerMessage}
handler.handlerMessage = handlerMessage
handlerMessage.On("run").Once().Return(nil)
handler.processIncomingMessage()
t.Run("when successful request received", func(t *testing.T) {
handlerMessage := &handlerMessageMock{}
handler := &handlerData{handlerMessage: handlerMessage}
handler.handlerMessage = handlerMessage
handlerMessage.On("run").Once().Return(nil)
handler.processIncomingMessage()
})
}

func TestHandlerDataWriteResult(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions handler_mailfrom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ func TestHandlerMaifromIsInvalidCmdArg(t *testing.T) {
assert.Empty(t, message.mailfromResponse)
})

t.Run("when request includes valid command MAILFROM argument with localhost domain", func(t *testing.T) {
message := new(Message)
handler := newHandlerMailfrom(session, message, configuration)

assert.False(t, handler.isInvalidCmdArg("MAIL FROM: user@localhost"))
assert.False(t, message.mailfrom)
assert.Empty(t, message.mailfromRequest)
assert.Empty(t, message.mailfromResponse)
})

t.Run("when request includes valid command MAILFROM argument without <> sign without space", func(t *testing.T) {
message := new(Message)
handler := newHandlerMailfrom(session, message, configuration)
Expand Down
9 changes: 9 additions & 0 deletions handler_rcptto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,15 @@ func TestHandlerRcpttoIsInvalidCmdArg(t *testing.T) {
assert.Empty(t, message.rcpttoRequestResponse)
})

t.Run("when request includes valid command RCPTTO argument with localhost domain", func(t *testing.T) {
message := new(Message)
handler := newHandlerRcptto(session, message, configuration)

assert.False(t, handler.isInvalidCmdArg("RCPT TO: user@localhost"))
assert.False(t, message.rcptto)
assert.Empty(t, message.rcpttoRequestResponse)
})

t.Run("when request includes valid command RCPTTO argument without <> sign without space", func(t *testing.T) {
message := new(Message)
handler := newHandlerRcptto(session, message, configuration)
Expand Down
4 changes: 1 addition & 3 deletions test_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,10 @@ func runSuccessfulSMTPSession(hostAddress string, portNumber int, fullFlow bool)
}
}

// client.Quit() will close connection after, so we don't need to use client.Close() after
if err = client.Quit(); err != nil {
return err
}
if err = client.Close(); err != nil {
return err
}

return nil
}

0 comments on commit 12fc9a5

Please sign in to comment.