smtp_spec.rb 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Channel::Driver::Smtp, integration: true, required_envs: %w[MAIL_SERVER MAIL_ADDRESS MAIL_PASS] do
  4. let(:server_host) { ENV['MAIL_SERVER'] }
  5. let(:server_login) { ENV['MAIL_ADDRESS'] }
  6. let(:server_password) { ENV['MAIL_PASS'] }
  7. let(:email_address) { create(:email_address, name: 'me Helpdesk', email: "some-zammad-#{server_login}") }
  8. let(:group) { create(:group, name: 'DeliverTest', email_address: email_address) }
  9. let(:channel) do
  10. create(:email_channel,
  11. group: group,
  12. outbound: outbound,
  13. inbound: {
  14. adapter: 'imap',
  15. options: {
  16. host: 'mx1.example.com',
  17. user: 'example',
  18. password: 'some_pw',
  19. ssl: true,
  20. }
  21. })
  22. end
  23. let(:state_name) { 'new' }
  24. let(:ticket) { create(:ticket, title: 'some delivery test', group: group, state_name: state_name) }
  25. let(:article) { create(:ticket_article, :outbound_email, ticket: ticket, to: Faker::Internet.unique.email, subject: 'some subject', message_id: 'some@id', body: 'some message delivery test') }
  26. before do
  27. ENV['ZAMMAD_MAIL_TO_FILE'] = '1'
  28. freeze_time
  29. email_address.update!(channel_id: channel.id)
  30. ticket && article
  31. end
  32. context 'when modifying channel options', :aggregate_failures do
  33. let(:outbound) { { adapter: 'sendmail' } }
  34. it 'updates article delivery preferences' do
  35. expect(article.preferences).not_to include(:delivery_retry,
  36. :delivery_status,
  37. :delivery_status_date,
  38. :delivery_status_message)
  39. TicketArticleCommunicateEmailJob.new.perform(article.id)
  40. expect(article.reload.preferences).to include(delivery_retry: 1,
  41. delivery_status: 'success',
  42. delivery_status_date: be_present,
  43. delivery_status_message: be_nil)
  44. # Send with invalid smtp settings.
  45. channel.options.tap do |options|
  46. options['outbound'] = {
  47. adapter: 'smtp',
  48. options: {
  49. host: 'mx1.example.com',
  50. port: 25,
  51. start_tls: true,
  52. user: 'not_existing',
  53. password: 'not_existing',
  54. },
  55. }
  56. end
  57. channel.save!
  58. expect { TicketArticleCommunicateEmailJob.new.perform(article.id) }.to raise_error(RuntimeError)
  59. expect(article.reload.preferences).to include(delivery_retry: 2,
  60. delivery_status: 'fail',
  61. delivery_status_date: be_present,
  62. delivery_status_message: be_present)
  63. # Send with valid smtp settings.
  64. channel.options.tap do |options|
  65. options['outbound'] = {
  66. adapter: 'smtp',
  67. options: {
  68. host: server_host,
  69. port: 25,
  70. start_tls: true,
  71. user: server_login,
  72. password: server_password,
  73. ssl_verify: false,
  74. },
  75. }
  76. end
  77. channel.save!
  78. TicketArticleCommunicateEmailJob.new.perform(article.id)
  79. expect(article.reload.preferences).to include(delivery_retry: 3,
  80. delivery_status: 'success',
  81. delivery_status_date: be_present,
  82. delivery_status_message: be_nil)
  83. end
  84. end
  85. context 'when encounters sending errors', :aggregate_failures, performs_jobs: true do
  86. let(:state_name) { 'closed' }
  87. let(:outbound) do
  88. {
  89. adapter: 'smtp',
  90. options: {
  91. host: 'mx1.example.com',
  92. port: 25,
  93. start_tls: true,
  94. user: 'not_existing',
  95. password: 'not_existing',
  96. },
  97. }
  98. end
  99. it 'retries delivery in expected intervals' do
  100. expect do
  101. perform_enqueued_jobs
  102. end.to have_performed_job(TicketArticleCommunicateEmailJob)
  103. expect(ticket.reload.articles.count).to eq(1)
  104. expect(ticket.state.name).to eq('closed')
  105. expect(article.reload.preferences).to include(delivery_retry: 1,
  106. delivery_status: 'fail',
  107. delivery_status_date: be_present,
  108. delivery_status_message: be_present)
  109. expect do
  110. perform_enqueued_jobs
  111. end.to have_performed_job(TicketArticleCommunicateEmailJob).at(25.seconds.from_now)
  112. expect(article.reload.preferences).to include(delivery_retry: 2,
  113. delivery_status: 'fail',
  114. delivery_status_date: be_present,
  115. delivery_status_message: be_present)
  116. expect(ticket.reload.articles.count).to eq(1)
  117. expect(ticket.state.name).to eq('closed')
  118. expect do
  119. perform_enqueued_jobs
  120. end.to have_performed_job(TicketArticleCommunicateEmailJob).at(50.seconds.from_now)
  121. expect(article.reload.preferences).to include(delivery_retry: 3,
  122. delivery_status: 'fail',
  123. delivery_status_date: be_present,
  124. delivery_status_message: be_present)
  125. expect(ticket.reload.articles.count).to eq(1)
  126. expect(ticket.state.name).to eq('closed')
  127. expect do
  128. perform_enqueued_jobs
  129. end.to raise_error(RuntimeError).and have_performed_job(TicketArticleCommunicateEmailJob).at(75.seconds.from_now)
  130. expect(article.reload.preferences).to include(delivery_retry: 4,
  131. delivery_status: 'fail',
  132. delivery_status_date: be_present,
  133. delivery_status_message: be_present)
  134. expect(ticket.reload.articles.count).to eq(2)
  135. expect(ticket.state).to eq(Ticket::State.find_by(default_follow_up: true))
  136. expect(ticket.articles.last).to have_attributes(sender: Ticket::Article::Sender.lookup(name: 'System'),
  137. preferences: include(delivery_message: true,
  138. delivery_article_id_related: article.id,
  139. notification: true))
  140. end
  141. end
  142. end