zammad/app/models/failed_email.rb
2026-01-02 15:41:09 +02:00

106 lines
2.3 KiB
Ruby

# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
class FailedEmail < ApplicationModel
def reprocess(params = {})
ticket, _article, _user, _mail = Channel::EmailParser.new.process_with_timeout(params, data)
raise __('Unknown error: Could not create a ticket from this email.') if !ticket
destroy
ticket
rescue => e
self.retries += 1
self.parsing_error = e
save!
message = "Can't reprocess failed email '#{id}'. This was attempt # #{retries}."
puts "ERROR: #{message}" # rubocop:disable Rails/Output
puts "ERROR: #{e.inspect}" # rubocop:disable Rails/Output
Rails.logger.error message
Rails.logger.error e
false
end
def parsing_error=(input)
message = case input
when StandardError
"#{input.inspect}\n#{input.backtrace&.join("\n")}"
else
input
end
write_attribute :parsing_error, message
end
def self.by_filepath(filepath)
id = Pathname
.new(filepath)
.basename
.to_s
.delete_suffix('.eml')
return if id.include?('.')
find_by(id:)
end
def self.reprocess_all(params = {})
reorder(id: :desc)
.in_batches
.each_record
.select { |elem| elem.reprocess(params) }
.map { |elem| "#{elem.id}.eml" }
end
def self.generate_path
Rails.root.join('tmp', "failed-email-#{SecureRandom.uuid}")
end
def self.export_all(path = generate_path)
in_batches
.each_record
.map { |elem| elem.export(path) }
end
def export(path = self.class.generate_path)
FileUtils.mkdir_p(path)
full_path = path.join("#{id}.eml")
File.binwrite full_path, data
full_path
end
def self.import_all(path)
Dir
.each_child(path)
.filter_map do |filename|
next if !filename.ends_with?('.eml')
import(path.join(filename))
end
end
def self.import(filepath)
failed_email = FailedEmail.by_filepath(filepath.basename)
return if !failed_email
new_data = File.binread filepath
if new_data != failed_email.data
failed_email.data = new_data
failed_email.parsing_error = nil
failed_email.save!
end
return if !failed_email.reprocess
filepath.unlink
filepath
end
end