Commit 2d2b2dc
Changed files (15)
bin
exe
lib
spec
bin/console
@@ -1,7 +1,8 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
-require "bundler/setup"
-require "minbox"
+require 'bundler/setup'
+require 'minbox'
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "minbox"
# require "pry"
# Pry.start
-require "irb"
+require 'irb'
IRB.start(__FILE__)
exe/minbox
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
-require "minbox/cli"
+require 'minbox/cli'
Minbox::Cli::Application.start(ARGV)
lib/minbox/cli.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'mail'
require 'net/smtp'
require 'openssl'
@@ -8,7 +10,7 @@ require 'minbox'
module Minbox
module Cli
class Application < Thor
- package_name "minbox"
+ package_name 'minbox'
desc 'client <HOST> <PORT>', 'SMTP client'
def client(host = 'localhost', port = 25)
@@ -19,7 +21,7 @@ module Minbox
body "#{Time.now} This is a test message."
end
Net::SMTP.start(host, port) do |smtp|
- smtp.debug_output= Minbox.logger
+ smtp.debug_output = Minbox.logger
smtp.send_message(mail.to_s, 'me+1@example.org', 'them+1@example.com')
smtp.send_message(mail.to_s, 'me+2@example.org', 'them+2@example.com')
end
lib/minbox/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Minbox
class Client
attr_reader :server, :socket, :logger
@@ -37,47 +39,47 @@ module Minbox
private
def quit
- write "221 Bye"
+ write '221 Bye'
close
end
- def data(line, &block)
- write "354 End data with <CR><LF>.<CR><LF>"
+ def data(line)
+ write '354 End data with <CR><LF>.<CR><LF>'
body = []
line = read
until line.nil? || line.match(/^\.\r\n$/)
body << line
line = read
end
- write "250 OK"
- block.call(Mail.new(body.join)) unless body.empty?
+ write '250 OK'
+ yield(Mail.new(body.join)) unless body.empty?
end
- def rcpt_to(line)
- write "250 OK"
+ def rcpt_to(_line)
+ write '250 OK'
end
- def mail_from(line)
- write "250 OK"
+ def mail_from(_line)
+ write '250 OK'
end
def ehlo(line)
- _ehlo, _client_domain = line.split(" ")
+ _ehlo, _client_domain = line.split(' ')
write "250-#{server.host} offers a warm hug of welcome"
- write "250-8BITMIME"
- write "250-ENHANCEDSTATUSCODES"
- #write "250 STARTTLS"
- write "250-AUTH PLAIN LOGIN"
- write "250 OK"
+ write '250-8BITMIME'
+ write '250-ENHANCEDSTATUSCODES'
+ # write "250 STARTTLS"
+ write '250-AUTH PLAIN LOGIN'
+ write '250 OK'
end
def helo(line)
- _ehlo, _client_domain = line.split(" ")
+ _ehlo, _client_domain = line.split(' ')
write "250 #{server.host}"
end
def start_tls
- write "220 Ready to start TLS"
+ write '220 Ready to start TLS'
socket = OpenSSL::SSL::SSLSocket.new(@socket, server.ssl_context)
socket.sync_close = true
@@ -99,10 +101,12 @@ module Minbox
data = read
end
parts = Base64.decode64(data).split("\0")
- username, password = parts[-2], parts[-1]
+ username = parts[-2]
+ password = parts[-1]
logger.debug("#{username}:#{password}")
return write '535 Authenticated failed - protocol error' unless username && password
- write "235 2.7.0 Authentication successful"
+
+ write '235 2.7.0 Authentication successful'
end
def auth_login(line)
@@ -118,7 +122,8 @@ module Minbox
logger.debug("#{username}:#{password}")
return write '535 Authenticated failed - protocol error' unless username && password
- write "235 2.7.0 Authentication successful"
+
+ write '235 2.7.0 Authentication successful'
end
def write(message)
lib/minbox/core.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Minbox
def self.logger
@logger ||= Logger.new(STDOUT)
lib/minbox/publisher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'redis'
module Minbox
@@ -51,7 +53,7 @@ module Minbox
end
def publish(mail)
- @redis.publish("minbox", mail.to_s)
+ @redis.publish('minbox', mail.to_s)
end
end
@@ -59,7 +61,7 @@ module Minbox
attr_reader :dir
def initialize(dir = Dir.pwd)
- @dir = File.join(dir, "tmp")
+ @dir = File.join(dir, 'tmp')
FileUtils.mkdir_p(@dir)
end
lib/minbox/server.rb
@@ -1,5 +1,8 @@
+# frozen_string_literal: true
+
module Minbox
class Server
+ SUBJECT = '/C=CA/ST=AB/L=Calgary/O=minbox/OU=development/CN=minbox'
attr_reader :host, :port, :logger, :key
def initialize(host = 'localhost', port = 25, tls = false, logger = Minbox.logger)
@@ -18,7 +21,7 @@ module Minbox
logger.debug("Starting server on port #{port}...")
@server = TCPServer.new(port.to_i)
@server = upgrade(@server) if tls?
- logger.debug("Server started!")
+ logger.debug('Server started!')
loop do
handle(@server.accept, &block)
@@ -55,9 +58,8 @@ module Minbox
server
end
- def certificate_for(private_key)
+ def certificate_for(private_key, subject = SUBJECT)
certificate = OpenSSL::X509::Certificate.new
- subject = '/C=CA/ST=AB/L=Calgary/O=minbox/OU=development/CN=minbox'
certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse(subject)
certificate.not_before = Time.now
certificate.not_after = certificate.not_before + 30 * 24 * 60 * 60 # 30 days
@@ -71,14 +73,14 @@ module Minbox
def apply_ski_extension_to(certificate)
extensions = OpenSSL::X509::ExtensionFactory.new
- extensions.subject_certificate = certificate
- extensions.issuer_certificate = certificate
- certificate.add_extension(
- extensions.create_extension('subjectKeyIdentifier', 'hash', false)
- )
- certificate.add_extension(
- extensions.create_extension('keyUsage', 'keyEncipherment,digitalSignature', true)
- )
+ extensions.subject_certificate =
+ extensions.issuer_certificate = certificate
+ [
+ ['subjectKeyIdentifier', 'hash', false],
+ ['keyUsage', 'keyEncipherment,digitalSignature', true],
+ ].each do |x|
+ certificate.add_extension(extensions.create_extension(x[0], x[1], x[2]))
+ end
end
end
end
lib/minbox/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Minbox
- VERSION = "0.1.4"
+ VERSION = '0.1.4'
end
lib/minbox.rb
@@ -1,12 +1,14 @@
+# frozen_string_literal: true
+
require 'base64'
require 'logger'
require 'socket'
-require "minbox/core"
-require "minbox/publisher"
-require "minbox/client"
-require "minbox/server"
-require "minbox/version"
+require 'minbox/core'
+require 'minbox/publisher'
+require 'minbox/client'
+require 'minbox/server'
+require 'minbox/version'
module Minbox
class Error < StandardError; end
spec/minbox/server_spec.rb
@@ -1,11 +1,13 @@
+# frozen_string_literal: true
+
require 'spec_helper'
RSpec.describe Minbox::Server do
- describe "#handle" do
+ describe '#handle' do
let(:host) { 'localhost' }
let(:port) { 8080 }
- context "when handling a simple client" do
+ context 'when handling a simple client' do
def create_mail(to: Faker::Internet.email, from: Faker::Internet.email)
Mail.new do |x|
x.from from
@@ -16,7 +18,7 @@ RSpec.describe Minbox::Server do
end
end
- context "when sending a single email" do
+ context 'when sending a single email' do
let(:result) do
Net::SMTP.start(host, port) do |smtp|
smtp.send_message(create_mail.to_s, Faker::Internet.email, Faker::Internet.email)
@@ -24,10 +26,10 @@ RSpec.describe Minbox::Server do
end
specify { expect(result).to be_success }
- specify { expect(result.status.to_i).to eql(250) }
+ specify { expect(result.status.to_i).to be(250) }
end
- context "when sending multiple emails" do
+ context 'when sending multiple emails' do
let(:n) { rand(10) }
let(:result) do
Net::SMTP.start(host, port) do |smtp|
@@ -40,7 +42,7 @@ RSpec.describe Minbox::Server do
specify { expect(result).to eql(n) }
end
- context "with plain authentication" do
+ context 'with plain authentication' do
let(:result) do
Net::SMTP.start(host, port, 'mail.from.domain', 'username', 'password', :plain) do |smtp|
smtp.send_message(create_mail.to_s, Faker::Internet.email, Faker::Internet.email)
@@ -48,10 +50,10 @@ RSpec.describe Minbox::Server do
end
specify { expect(result).to be_success }
- specify { expect(result.status.to_i).to eql(250) }
+ specify { expect(result.status.to_i).to be(250) }
end
- context "with login authentication" do
+ context 'with login authentication' do
let(:result) do
Net::SMTP.start(host, port, 'mail.from.domain', 'username', 'password', :login) do |smtp|
smtp.send_message(create_mail.to_s, Faker::Internet.email, Faker::Internet.email)
@@ -59,25 +61,25 @@ RSpec.describe Minbox::Server do
end
specify { expect(result).to be_success }
- specify { expect(result.status.to_i).to eql(250) }
+ specify { expect(result.status.to_i).to be(250) }
end
- context "with attachment" do
+ context 'with attachment' do
let(:result) do
mail = create_mail do |x|
x.add_file __FILE__
end
Net::SMTP.start(host, port, 'mail.from.domain', 'username', 'password', :login) do |smtp|
- smtp.debug_output= STDOUT
+ smtp.debug_output = STDOUT
smtp.send_message(mail.to_s, Faker::Internet.email, Faker::Internet.email)
end
end
specify { expect(result).to be_success }
- specify { expect(result.status.to_i).to eql(250) }
+ specify { expect(result.status.to_i).to be(250) }
end
- context "with html part" do
+ context 'with html part' do
let(:result) do
mail = create_mail do |x|
x.text_part do
@@ -93,16 +95,16 @@ RSpec.describe Minbox::Server do
end
specify { expect(result).to be_success }
- specify { expect(result.status.to_i).to eql(250) }
+ specify { expect(result.status.to_i).to be(250) }
end
- context "when upgrading to tls" do
+ context 'when upgrading to tls' do
let(:result) do
`(echo 'QUIT'; sleep 1) | openssl s_client -connect #{host}:#{port} -starttls smtp 2>&1`
end
specify { expect(result).to end_with("DONE\n") }
- specify { expect(result).to include("250 OK") }
+ specify { expect(result).to include('250 OK') }
end
end
end
spec/minbox_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe Minbox do
specify { expect(Minbox::VERSION).not_to be_nil }
end
spec/spec_helper.rb
@@ -1,12 +1,14 @@
-require "bundler/setup"
-require "minbox"
+# frozen_string_literal: true
+
+require 'bundler/setup'
+require 'minbox'
require 'net/smtp'
require 'mail'
require 'faker'
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
- config.example_status_persistence_file_path = ".rspec_status"
+ config.example_status_persistence_file_path = '.rspec_status'
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
.rubocop.yml
@@ -0,0 +1,91 @@
+require:
+ - rubocop/cop/internal_affairs
+ - rubocop-rspec
+
+AllCops:
+ Exclude:
+ - 'coverage/**/*'
+ - 'pkg/**/*'
+ - 'tmp/**/*'
+ - 'vendor/**/*'
+ TargetRubyVersion: 2.6
+
+Layout/AlignParameters:
+ Enabled: true
+ EnforcedStyle: with_fixed_indentation
+ IndentationWidth: 2
+
+Layout/ClassStructure:
+ Enabled: true
+ Categories:
+ module_inclusion:
+ - include
+ - prepend
+ - extend
+ ExpectedOrder:
+ - module_inclusion
+ - constants
+ - public_class_methods
+ - initializer
+ - instance_methods
+ - protected_methods
+ - private_methods
+
+Layout/EndOfLine:
+ EnforcedStyle: lf
+
+Layout/IndentArray:
+ EnforcedStyle: consistent
+
+Layout/IndentHeredoc:
+ EnforcedStyle: active_support
+
+Layout/MultilineMethodCallIndentation:
+ Enabled: true
+ EnforcedStyle: indented
+
+Lint/AmbiguousBlockAssociation:
+ Exclude:
+ - 'spec/**/*.rb'
+
+Lint/InterpolationCheck:
+ Exclude:
+ - 'spec/**/*.rb'
+
+Metrics/BlockLength:
+ Exclude:
+ - '**/*.rake'
+ - '*.gemspec'
+ - 'Rakefile'
+ - 'spec/**/*.rb'
+
+Metrics/ModuleLength:
+ Exclude:
+ - 'spec/**/*.rb'
+
+Metrics/LineLength:
+ Exclude:
+ - 'spec/**/*.rb'
+ IgnoredPatterns:
+ - '^#*'
+
+Style/Documentation:
+ Enabled: false
+
+Style/EachWithObject:
+ Enabled: false
+
+Style/StringLiterals:
+ EnforcedStyle: 'single_quotes'
+
+Style/TrailingCommaInArrayLiteral:
+ Enabled: false
+
+Style/TrailingCommaInHashLiteral:
+ Enabled: false
+
+RSpec/NamedSubject:
+ Enabled: false
+
+RSpec/NestedGroups:
+ Max: 4
Gemfile
@@ -1,4 +1,6 @@
-source "https://rubygems.org"
+# frozen_string_literal: true
+
+source 'https://rubygems.org'
# Specify your gem's dependencies in minbox.gemspec
gemspec
Gemfile.lock
@@ -9,15 +9,26 @@ PATH
GEM
remote: https://rubygems.org/
specs:
+ ast (2.4.0)
+ bundler-audit (0.6.1)
+ bundler (>= 1.2.0, < 3)
+ thor (~> 0.18)
concurrent-ruby (1.1.4)
diff-lcs (1.3)
faker (1.9.3)
i18n (>= 0.7)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
+ jaro_winkler (1.5.2)
mail (2.7.1)
mini_mime (>= 0.1.1)
mini_mime (1.0.1)
+ parallel (1.14.0)
+ parser (2.6.0.0)
+ ast (~> 2.4.0)
+ powerpack (0.1.2)
+ psych (3.1.0)
+ rainbow (3.0.0)
rake (10.5.0)
redis (4.1.0)
rspec (3.8.0)
@@ -33,17 +44,33 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
+ rubocop (0.65.0)
+ jaro_winkler (~> 1.5.1)
+ parallel (~> 1.10)
+ parser (>= 2.5, != 2.5.1.1)
+ powerpack (~> 0.1)
+ psych (>= 3.1.0)
+ rainbow (>= 2.2.2, < 4.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (~> 1.4.0)
+ rubocop-rspec (1.32.0)
+ rubocop (>= 0.60.0)
+ ruby-progressbar (1.10.0)
thor (0.20.3)
+ unicode-display_width (1.4.1)
PLATFORMS
ruby
DEPENDENCIES
bundler (~> 2.0)
+ bundler-audit (~> 0.6)
faker (~> 1.9)
minbox!
rake (~> 10.0)
rspec (~> 3.0)
+ rubocop (~> 0.52)
+ rubocop-rspec (~> 1.22)
BUNDLED WITH
2.0.1