Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

SMTP mock server written on Golang. Mimic any 📤 SMTP server behavior for your test environment with fake SMTP server.

License

NotificationsYou must be signed in to change notification settings

mocktools/go-smtp-mock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SMTP mock server written on Golang. Mimic any SMTP server behavior for your test environment with fake SMTP server

Go Report CardCodecovCircleCIGitHub release (latest by date)PkgGoDevMentioned in Awesome GoGitHubContributor Covenant

smtpmock is lightweight configurable multithreaded fake SMTP server written in Go. It meets the minimum requirements specified byRFC 2821 &RFC 5321. Allows to mimic any SMTP server behavior for your test environment and even more 🚀

Table of Contents

Features

  • Configurable multithreaded RFC compatible SMTP server
  • Implements the minimum command set, responds to commands and adds a valid received header to messages as specified inRFC 2821 &RFC 5321
  • Ability to configure behavior for each SMTP command
  • Comes with default settings out of the box, configure only what you need
  • Ability to override previous SMTP commands
  • Fail fast scenario (ability to close client session for case when command was inconsistent or failed)
  • Multiple receivers (ability to configure multipleRCPT TO commands receiving during one session)
  • Multiple message receiving (ability to configure multiple message receiving during one session)
  • Mock-server activity logger
  • Ability to do graceful/force shutdown of SMTP mock server
  • No authentication support
  • Zero runtime dependencies
  • Ability to access to server messages
  • Simple and intuitive DSL
  • Ability to run server as binary with command line arguments

Requirements

Golang 1.15+

Installation

Installsmtpmock:

go get github.com/mocktools/go-smtp-mock/v2go install github.com/mocktools/go-smtp-mock/v2

Importsmtpmock dependency into your code:

package mainimport smtpmock"github.com/mocktools/go-smtp-mock/v2"

Usage

Inside of Golang ecosystem

You have to create your SMTP mock server usingsmtpmock.New() andsmtpmock.ConfigurationAttr{} to start interaction with it.

Configuring

smtpmock is SMTP server for test environment with configurable behavior. It comes with default settings out of the box. But you can override any default behavior if you need.

