smtp_spec.rb 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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: 'some_recipient@example_not_existing_what_ever.com', subject: 'some subject', message_id: 'some@id', body: 'some message delivery test') }
  26. before do
  27. freeze_time
  28. email_address.update!(channel_id: channel.id)
  29. ticket && article
  30. end
  31. context 'when modifying channel options', :aggregate_failures do
  32. let(:outbound) { { adapter: 'sendmail' } }
  33. it 'updates article delivery preferences' do
  34. expect(article.preferences).not_to include(:delivery_retry,
  35. :delivery_status,
  36. :delivery_status_date,
  37. :delivery_status_message)
  38. TicketArticleCommunicateEmailJob.new.perform(article.id)
  39. expect(article.reload.preferences).to include(delivery_retry: 1,
  40. delivery_status: 'success',
  41. delivery_status_date: be_present,
  42. delivery_status_message: be_nil)
  43. # Send with invalid smtp settings.
  44. channel.options.tap do |options|
  45. options['outbound'] = {
  46. adapter: 'smtp',
  47. options: {
  48. host: 'mx1.example.com',
  49. port: 25,
  50. start_tls: true,
  51. user: 'not_existing',
  52. password: 'not_existing',
  53. },
  54. }
  55. end
  56. channel.save!
  57. expect { TicketArticleCommunicateEmailJob.new.perform(article.id) }.to raise_error(RuntimeError)
  58. expect(article.reload.preferences).to include(delivery_retry: 2,
  59. delivery_status: 'fail',
  60. delivery_status_date: be_present,
  61. delivery_status_message: be_present)
  62. # Send with valid smtp settings.
  63. channel.options.tap do |options|
  64. options['outbound'] = {
  65. adapter: 'smtp',
  66. options: {
  67. host: server_host,
  68. port: 25,
  69. start_tls: true,
  70. user: server_login,
  71. password: server_password,
  72. ssl_verify: false,
  73. },
  74. }
  75. end
  76. channel.save!
  77. TicketArticleCommunicateEmailJob.new.perform(article.id)
  78. expect(article.reload.preferences).to include(delivery_retry: 3,
  79. delivery_status: 'success',
  80. delivery_status_date: be_present,
  81. delivery_status_message: be_nil)
  82. end
  83. end
  84. context 'when encounters sending errors', :aggregate_failures, performs_jobs: true do
  85. let(:state_name) { 'closed' }
  86. let(:outbound) do
  87. {
  88. adapter: 'smtp',
  89. options: {
  90. host: 'mx1.example.com',
  91. port: 25,
  92. start_tls: true,
  93. user: 'not_existing',
  94. password: 'not_existing',
  95. },
  96. }
  97. end
  98. it 'retries delivery in expected intervals' do
  99. expect do
  100. perform_enqueued_jobs
  101. end.to have_performed_job(TicketArticleCommunicateEmailJob)
  102. expect(ticket.reload.articles.count).to eq(1)
  103. expect(ticket.state.name).to eq('closed')
  104. expect(article.reload.preferences).to include(delivery_retry: 1,
  105. delivery_status: 'fail',
  106. delivery_status_date: be_present,
  107. delivery_status_message: be_present)
  108. expect do
  109. perform_enqueued_jobs
  110. end.to have_performed_job(TicketArticleCommunicateEmailJob).at(25.seconds.from_now)
  111. expect(article.reload.preferences).to include(delivery_retry: 2,
  112. delivery_status: 'fail',
  113. delivery_status_date: be_present,
  114. delivery_status_message: be_present)
  115. expect(ticket.reload.articles.count).to eq(1)
  116. expect(ticket.state.name).to eq('closed')
  117. expect do
  118. perform_enqueued_jobs
  119. end.to have_performed_job(TicketArticleCommunicateEmailJob).at(50.seconds.from_now)
  120. expect(article.reload.preferences).to include(delivery_retry: 3,
  121. delivery_status: 'fail',
  122. delivery_status_date: be_present,
  123. delivery_status_message: be_present)
  124. expect(ticket.reload.articles.count).to eq(1)
  125. expect(ticket.state.name).to eq('closed')
  126. expect do
  127. perform_enqueued_jobs
  128. end.to raise_error(RuntimeError).and have_performed_job(TicketArticleCommunicateEmailJob).at(75.seconds.from_now)
  129. expect(article.reload.preferences).to include(delivery_retry: 4,
  130. delivery_status: 'fail',
  131. delivery_status_date: be_present,
  132. delivery_status_message: be_present)
  133. expect(ticket.reload.articles.count).to eq(2)
  134. expect(ticket.state).to eq(Ticket::State.find_by(default_follow_up: true))
  135. expect(ticket.articles.last).to have_attributes(sender: Ticket::Article::Sender.lookup(name: 'System'),
  136. preferences: include(delivery_message: true,
  137. delivery_article_id_related: article.id,
  138. notification: true))
  139. end
  140. end
  141. end