Skip to content

Commit 82c0e47

Browse files
author
David Zuckerman
committed
custom health check to verify mail password is set
added test for new mail password healthcheck removed stubbing for gpg key added connection checks for smtp in okcomputer renamed mail-connectivity check, generalized public errors moved okcomputer registration for mail-connectivity outside of class added tests for mail_connectivity rubocop syntax fixes
1 parent ba0dbd0 commit 82c0e47

3 files changed

Lines changed: 201 additions & 18 deletions

File tree

config/initializers/okcomputer.rb

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require 'net/smtp'
4+
35
# Health check configuration
46

57
OkComputer.logger = Rails.logger
@@ -18,11 +20,49 @@ def check
1820
end
1921
end
2022

23+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24+
class MailConnectivityCheck < OkComputer::Check
25+
26+
# Check that the mail password is set
27+
def check
28+
settings = ActionMailer::Base.smtp_settings
29+
begin
30+
Net::SMTP.start(
31+
settings[:address],
32+
settings[:port],
33+
settings[:domain],
34+
settings[:user_name],
35+
settings[:password],
36+
settings[:authentication],
37+
tls: true
38+
) { mark_message 'Connection for smtp successful' }
39+
rescue Net::SMTPAuthenticationError => e
40+
mark_failure
41+
Rails.logger.warn "SMTP authentication error: #{e}"
42+
mark_message 'SMTP Error: Authentication failed. Check logs for more details'
43+
rescue Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError => e
44+
mark_failure
45+
Rails.logger.warn "SMTP Error: #{e}"
46+
mark_message 'SMTP error. Check logs for more details'
47+
rescue IOError, Net::ReadTimeout => e
48+
mark_failure
49+
Rails.logger.warn "SMTP Timeout: #{e}"
50+
mark_message 'SMTP Connection error: Timeout. Check logs for more details'
51+
rescue StandardError => e
52+
# Catch any other unexpected errors
53+
mark_failure
54+
Rails.logger.warn "SMTP standard error: #{e}"
55+
mark_message 'SMTP ERROR: Could not connect. Check logs for more details'
56+
end
57+
end
58+
end
59+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
60+
2161
# Ensure Alma API is working.
2262
OkComputer::Registry.register 'alma-patron-lookup', AlmaPatronCheck.new
2363

2464
# Ensure database migrations have been run.
2565
OkComputer::Registry.register 'database-migrations', OkComputer::ActiveRecordMigrationsCheck.new
2666

27-
# Ensure connectivity to the mail system.
28-
OkComputer::Registry.register 'action-mailer', OkComputer::ActionMailerCheck.new
67+
# Ensure SMTP can connect
68+
OkComputer::Registry.register 'mail-connectivity', MailConnectivityCheck.new if ActionMailer::Base.delivery_method == :smtp
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
require 'rails_helper'
2+
require 'net/smtp'
3+
4+
RSpec.describe MailConnectivityCheck do
5+
subject(:check) { described_class.new }
6+
7+
let(:smtp_settings) do
8+
{
9+
address: 'smtp.example.com',
10+
port: 587,
11+
domain: 'example.com',
12+
user_name: 'user',
13+
password: 'password',
14+
authentication: 'plain',
15+
tls: true
16+
}
17+
end
18+
19+
before do
20+
allow(ActionMailer::Base).to receive(:smtp_settings).and_return(smtp_settings)
21+
allow(Rails.logger).to receive(:warn)
22+
end
23+
24+
describe '#check' do
25+
context 'when SMTP connection succeeds' do
26+
before do
27+
allow(Net::SMTP).to receive(:start).and_yield
28+
end
29+
30+
it 'marks the check as successful' do
31+
check.check
32+
33+
expect(check.success?).to be(true)
34+
expect(check.message).to eq('Connection for smtp successful')
35+
end
36+
end
37+
38+
context 'when authentication fails' do
39+
before do
40+
allow(Net::SMTP).to receive(:start)
41+
.and_raise(Net::SMTPAuthenticationError.new('auth failed'))
42+
end
43+
44+
it 'marks failure and logs authentication error' do
45+
check.check
46+
47+
expect(check.success?).to be(false)
48+
expect(check.message)
49+
.to eq('SMTP Error: Authentication failed. Check logs for more details')
50+
expect(Rails.logger)
51+
.to have_received(:warn).with(/SMTP authentication error/)
52+
end
53+
end
54+
55+
context 'when SMTP protocol errors occur' do
56+
[
57+
Net::SMTPServerBusy,
58+
Net::SMTPSyntaxError,
59+
Net::SMTPFatalError,
60+
Net::SMTPUnknownError
61+
].each do |error_class|
62+
it "handles #{error_class.name}" do
63+
allow(Net::SMTP).to receive(:start)
64+
.and_raise(error_class.new('smtp error'))
65+
66+
check.check
67+
68+
expect(check.success?).to be(false)
69+
expect(check.message)
70+
.to eq('SMTP error. Check logs for more details')
71+
expect(Rails.logger)
72+
.to have_received(:warn).with(/SMTP Error/)
73+
end
74+
end
75+
end
76+
77+
context 'when a timeout occurs' do
78+
[IOError, Net::ReadTimeout].each do |error_class|
79+
it "handles #{error_class.name}" do
80+
allow(Net::SMTP).to receive(:start)
81+
.and_raise(error_class.new('timeout'))
82+
83+
check.check
84+
85+
expect(check.success?).to be(false)
86+
expect(check.message)
87+
.to eq('SMTP Connection error: Timeout. Check logs for more details')
88+
expect(Rails.logger)
89+
.to have_received(:warn).with(/SMTP Timeout/)
90+
end
91+
end
92+
end
93+
94+
context 'when an unexpected error occurs' do
95+
before do
96+
allow(Net::SMTP).to receive(:start)
97+
.and_raise(StandardError.new('failed'))
98+
end
99+
100+
it 'marks failure and logs standard error' do
101+
check.check
102+
103+
expect(check.success?).to be(false)
104+
expect(check.message)
105+
.to eq('SMTP ERROR: Could not connect. Check logs for more details')
106+
expect(Rails.logger)
107+
.to have_received(:warn).with(/SMTP standard error/)
108+
end
109+
end
110+
end
111+
end

