probe_spec.rb 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe EmailHelper::Probe, integration: true, required_envs: %w[MAIL_SERVER MAIL_ADDRESS MAIL_PASS] do
  4. let(:expected_result_failed) { { result: 'failed', message: message_human, } }
  5. let(:expected_result_invalid) { { result: 'invalid', message_human: message_human, } }
  6. before do
  7. allow(EmailHelper).to receive(:mx_records).and_return([ ENV['MAIL_SERVER'] ])
  8. end
  9. shared_examples 'probe tests with invalid result' do
  10. it 'contains all information for an invalid result' do
  11. expect(probe_result).to include(
  12. result: expected_result_invalid[:result],
  13. message_human: be_in(expected_result_invalid[:message_human]),
  14. settings: include(
  15. options: include(
  16. host: host,
  17. ),
  18. ),
  19. )
  20. end
  21. end
  22. describe '#inbound' do
  23. subject(:probe_result) { described_class.inbound(inbound_params) }
  24. let(:inbound_params) do
  25. {
  26. adapter: adapter,
  27. options: {
  28. host: host,
  29. port: port,
  30. ssl: true,
  31. user: user,
  32. password: password,
  33. ssl_verify: false,
  34. },
  35. }
  36. end
  37. let(:adapter) { 'imap' }
  38. let(:port) { 993 }
  39. let(:user) { 'some@example.com' }
  40. let(:password) { 'password' }
  41. context 'with unknown adapter' do
  42. let(:adapter) { 'imap2' }
  43. let(:host) { 'nonexisting_host' }
  44. let(:message_human) { "Unknown adapter '#{adapter}'" }
  45. it { is_expected.to eq(expected_result_failed) }
  46. end
  47. context 'when network issues are present' do
  48. let(:host) { 'nonexisting_host' }
  49. let(:message_human) { 'The hostname could not be found.' }
  50. include_examples 'probe tests with invalid result'
  51. end
  52. context 'when an imap service with a blocked port is used' do
  53. let(:host) { '127.0.0.1' }
  54. let(:port) { 8 } # no service to be expected
  55. let(:message_human) { 'The connection was refused.' }
  56. include_examples 'probe tests with invalid result'
  57. end
  58. context 'when host is not reachable' do
  59. let(:host) { nil }
  60. let(:message_human) { [ 'This host cannot be reached.', 'There is no route to this host.' ] }
  61. before do
  62. allow(Socket).to receive(:tcp).and_raise(Errno::EHOSTUNREACH)
  63. end
  64. include_examples 'probe tests with invalid result'
  65. end
  66. context 'when authentication fails' do
  67. let(:host) { ENV['MAIL_SERVER'] }
  68. let(:message_human) { [ 'Authentication failed.', 'This host cannot be reached.' ] }
  69. include_examples 'probe tests with invalid result'
  70. end
  71. context 'when doing a real test' do
  72. let(:host) { ENV['MAIL_SERVER'] }
  73. let(:user) { ENV['MAIL_ADDRESS'] }
  74. let(:password) { ENV['MAIL_PASS'] }
  75. it { is_expected.to include(result: 'ok') }
  76. end
  77. end
  78. describe '#outbound' do
  79. subject(:probe_result) { described_class.outbound(outbound_params, user) }
  80. let(:outbound_params) do
  81. {
  82. adapter: adapter,
  83. options: {
  84. host: host,
  85. port: port,
  86. start_tls: true,
  87. user: user,
  88. password: password,
  89. ssl_verify: false,
  90. },
  91. }
  92. end
  93. let(:adapter) { 'smtp' }
  94. let(:port) { 25 }
  95. let(:user) { 'some@example.com' }
  96. let(:password) { 'password' }
  97. context 'with unknown adapter' do
  98. let(:adapter) { 'imap2' }
  99. let(:host) { 'nonexisting_host' }
  100. let(:message_human) { "Unknown adapter '#{adapter}'" }
  101. it { is_expected.to eq(expected_result_failed) }
  102. end
  103. context 'when network issues are present' do
  104. let(:host) { 'nonexisting_host' }
  105. let(:message_human) { 'The hostname could not be found.' }
  106. include_examples 'probe tests with invalid result'
  107. end
  108. context 'when an imap service with a blocked port is used' do
  109. let(:host) { '127.0.0.1' }
  110. let(:port) { 8 } # no service to be expected
  111. let(:message_human) { 'The connection was refused.' }
  112. include_examples 'probe tests with invalid result'
  113. end
  114. context 'when host is not reachable' do
  115. let(:host) { nil }
  116. let(:message_human) { [ 'This host cannot be reached.', 'There is no route to this host.' ] }
  117. before do
  118. allow(TCPSocket).to receive(:open).and_raise(Errno::EHOSTUNREACH)
  119. end
  120. include_examples 'probe tests with invalid result'
  121. end
  122. context 'when authentication fails' do
  123. let(:host) { ENV['MAIL_SERVER'] }
  124. let(:port) { 25 }
  125. let(:message_human) { 'Authentication failed.' }
  126. include_examples 'probe tests with invalid result'
  127. end
  128. context 'when doing a real test' do
  129. let(:host) { ENV['MAIL_SERVER'] }
  130. let(:port) { 25 }
  131. let(:user) { ENV['MAIL_ADDRESS'] }
  132. let(:password) { ENV['MAIL_PASS'] }
  133. let(:outbound_params) do
  134. {
  135. adapter: adapter,
  136. options: {
  137. host: host,
  138. port: port,
  139. user: user,
  140. ssl: false,
  141. password: password,
  142. ssl_verify: false,
  143. },
  144. }
  145. end
  146. it { is_expected.to include(result: 'ok') }
  147. end
  148. end
  149. describe '#full' do
  150. subject(:probe_result) { described_class.full(full_params) }
  151. let(:full_params) do
  152. {
  153. email: email,
  154. password: password,
  155. ssl_verify: (ssl_verify if defined? ssl_verify),
  156. }
  157. end
  158. context 'when providing invalid information' do
  159. let(:email) { 'invalid_format' }
  160. let(:password) { 'somepass' }
  161. it 'contains all information for an invalid probe' do
  162. expect(probe_result)
  163. .to include(
  164. result: 'invalid'
  165. )
  166. .and not_include('setting')
  167. end
  168. end
  169. context 'when doing real tests' do
  170. let(:email) { ENV['MAIL_ADDRESS'] }
  171. let(:password) { ENV['MAIL_PASS'] }
  172. shared_examples 'do real testing' do
  173. it 'contains all information for a successful probe' do
  174. expect(probe_result).to include(result: 'ok')
  175. .and include(
  176. setting: include(
  177. inbound: include(
  178. options: include(
  179. host: host
  180. ),
  181. ),
  182. ),
  183. )
  184. .and include(
  185. setting: include(
  186. outbound: include(
  187. options: include(
  188. host: host,
  189. ),
  190. ),
  191. ),
  192. )
  193. end
  194. end
  195. context 'when doing a real test' do
  196. let(:host) { ENV['MAIL_SERVER'] }
  197. context 'with ssl verification turned on' do
  198. let(:ssl_verify) { true }
  199. before do
  200. # Import CA certificate into the trust store.
  201. SSLCertificate.create!(certificate: Rails.root.join('spec/fixtures/files/imap/ca.crt').read)
  202. end
  203. include_examples 'do real testing'
  204. end
  205. context 'with ssl verification turned off' do
  206. let(:ssl_verify) { false }
  207. include_examples 'do real testing'
  208. end
  209. end
  210. end
  211. end
  212. end