@@ -479,49 +479,71 @@ func rspamdQuery(s *session, token string) {
479479 }
480480
481481 if len (rr .Headers .Add ) > 0 {
482- authHeaders := map [string ]string {}
482+ // Authentication headers from Rspamd are in the form of:
483+ // "ARC-Seal": { "order": 1, "value": text }
484+ // "ARC-Authentication-Results": { "order": 1, "value": text }
485+ // "ARC-Message-Signature": { "order": 1, "value": text }
486+ // Unfortunately they all have an order of 1,
487+ // thought they should be ordered as per RFC 8617
488+ // so we give them a fixed order, and shift everything after
489+ orderFix := map [string ]int {
490+ "ARC-Seal" : 0 ,
491+ "ARC-Message-Signature" : 1 ,
492+ "ARC-Authentication-Results" : 2 ,
493+ }
494+
495+ // headers, indexed by order
496+ headers := map [int ]map [string ]string {- 1 : {}}
483497
484498 for h , t := range rr .Headers .Add {
499+ if h == "" {
500+ continue
501+ }
502+
485503 switch v := t .(type ) {
486- /**
487- * Authentication headers from Rspamd are in the form of:
488- * ARC-Seal : { order : 1, value : text }
489- * ARC-Message-Signature : { order : 1, value : text }
490- * Unfortunately they all have an order of 1, so we
491- * make a map of them and print them in proper order.
492- */
504+ case string :
505+ // Regular headers from Rspamd used to be plain strings
506+ // continue to accept this old format, just in case
507+
508+ headers [- 1 ][h ] = v
509+
493510 case map [string ]interface {}:
494- if h != "" {
495- v , ok := v ["value" ].(string )
496- if ok {
497- authHeaders [h ] = v
511+ // They are now in the form { "value": text, "order": -1 }
512+ // so we convert them, and use `order` as the map index
513+
514+ vv , ok_v := v ["value" ].(string )
515+ vo , ok_o := v ["order" ].(float64 )
516+ if ok_v && ok_o {
517+ vo := int (vo )
518+ if vo > - 1 {
519+ o_fix , ok := orderFix [h ]
520+ if ok {
521+ vo = o_fix
522+ } else {
523+ // if not in orderFix, add after
524+ vo = vo + len (orderFix )
525+ }
526+ }
527+
528+ if _ , ok := headers [vo ]; ! ok {
529+ headers [vo ] = map [string ]string {}
498530 }
531+ headers [vo ][h ] = vv
499532 }
500- /**
501- * Regular X-Spam headers from Rspamd are plain strings.
502- * Insert these at the top.
503- */
504- case string :
505- writeHeader (s , token , h , v )
533+
506534 default :
507535 }
508536 }
509537
510- /**
511- * Prefix auth headers to incoming mail in proper order.
512- */
513- if len (authHeaders ) > 0 {
514- hdrs := []string {
515- "ARC-Seal" ,
516- "ARC-Message-Signature" ,
517- "ARC-Authentication-Results" ,
518- "Authentication-Results" ,
519- }
520-
521- for _ , h := range hdrs {
522- if authHeaders [h ] != "" {
523- writeHeader (s , token , h , authHeaders [h ])
524- }
538+ // add the headers in order
539+ orders := make ([]int , 0 , len (headers ))
540+ for k := range headers {
541+ orders = append (orders , k )
542+ }
543+ sort .Ints (orders )
544+ for _ , o := range orders {
545+ for h , v := range headers [o ] {
546+ writeHeader (s , token , h , v )
525547 }
526548 }
527549 }
0 commit comments