Browse Source

Fixes #5334 - MS365 failing to send articles when mail headers too long.

Co-authored-by: Martin Gruner <mg@zammad.com>
Rolf Schmidt 6 months ago
parent
commit
a3a5c82f61
2 changed files with 42 additions and 8 deletions
  1. 15 8
      app/models/ticket.rb
  2. 27 0
      spec/models/ticket_spec.rb

+ 15 - 8
app/models/ticket.rb

@@ -563,18 +563,25 @@ result
 
 =end
 
-  def get_references(ignore = [])
+  # limited by 32kb (https://github.com/zammad/zammad/issues/5334)
+  # https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-service-description/exchange-online-limits
+  def get_references(ignore = [], max_length: 30_000)
     references = []
-    Ticket::Article.select('in_reply_to, message_id').where(ticket_id: id).each do |article|
+    counter    = 0
+    Ticket::Article.select('in_reply_to, message_id').where(ticket_id: id).reverse_each do |article|
+      new_references = []
+      if article.message_id.present?
+        new_references.push article.message_id
+      end
       if article.in_reply_to.present?
-        references.push article.in_reply_to
+        new_references.push article.in_reply_to
       end
-      next if article.message_id.blank?
+      new_references -= ignore
 
-      references.push article.message_id
-    end
-    ignore.each do |item|
-      references.delete(item)
+      counter += new_references.join.length
+      break if counter > max_length
+
+      references.unshift(*new_references)
     end
     references
   end

+ 27 - 0
spec/models/ticket_spec.rb

@@ -1979,4 +1979,31 @@ RSpec.describe Ticket, type: :model do
       end
     end
   end
+
+  describe '#get_references' do
+    let!(:ticket) { create(:ticket) }
+    let!(:articles) { create_list(:ticket_article, 10, ticket: ticket, reply_to: nil) }
+
+    before do
+      articles.each do |article|
+        article.update(message_id: SecureRandom.uuid)
+      end
+    end
+
+    it 'does return references' do
+      expect(ticket.get_references.count).to eq(10)
+    end
+
+    it 'does return references by limit' do
+      expect(ticket.get_references([], max_length: articles.last.message_id.length * 3).count).to eq(3)
+    end
+
+    it 'does return last 3 references by limit' do
+      expect(ticket.get_references([], max_length: articles.last.message_id.length * 3)).to eq(articles.map(&:message_id)[-3..])
+    end
+
+    it 'does ignore references' do
+      expect(ticket.get_references([articles.last.message_id])).not_to include(articles.last.message_id)
+    end
+  end
 end