spec/request/okcomputer_spec.rb

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,61 @@
11
require 'rails_helper'
22

33
RSpec.describe 'OKComputer', type: :request do
4-
before { allow(Alma::User).to receive(:find).and_return(Alma::User.new) }
4+
before do
5+
allow(Alma::User).to receive(:find).and_return(Alma::User.new)
6+
end
57

68
it 'is mounted at /okcomputer' do
79
get '/okcomputer'
810
expect(response).to have_http_status :ok
911
end
1012

11-
it 'returns all checks to /health' do
12-
get '/health'
13-
expect(response.parsed_body.keys).to match_array %w[
14-
action-mailer
15-
alma-patron-lookup
16-
default
17-
database
18-
database-migrations
19-
]
20-
pending 'https://github.com/emmahsax/okcomputer/pull/21'
21-
expect(response).to have_http_status :ok
13+
context 'without SMTP enabled' do
14+
before do
15+
allow(ActionMailer::Base).to receive(:delivery_method).and_return(:test)
16+
17+
OkComputer::Registry.instance_variable_set(:@checks, {})
18+
load Rails.root.join('config/initializers/okcomputer.rb')
19+
end
20+
21+
it 'returns checks to /health' do
22+
get '/health'
23+
expect(response.parsed_body.keys).to match_array %w[
24+
default
25+
database
26+
alma-patron-lookup
27+
database-migrations
28+
]
29+
end
2230
end
2331

24-
it 'fails when Alma lookups fail' do
25-
expect(Alma::User).to receive(:find).and_raise('Uh oh!')
26-
get '/health'
27-
expect(response).not_to have_http_status :ok
32+
context 'with SMTP enabled' do
33+
before do
34+
allow(ActionMailer::Base).to receive(:delivery_method).and_return(:smtp)
35+
allow(Net::SMTP).to receive(:start)
36+
37+
OkComputer::Registry.instance_variable_set(:@checks, {})
38+
load Rails.root.join('config/initializers/okcomputer.rb')
39+
end
40+
41+
it 'returns all checks to /health' do
42+
get '/health'
43+
expect(response.parsed_body.keys).to match_array %w[
44+
default
45+
database
46+
alma-patron-lookup
47+
database-migrations
48+
mail-connectivity
49+
]
50+
end
51+
end
52+
53+
context 'when Alma lookups fail' do
54+
it 'returns a non-200 response' do
55+
expect(Alma::User).to receive(:find).and_raise('Uh oh!')
56+
get '/health'
57+
expect(response).not_to have_http_status :ok
58+
end
2859
end
60+
2961
end

0 commit comments

Comments
 (0)