diff --git a/MimeKit/Header.cs b/MimeKit/Header.cs index b3faa2956a..ac0c48db44 100644 --- a/MimeKit/Header.cs +++ b/MimeKit/Header.cs @@ -677,7 +677,7 @@ static byte[] EncodeReceivedHeader (ParserOptions options, FormatOptions format, { var tokens = new List (); var rawValue = encoding.GetBytes (value); - var encoded = new ValueStringBuilder (128); + var encoded = new ValueStringBuilder (rawValue.Length); int lineLength = field.Length + 1; bool date = false; int index = 0; @@ -825,7 +825,7 @@ static void EncodeDkimHeaderList (FormatOptions format, ref ValueStringBuilder e static byte[] EncodeDkimOrArcSignatureHeader (ParserOptions options, FormatOptions format, Encoding encoding, string field, string value) { - var encoded = new ValueStringBuilder (128); + var encoded = new ValueStringBuilder (value.Length); int lineLength = field.Length + 1; int index = 0; @@ -884,9 +884,58 @@ static byte[] EncodeDkimOrArcSignatureHeader (ParserOptions options, FormatOptio return encoding.GetBytes (encoded.ToString ()); } + static byte[] EncodeDispositionNotificationOptions (ParserOptions options, FormatOptions format, Encoding encoding, string field, string value) + { + var encoded = new ValueStringBuilder (value.Length); + int lineLength = field.Length + 1; + int index = 0; + + while (index < value.Length) { + using var parameter = new ValueStringBuilder (128); + + while (index < value.Length && IsWhiteSpace (value[index])) + index++; + + int startIndex = index; + + while (index < value.Length && value[index] != '=') { + if (!IsWhiteSpace (value[index])) + parameter.Append (value[index]); + index++; + } + + while (index < value.Length && value[index] != ';') { + if (!IsWhiteSpace (value[index])) + parameter.Append (value[index]); + index++; + } + + if (index < value.Length && value[index] == ';') { + parameter.Append (';'); + index++; + } + + if (lineLength + parameter.Length + 1 > format.MaxLineLength && encoded.Length > 0) { + encoded.Append (format.NewLine); + encoded.Append ('\t'); + lineLength = 1; + } else { + encoded.Append (' '); + lineLength++; + } + + encoded.Append (parameter.AsSpan ()); + lineLength += parameter.Length; + } + + encoded.Append (format.NewLine); + + return encoding.GetBytes (encoded.ToString ()); + } + static byte[] EncodeReferencesHeader (ParserOptions options, FormatOptions format, Encoding encoding, string field, string value) { - var encoded = new ValueStringBuilder (128); + var encoded = new ValueStringBuilder (value.Length); int lineLength = field.Length + 1; int count = 0; @@ -1179,7 +1228,7 @@ static bool IsMailingListCommandSpecial (char c) static byte[] EncodeMailingListCommandHeader (ParserOptions options, FormatOptions format, Encoding encoding, string field, string value) { - var encoded = new ValueStringBuilder (128); + var encoded = new ValueStringBuilder (value.Length); int lineLength = field.Length + 1; int index = 0; @@ -1309,6 +1358,8 @@ protected virtual byte[] FormatRawValue (FormatOptions format, Encoding encoding return EncodeContentDisposition (Options, format, encoding, Field, value); case HeaderId.ContentType: return EncodeContentType (Options, format, encoding, Field, value); + case HeaderId.DispositionNotificationOptions: + return EncodeDispositionNotificationOptions (Options, format, encoding, Field, value); case HeaderId.ArcAuthenticationResults: case HeaderId.AuthenticationResults: return EncodeAuthenticationResultsHeader (Options, format, encoding, Field, value); @@ -1362,6 +1413,8 @@ internal byte[] GetRawValue (FormatOptions format) return ReformatContentDisposition (Options, format, CharsetUtils.UTF8, Field, rawValue); case HeaderId.ContentType: return ReformatContentType (Options, format, CharsetUtils.UTF8, Field, rawValue); + case HeaderId.DispositionNotificationOptions: + return rawValue; case HeaderId.ArcAuthenticationResults: case HeaderId.AuthenticationResults: // Note: No text that can be internationalized. diff --git a/UnitTests/HeaderTests.cs b/UnitTests/HeaderTests.cs index 6d410e8895..da7ce37c7d 100644 --- a/UnitTests/HeaderTests.cs +++ b/UnitTests/HeaderTests.cs @@ -723,5 +723,21 @@ public void TestEncodeListCommandHeaderWithExtremelyLongUrl () Assert.AreEqual (expected.ReplaceLineEndings (), result); } + + [Test] + public void TestEncodeDispositionNotificationOptions () + { + const string value = "signed-receipt-protocol=optional,pkcs7-signature;signed-receipt-micalg=optional,sha1,sha128,sha256"; + const string expected = " signed-receipt-protocol=optional,pkcs7-signature;\r\n\tsigned-receipt-micalg=optional,sha1,sha128,sha256\r\n"; + var header = new Header (HeaderId.DispositionNotificationOptions, value); + + var options = FormatOptions.Default.Clone (); + options.NewLineFormat = NewLineFormat.Dos; + options.International = false; + + var result = Encoding.UTF8.GetString (header.GetRawValue (options)); + + Assert.AreEqual (expected.ReplaceLineEndings (), result); + } } }