--- mail_handler.rb.orig	2021-07-24 01:39:32.077948785 +0200
+++ mail_handler.rb	2022-02-26 20:19:23.485414674 +0100
@@ -65,7 +65,7 @@
     %w(project status tracker category priority assigned_to fixed_version).each do |option|
       options[:issue][option.to_sym] = env[option] if env[option]
     end
-    %w(allow_override unknown_user no_permission_check no_account_notice no_notification default_group project_from_subaddress).each do |option|
+    %w(allow_override unknown_user no_permission_check no_account_notice no_notification default_group project_from_subaddress ext_ref reprefix).each do |option|
       options[option.to_sym] = env[option] if env[option]
     end
     if env['private']
@@ -188,6 +188,40 @@
   end
 
   def dispatch_to_default
+    extref_name = handler_options[:ext_ref]
+    extref = get_keyword(extref_name, {}, false) if extref_name
+    Rails.logger.error "MailHandlerExt: found ext ref #{extref_name} = #{extref}"
+    if extref_name && extref
+      begin
+        query = IssueQuery.new(:name => '_',
+                               :filters => { 'status_id' => {:operator => "o", :values => [""]}})
+        cf = query.issue_custom_fields.visible.where(:is_filter => true).where(:name => extref_name).first
+        if cf
+          query.add_filter "cf_#{cf.id}", '=', [extref]
+        end
+        issues=query.issues
+        issue_id = nil
+        if issues.count > 10
+          Rails.logger.error "MailHandler: found #{issues.count} open issues with #{extref_name}: #{extref}. Too much. Ignoring external reference."
+        elsif issues.count > 1
+          Rails.logger.warn "MailHandler: found #{issues.count} open issues with #{extref_name}: #{extref}:"
+          Rails.logger.warn "MailHandler: issues: #{issues.map{ |i| i.id.to_s }.join(", ")}"
+          issue_id = issues.first.id
+        elsif issues.count == 1
+          issue_id = issues.first.id
+        else
+          Rails.logger.warn "MailHandler: no open issues found with #{extref_name}: #{extref}:"
+        end
+        #Rails.logger.error "MailHandler: query #{query}"
+        #Rails.logger.error "MailHandler: query.statement #{query.statement}"
+        if !issue_id.nil?
+          Rails.logger.error "MailHandler: ext ref maps mail to issue #{issue_id}"
+          return receive_issue_reply(issue_id)
+        end
+      rescue Exception => e
+        Rails.logger.error "MailHandlerExt: error quer ext ref #{extref}: #{e.message}"
+      end
+    end
     receive_issue
   end
 
@@ -214,6 +248,7 @@
       issue.subject = '(no subject)'
     end
     issue.description = cleaned_up_text_body
+    issue.description << "\n\n-- \n" << headers_as_text
     issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
     issue.is_private = (handler_options[:issue][:is_private] == '1')
 
@@ -225,6 +260,27 @@
     issue
   end
 
+  def headers_as_text
+    headers_txt = ''
+    headers_txt << header_as_text('from')
+    headers_txt << header_as_text('to')
+    headers_txt << header_as_text('cc')
+    return headers_txt
+  end
+
+  def header_as_text(h)
+    value = email.header[h]
+    ret = ''
+    if value
+      ret << h << ': ' << value.to_s << "\n"
+    end
+    return ret
+  rescue Exception => e
+    ret = ''
+    ret << h << ": error reading value\n"
+    return ret
+  end
+
   # Adds a note to an existing issue
   def receive_issue_reply(issue_id, from_journal=nil)
     issue = Issue.find_by_id(issue_id)
@@ -248,6 +304,7 @@
     issue.safe_attributes = issue_attributes_from_keywords(issue)
     issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
     journal.notes = cleaned_up_text_body
+    journal.notes << "\n\n-- \n" << header_as_text('subject') << headers_as_text
 
     # add To and Cc as watchers before saving so the watchers can reply to Redmine
     add_watchers(issue)
@@ -339,28 +396,33 @@
     end
   end
 
-  def get_keyword(attr, options={})
+  def get_keyword(attr, options={}, remove_line=true)
     @keywords ||= {}
     if @keywords.has_key?(attr)
       @keywords[attr]
     else
-      @keywords[attr] = begin
+      value = begin
         override = options.key?(:override) ?
           options[:override] :
           (handler_options[:allow_override] & [attr.to_s.downcase.gsub(/\s+/, '_'), 'all']).present?
 
-        if override && (v = extract_keyword!(cleaned_up_text_body, attr, options[:format]))
+        if override && (v = extract_keyword!(cleaned_up_text_body, attr, options[:format], remove_line))
           v
         elsif !handler_options[:issue][attr].blank?
           handler_options[:issue][attr]
         end
       end
+      if remove_line
+        #Rails.logger.warn "MailHandler: reading and removed attr #{attr.to_s}: '#{value}'"
+        @keywords[attr] = value
+      end
+      value
     end
   end
 
   # Destructively extracts the value for +attr+ in +text+
   # Returns nil if no matching keyword found
-  def extract_keyword!(text, attr, format=nil)
+  def extract_keyword!(text, attr, format=nil, remove_line=true)
     keys = [attr.to_s.humanize]
     if attr.is_a?(Symbol)
       if user && user.language.present?
@@ -374,10 +436,14 @@
     keys.collect! {|k| Regexp.escape(k)}
     format ||= '.+'
     keyword = nil
-    regexp = /^(#{keys.join('|')})[ \t]*:[ \t]*(#{format})\s*$/i
+    prefix = handler_options[:reprefix]
+    prefix ||= ''
+    regexp = /^#{prefix}(#{keys.join('|')})[ \t]*:[ \t]*(?<kval>#{format})\s*$/i
     if m = text.match(regexp)
-      keyword = m[2].strip
-      text.sub!(regexp, '')
+      keyword = m[:kval].strip
+      if remove_line
+        text.sub!(regexp, '')
+      end
     end
     keyword
   end
