💎 Ruby SMTP mock - flexible Ruby wrapper over smtpmock
. Mimic any 📤 SMTP server behavior for your test environment and even more.
Table of Contents
- Features
- Requirements
- Installation
- Usage
- Dependency manager
- Available flags
- DSL
- Available server options
- Example of usage
- RSpec integration
- SmtpMock RSpec helper
- SmtpMock RSpec interface
- Dependency manager
- Contributing
- License
- Code of Conduct
- Credits
- Versioning
- Changelog
Features
- Ability to handle configurable behavior and life cycles of SMTP mock server(s)
- Dynamic/manual port assignment
- Test framework agnostic (it's PORO, so you can use it outside of
RSpec
,Test::Unit
orMiniTest
) - Simple and intuitive DSL
- RSpec integration out of the box
- Includes easy system dependency manager
Requirements
Ruby MRI 2.5.0+
Installation
Add this line to your application's Gemfile
:
group :development, :test do
gem 'smtp_mock', require: false
end
And then execute:
bundle
Or install it yourself as:
gem install smtp_mock
Then install smtpmock
as system dependency:
bundle exec smtp_mock -i ~
Usage
Dependency manager
This gem includes easy system dependency manager. Run bundle exec smtp_mock
with options for manage smtpmock
system dependency.
Available flags
Flag | Description | Example of usage |
---|---|---|
-s , --sudo
|
Run command as sudo | bundle exec smtp_mock -s -i ~ |
-i , --install=PATH
|
Install smtpmock to the existing path |
bundle exec smtp_mock -i ~/existent_dir |
-u , --uninstall
|
Uninstall smtpmock
|
bundle exec smtp_mock -u |
-g , --upgrade
|
Upgrade to latest version of smtpmock
|
bundle exec smtp_mock -g |
-v , --version
|
Prints current version of smtpmock
|
bundle exec smtp_mock -v |
-h , --help
|
Prints help | bundle exec smtp_mock -h |
DSL
Available server options
Example of usage kwarg | Description |
---|---|
host: '0.0.0.0' |
Host address where smtpmock will run. It's equal to 127.0.0.1 by default |
port: 2525 |
Server port number. If not specified it will be assigned dynamically |
log: true |
Enables log server activity. Disabled by default |
session_timeout: 60 |
Session timeout in seconds. It's equal to 30 seconds by default |
shutdown_timeout: 5 |
Graceful shutdown timeout in seconds. It's equal to 1 second by default |
fail_fast: true |
Enables fail fast scenario. Disabled by default |
multiple_rcptto: true |
Enables multiple RCPT TO receiving scenario. Disabled by default |
multiple_message_receiving: true |
Enables multiple message receiving scenario. Disabled by default |
blacklisted_helo_domains: %w[a.com b.com] |
Blacklisted HELO domains |
blacklisted_mailfrom_emails: %w[a@a.com b@b.com] |
Blacklisted MAIL FROM emails |
blacklisted_rcptto_emails: %w[c@c.com d@d.com] |
blacklisted RCPT TO emails |
not_registered_emails: %w[e@e.com f@f.com] |
Not registered (non-existent) RCPT TO emails |
response_delay_helo: 2 |
HELO response delay in seconds. It's equal to 0 seconds by default |
response_delay_mailfrom: 2 |
MAIL FROM response delay in seconds. It's equal to 0 seconds by default |
response_delay_rcptto: 2 |
RCPT TO response delay in seconds. It's equal to 0 seconds by default |
response_delay_data: 2 |
DATA response delay in seconds. It's equal to 0 seconds by default |
response_delay_message: 2 |
Message response delay in seconds. It's equal to 0 seconds by default |
response_delay_rset: 2 |
RSET response delay in seconds. It's equal to 0 seconds by default |
response_delay_quit: 2 |
QUIT response delay in seconds. It's equal to 0 seconds by default |
msg_size_limit: 42 |
Message body size limit in bytes. It's equal to 10485760 bytes by default |
msg_greeting: 'Greeting message' |
Custom server greeting message |
msg_invalid_cmd: 'Invalid command message' |
Custom invalid command message |
msg_invalid_cmd_helo_sequence: 'Invalid command HELO sequence message' |
Custom invalid command HELO sequence message |
msg_invalid_cmd_helo_arg: 'Invalid command HELO argument message' |
Custom invalid command HELO argument message |
msg_helo_blacklisted_domain: 'Blacklisted domain message' |
Custom HELO blacklisted domain message |
msg_helo_received: 'HELO received message' |
Custom HELO received message |
msg_invalid_cmd_mailfrom_sequence: 'Invalid command MAIL FROM sequence message' |
Custom invalid command MAIL FROM sequence message |
msg_invalid_cmd_mailfrom_arg: 'Invalid command MAIL FROM argument message' |
Custom invalid command MAIL FROM argument message |
msg_mailfrom_blacklisted_email: 'Blacklisted email message' |
Custom MAIL FROM blacklisted email message |
msg_mailfrom_received: 'MAIL FROM received message' |
Custom MAIL FROM received message |
msg_invalid_cmd_rcptto_sequence: 'Invalid command RCPT TO sequence message' |
Custom invalid command RCPT TO sequence message |
msg_invalid_cmd_rcptto_arg: 'Invalid command RCPT TO argument message' |
Custom invalid command RCPT TO argument message |
msg_rcptto_not_registered_email: 'Not registered email message' |
Custom RCPT TO not registered email message |
msg_rcptto_blacklisted_email: 'Blacklisted email message' |
Custom RCPT TO blacklisted email message |
msg_rcptto_received: 'RCPT TO received message' |
Custom RCPT TO received message |
msg_invalid_cmd_data_sequence: 'Invalid command DATA sequence message' |
Custom invalid command DATA sequence message |
msg_data_received: 'DATA received message' |
Custom DATA received message |
msg_msg_size_is_too_big: 'Message size is too big' |
Custom size is too big message |
msg_invalid_cmd_rset_sequence: 'Invalid command RSET sequence message' |
Custom invalid command RSET sequence message |
msg_invalid_cmd_rset_arg: 'Invalid command RSET argument message' |
Custom invalid command RSET argument message |
msg_rset_received: 'RSET received message' |
Custom RSET received message |
msg_quit_cmd: 'Quit command message' |
Custom quit command message |
Example of usage
# Public SmtpMock interface
# Without kwargs creates SMTP mock server with default behavior.
# A free port for server will be randomly assigned in the range
# from 49152 to 65535. Returns current smtp mock server instance
smtp_mock_server = SmtpMock.start_server(not_registered_emails: %w[user@example.com]) # => SmtpMock::Server instance
# returns current smtp mock server port
smtp_mock_server.port # => 55640
# returns current smtp mock server process identification number (PID)
smtp_mock_server.pid # => 38195
# returns current smtp mock server version
smtp_mock_server.version # => '1.5.2'
# interface for graceful shutdown current smtp mock server
smtp_mock_server.stop # => true
# interface for force shutdown current smtp mock server
smtp_mock_server.stop! # => true
# interface to check state of current smtp mock server
# returns true if server is running, otherwise returns false
smtp_mock_server.active? # => true
# returns list of running smtp mock servers
SmtpMock.running_servers # => [SmtpMock::Server instance]
# interface to stop all running smtp mock servers
SmtpMock.stop_running_servers! # => true
RSpec integration
Require this either in your Gemfile or in RSpec's support scripts. So either:
# Gemfile
group :test do
gem 'rspec'
gem 'smtp_mock', require: 'smtp_mock/test_framework/rspec'
end
or
# spec/support/config/smtp_mock.rb
require 'smtp_mock/test_framework/rspec'
SmtpMock RSpec helper
Just add SmtpMock::TestFramework::RSpec::Helper
if you wanna use shortcut smtp_mock_server
for SmtpMock server instance inside of your RSpec.describe
blocks:
# spec/support/config/smtp_mock.rb
RSpec.configure do |config|
config.include SmtpMock::TestFramework::RSpec::Helper
end
# your awesome smtp_client_spec.rb
RSpec.describe SmtpClient do
subject(:smtp_response) do
described_class.call(
host: 'localhost',
port: smtp_mock_server.port,
mailfrom: mailfrom,
rcptto: rcptto,
message: message
)
end
let(:mailfrom) { 'sender@example.com' }
let(:rcptto) { 'receiver@example.com' }
let(:message) { 'Email message context' }
let(:expected_response_message) { '250 Custom successful response' }
before { smtp_mock_server(msg_msg_received: expected_response_message) }
it do
expect(smtp_response).to be_success
expect(smtp_response).to have_status(expected_response_status)
expect(smtp_response).to have_message_context(expected_response_message)
end
end
SmtpMock RSpec interface
If you won't use SmtpMock::TestFramework::RSpec::Helper
you can use SmtpMock::TestFramework::RSpec::Interface
directly instead:
SmtpMock::TestFramework::RSpec::Interface.start_server # creates and runs SmtpMock server instance
SmtpMock::TestFramework::RSpec::Interface.stop_server! # stops and clears current SmtpMock server instance
SmtpMock::TestFramework::RSpec::Interface.clear_server! # clears current SmtpMock server instance
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/mocktools/ruby-smtp-mock. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct. Please check the open tickets. Be sure to follow Contributor Code of Conduct below and our Contributing Guidelines.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the SmtpMock project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Credits
- The Contributors for code and awesome suggestions
- The Stargazers for showing their support
Versioning
SmtpMock uses Semantic Versioning 2.0.0