smtpmock.ConfigurationAttr{// Customizing server behavior// ---------------------------------------------------------------------// Host address where smtpmock will run, it's equal to "127.0.0.1" by defaultHostAddress:"[::]",// Port number on which the server will bind. If it not specified, it will be// assigned dynamically after server.Start() by defaultPortNumber:2525,// Enables/disables log to stdout. It's equal to false by defaultLogToStdout:true,// Enables/disables log server activity. It's equal to false by defaultLogServerActivity:true,// Ability to specify session timeout. It's equal to 30 seconds by defaultSessionTimeout:42,// Ability to specify graceful shutdown timeout. It's equal to 1 second by defaultShutdownTimeout:5,// Customizing SMTP command handlers behavior// ---------------------------------------------------------------------// Ability to configure fail fast scenario. It means that server will// close client session for case when command was inconsistent or failed.// It's equal to false by defaultIsCmdFailFast:true,// Ability to configure multiple RCPT TO command receiving during one session.// It means that server will handle and save all RCPT TO command request-response// pairs until receive successful response and next SMTP command has been passed.// Please note, by default will be saved only one, the last RCPT TO command// request-response pair. It's equal to false by defaultMultipleRcptto:true,// Ability to configure multiple message receiving during one session. It means that server// will create another message during current SMTP session in case when RSET// command has been used after successful commands chain: MAIL FROM, RCPT TO, DATA.// Please note, by default RSET command flushes current message in any case.// It's equal to false by defaultMultipleMessageReceiving:true,// Ability to specify blacklisted HELO domains. It's equal to empty []stringBlacklistedHeloDomains:        []string{"example1.com","example2.com","localhost"},// Ability to specify blacklisted MAIL FROM emails. It's equal to empty []stringBlacklistedMailfromEmails:     []string{"bot@olo.com","robot@molo.com"},// Ability to specify blacklisted RCPT TO emails. It's equal to empty []stringBlacklistedRcpttoEmails:       []string{"blacklisted@olo.com","blacklisted@molo.com"},// Ability to specify not registered (non-existent) RCPT TO emails.// It's equal to empty []stringNotRegisteredEmails:           []string{"nobody@olo.com","non-existent@email.com"},// Ability to specify HELO response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayHelo:2,// Ability to specify MAIL FROM response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayMailfrom:2,// Ability to specify RCPT TO response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayRcptto:2,// Ability to specify DATA response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayData:2,// Ability to specify message response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayMessage:2,// Ability to specify RSET response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayRset:2,// Ability to specify NOOP response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayNoop:2,// Ability to specify QUIT response delay in seconds. It runs immediately,// equals to 0 seconds by defaultResponseDelayQuit:2,// Ability to specify message body size limit. It's equal to 10485760 bytes (10MB) by defaultMsgSizeLimit:5,// Customizing SMTP command handler messages context// ---------------------------------------------------------------------// Custom server greeting message. Base on defaultGreetingMsg by defaultMsgGreeting:"msgGreeting",// Custom invalid command message. Based on defaultInvalidCmdMsg by defaultMsgInvalidCmd:"msgInvalidCmd",// Custom invalid command HELO sequence message.// Based on defaultInvalidCmdHeloSequenceMsg by defaultMsgInvalidCmdHeloSequence:"msgInvalidCmdHeloSequence",// Custom invalid command HELO argument message.// Based on defaultInvalidCmdHeloArgMsg by defaultMsgInvalidCmdHeloArg:"msgInvalidCmdHeloArg",// Custom HELO blacklisted domain message. Based on defaultQuitMsg by defaultMsgHeloBlacklistedDomain:"msgHeloBlacklistedDomain",// Custom HELO received message. Based on defaultReceivedMsg by defaultMsgHeloReceived:"msgHeloReceived",// Custom invalid command MAIL FROM sequence message.// Based on defaultInvalidCmdMailfromSequenceMsg by defaultMsgInvalidCmdMailfromSequence:"msgInvalidCmdMailfromSequence",// Custom invalid command MAIL FROM argument message.// Based on defaultInvalidCmdMailfromArgMsg by defaultMsgInvalidCmdMailfromArg:"msgInvalidCmdMailfromArg",// Custom MAIL FROM blacklisted email message. Based on defaultQuitMsg by defaultMsgMailfromBlacklistedEmail:"msgMailfromBlacklistedEmail",// Custom MAIL FROM received message. Based on defaultReceivedMsg by defaultMsgMailfromReceived:"msgMailfromReceived",// Custom invalid command RCPT TO sequence message.// Based on defaultInvalidCmdRcpttoSequenceMsg by defaultMsgInvalidCmdRcpttoSequence:"msgInvalidCmdRcpttoSequence",// Custom invalid command RCPT TO argument message.// Based on defaultInvalidCmdRcpttoArgMsg by defaultMsgInvalidCmdRcpttoArg:"msgInvalidCmdRcpttoArg",// Custom RCPT TO not registered email message.// Based on defaultNotRegisteredRcpttoEmailMsg by defaultMsgRcpttoNotRegisteredEmail:"msgRcpttoNotRegisteredEmail",// Custom RCPT TO blacklisted email message. Based on defaultQuitMsg by defaultMsgRcpttoBlacklistedEmail:"msgRcpttoBlacklistedEmail",// Custom RCPT TO received message. Based on defaultReceivedMsg by defaultMsgRcpttoReceived:"msgRcpttoReceived",// Custom invalid command DATA sequence message.// Based on defaultInvalidCmdDataSequenceMsg by defaultMsgInvalidCmdDataSequence:"msgInvalidCmdDataSequence",// Custom DATA received message. Based on defaultReadyForReceiveMsg by defaultMsgDataReceived:"msgDataReceived",// Custom size is too big message. Based on defaultMsgSizeIsTooBigMsg by defaultMsgMsgSizeIsTooBig:"msgMsgSizeIsTooBig",// Custom received message body message. Based on defaultReceivedMsg by defaultMsgMsgReceived:"msgMsgReceived",// Custom invalid command RSET sequence message.// Based on defaultInvalidCmdHeloSequenceMsg by defaultMsgInvalidCmdRsetSequence:"msgInvalidCmdRsetSequence",// Custom invalid command RSET message. Based on defaultInvalidCmdMsg by defaultMsgInvalidCmdRsetArg:"msgInvalidCmdRsetArg",// Custom RSET received message. Based on defaultOkMsg by defaultMsgRsetReceived:"msgRsetReceived",// Custom NOOP received message. Based on defaultOkMsg by defaultMsgNoopReceived:"msgNoopReceived",// Custom quit command message. Based on defaultQuitMsg by defaultMsgQuitCmd:"msgQuitCmd",}

Manipulation with server

package mainimport ("fmt""net""net/smtp"  smtpmock"github.com/mocktools/go-smtp-mock/v2")funcmain() {// You can pass empty smtpmock.ConfigurationAttr{}. It means that smtpmock will use default settingsserver:=smtpmock.New(smtpmock.ConfigurationAttr{LogToStdout:true,LogServerActivity:true,  })// To start server use Start() methodiferr:=server.Start();err!=nil {fmt.Println(err)  }// Server's port will be assigned dynamically after server.Start()// for case when portNumber wasn't specifiedhostAddress,portNumber:="127.0.0.1",server.PortNumber()// Possible SMTP-client stuff for iteration with mock serveraddress:=fmt.Sprintf("%s:%d",hostAddress,portNumber)timeout:=time.Duration(2)*time.Secondconnection,_:=net.DialTimeout("tcp",address,timeout)client,_:=smtp.NewClient(connection,hostAddress)client.Hello("example.com")client.Quit()client.Close()// Each result of SMTP session will be saved as message.// To get access for server messages copies use Messages() methodserver.Messages()// To get access for server messages copies and purge it on server after// use MessagesAndPurge() methodserver.MessagesAndPurge()// In case with flaky test environment you can wait for the specified number// of messages to arrive or until timeout is reached use WaitForMessages() methodserver.WaitForMessages(42,1*time.Millisecond)// In case with flaky test environment you can wait for the specified number// of messages to arrive or until timeout is reached and purge it on server// after use WaitForMessagesAndPurge() methodserver.WaitForMessagesAndPurge(42,1*time.Millisecond)// To stop the server use Stop() method. Please note, smtpmock uses graceful shutdown.// It means that smtpmock will end all sessions after client responses or by session// timeouts immediately.iferr:=server.Stop();err!=nil {fmt.Println(err)  }}

Code from example above will produce next output to stdout:

INFO: 2021/11/30 22:07:30.554827 SMTP mock server started on port: 2525INFO: 2021/11/30 22:07:30.554961 SMTP session startedINFO: 2021/11/30 22:07:30.554998 SMTP response: 220 WelcomeINFO: 2021/11/30 22:07:30.555059 SMTP request: EHLO example.comINFO: 2021/11/30 22:07:30.555648 SMTP response: 250 ReceivedINFO: 2021/11/30 22:07:30.555686 SMTP request: QUITINFO: 2021/11/30 22:07:30.555722 SMTP response: 221 Closing connectionINFO: 2021/11/30 22:07:30.555732 SMTP session finishedWARNING: 2021/11/30 22:07:30.555801 SMTP mock server is in the shutdown mode and won't accept new connectionsINFO: 2021/11/30 22:07:30.555808 SMTP mock server was stopped successfully

Inside of Ruby ecosystem

In Ruby ecosystemsmtpmock is available assmtp_mock gem. It's flexible Ruby wrapper oversmtpmock binary.

Example of usage

First, you should installsmtp_mock gem andsmtpmock as system dependency:

gem install smtp_mockbundleexec smtp_mock -i~

Now, you can create and interact with yoursmtpmock instance natively from Ruby ecosystem. It comes with default settings out of the box. Configure only what you need, for example:

require'smtp_mock'# List of all available server options:# https://github.com/mocktools/ruby-smtp-mock#available-server-optionssmtp_mock_server=SmtpMock.start_server(not_registered_emails:%w[user@olo.comuser@molo.com])# returns current smtp mock server portsmtp_mock_server.port# => 55640# interface for force shutdown current smtp mock serversmtp_mock_server.stop!# => true

Inside of any ecosystem

You can usesmtpmock as binary. Just download the pre-compiled binary from thereleases page and copy them to the desired location. For start server run command with needed arguments. You can use our bash script for automation this process like in the example below:

curl -sL https://raw.githubusercontent.com/mocktools/go-smtp-mock/master/script/download.sh| bash./smtpmock -port=2525 -log

Configuring with command line arguments

smtpmock configuration is available as command line arguments specified in the list below:

Flag descriptionExample of usage
-host - host address where smtpmock will run. It's equal to127.0.0.1 by default-host=localhost
-port - server port number. If not specified it will be assigned dynamically-port=2525
-log - enables log server activity. Disabled by default-log
-sessionTimeout - session timeout in seconds. It's equal to 30 seconds by default-sessionTimeout=60
-shutdownTimeout - graceful shutdown timeout in seconds. It's equal to 1 second by default-shutdownTimeout=5
-failFast - enables fail fast scenario. Disabled by default-failFast
-multipleRcptto - enables multipleRCPT TO receiving scenario. Disabled by default-multipleRcptto
-multipleMessageReceiving - enables multiple message receiving scenario. Disabled by default-multipleMessageReceiving
-blacklistedHeloDomains - blacklistedHELO domains, separated by commas-blacklistedHeloDomains="example1.com,example2.com"
-blacklistedMailfromEmails - blacklistedMAIL FROM emails, separated by commas-blacklistedMailfromEmails="a@example1.com,b@example2.com"
-blacklistedRcpttoEmails - blacklistedRCPT TO emails, separated by commas-blacklistedRcpttoEmails="a@example1.com,b@example2.com"
-notRegisteredEmails - not registered (non-existent)RCPT TO emails, separated by commas-notRegisteredEmails="a@example1.com,b@example2.com"
-responseDelayHelo -HELO response delay in seconds. It's equal to 0 seconds by default-responseDelayHelo=2
-responseDelayMailfrom -MAIL FROM response delay in seconds. It's equal to 0 seconds by default-responseDelayMailfrom=2
-responseDelayRcptto -RCPT TO response delay in seconds. It's equal to 0 seconds by default-responseDelayRcptto=2
-responseDelayData -DATA response delay in seconds. It's equal to 0 seconds by default-responseDelayData=2
-responseDelayMessage - Message response delay in seconds. It's equal to 0 seconds by default-responseDelayMessage=2
-responseDelayRset -RSET response delay in seconds. It's equal to 0 seconds by default-responseDelayRset=2
-responseDelayNoop -NOOP response delay in seconds. It's equal to 0 seconds by default-responseDelayNoop=2
-responseDelayQuit -QUIT response delay in seconds. It's equal to 0 seconds by default-responseDelayQuit=2
-msgSizeLimit - message body size limit in bytes. It's equal to10485760 bytes-msgSizeLimit=42
-msgGreeting - custom server greeting message-msgGreeting="Greeting message"
-msgInvalidCmd - custom invalid command message-msgInvalidCmd="Invalid command message"
-msgInvalidCmdHeloSequence - custom invalid commandHELO sequence message-msgInvalidCmdHeloSequence="Invalid command HELO sequence message"
-msgInvalidCmdHeloArg - custom invalid commandHELO argument message-msgInvalidCmdHeloArg="Invalid command HELO argument message"
-msgHeloBlacklistedDomain - customHELO blacklisted domain message-msgHeloBlacklistedDomain="Blacklisted domain message"
-msgHeloReceived - customHELO received message-msgHeloReceived="HELO received message"
-msgInvalidCmdMailfromSequence - custom invalid commandMAIL FROM sequence message-msgInvalidCmdMailfromSequence="Invalid command MAIL FROM sequence message"
-msgInvalidCmdMailfromArg - custom invalid commandMAIL FROM argument message-msgInvalidCmdMailfromArg="Invalid command MAIL FROM argument message"
-msgMailfromBlacklistedEmail - customMAIL FROM blacklisted email message-msgMailfromBlacklistedEmail="Blacklisted email message"
-msgMailfromReceived- customMAIL FROM received message-msgMailfromReceived="MAIL FROM received message"
-msgInvalidCmdRcpttoSequence - custom invalid commandRCPT TO sequence message-msgInvalidCmdRcpttoSequence="Invalid command RCPT TO sequence message"
-msgInvalidCmdRcpttoArg - custom invalid commandRCPT TO argument message-msgInvalidCmdRcpttoArg="Invalid command RCPT TO argument message"
-msgRcpttoNotRegisteredEmail - customRCPT TO not registered email message-msgRcpttoNotRegisteredEmail="Not registered email message"
-msgRcpttoBlacklistedEmail - customRCPT TO blacklisted email message-msgRcpttoBlacklistedEmail="Blacklisted email message"
-msgRcpttoReceived - customRCPT TO received message-msgRcpttoReceived="RCPT TO received message"
-msgInvalidCmdDataSequence - custom invalid commandDATA sequence message-msgInvalidCmdDataSequence="Invalid command DATA sequence message"
-msgDataReceived - customDATA received message-msgDataReceived="DATA received message"
-msgMsgSizeIsTooBig - custom size is too big message-msgMsgSizeIsTooBig="Message size is too big"
-msgMsgReceived - custom received message body message-msgMsgReceived="Message has been received"
-msgInvalidCmdRsetSequence - custom invalid commandRSET sequence message-msgInvalidCmdRsetSequence="Invalid command RSET sequence message"
-msgInvalidCmdRsetArg - custom invalid commandRSET message-msgInvalidCmdRsetArg="Invalid command RSET message"
-msgRsetReceived - customRSET received message-msgRsetReceived="RSET received message"
-msgNoopReceived - customNOOP received message-msgNoopReceived="NOOP received message"
-msgQuitCmd - customQUIT command message-msgQuitCmd="Quit command message"

Other options

Available not configurationsmtpmock options:

Flag descriptionExample of usage
-v - Just prints currentsmtpmock binary build data (version, commit, datetime). Doesn't run the server.-v

Stopping server

smtpmock accepts 3 shutdown signals:SIGINT,SIGQUIT,SIGTERM.

Implemented SMTP commands

idCommandSequenceableAvailable argsExample of usage
1HELOnodomain name,localhost,ip address,[ip address]HELO example.com
1EHLOnodomain name,localhost,ip address,[ip address]EHLO example.com
2MAIL FROMcan be used after command with id1 and greateremail address,<email address>,localhost email address,<localhost email address>MAIL FROM: user@domain.com
3RCPT TOcan be used after command with id2 and greateremail address,<email address>,localhost email address,<localhost email address>RCPT TO: user@domain.com
4DATAcan be used after command with id3-DATA
5RSETcan be used after command with id1 and greater-RSET
6NOOPno-NOOP
7QUITno-QUIT

Please note in case when same command used more the one time during same session all saved data upper this command will be erased.

Contributing

Bug reports and pull requests are welcome on GitHub athttps://github.com/mocktools/go-smtp-mock. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to theContributor Covenant code of conduct. Please check theopen tickets. Be sure to follow Contributor Code of Conduct below and ourContributing Guidelines.

License

This golang package is available as open source under the terms of theMIT License.

Code of Conduct

Everyone interacting in thesmtpmock project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow thecode of conduct.

Credits

Versioning

smtpmock usesSemantic Versioning 2.0.0


[8]ページ先頭

©2009-2025 Movatter.jp