@@ -85,6 +85,29 @@ void AddTextArgument (StringBuilder builder, List<object> args, string text, ref
8585 args . Add ( buffer ) ;
8686 }
8787
88+ void AddKeywordArgument ( StringBuilder builder , List < object > args , string text , ref string charset )
89+ {
90+ // Note: Technically, the IMAP RFC states that keywords are not allowed to start with '\',
91+ // but some non-rfc-compliant IMAP servers do it anyway, so we need to allow it here.
92+ // See https://github.com/jstedfast/MailKit/issues/1906 for details.
93+ int startIndex = text [ 0 ] == '\\ ' ? 1 : 0 ;
94+ bool isAtom = true ;
95+
96+ for ( int i = startIndex ; i < text . Length ; i ++ ) {
97+ if ( ! ImapCommand . IsAtom ( text [ i ] ) ) {
98+ isAtom = false ;
99+ break ;
100+ }
101+ }
102+
103+ if ( isAtom ) {
104+ builder . Append ( "%s" ) ;
105+ args . Add ( text ) ;
106+ } else {
107+ AddTextArgument ( builder , args , text , ref charset ) ;
108+ }
109+ }
110+
88111 void BuildQuery ( StringBuilder builder , SearchQuery query , List < object > args , bool parens , ref string charset )
89112 {
90113 AnnotationSearchQuery annotation ;
@@ -196,7 +219,7 @@ void BuildQuery (StringBuilder builder, SearchQuery query, List<object> args, bo
196219 case SearchTerm . Keyword :
197220 text = ( TextSearchQuery ) query ;
198221 builder . Append ( "KEYWORD " ) ;
199- AddTextArgument ( builder , args , text . Text , ref charset ) ;
222+ AddKeywordArgument ( builder , args , text . Text , ref charset ) ;
200223 break ;
201224 case SearchTerm . LargerThan :
202225 numeric = ( NumericSearchQuery ) query ;
@@ -236,7 +259,7 @@ void BuildQuery (StringBuilder builder, SearchQuery query, List<object> args, bo
236259 case SearchTerm . NotKeyword :
237260 text = ( TextSearchQuery ) query ;
238261 builder . Append ( "UNKEYWORD " ) ;
239- AddTextArgument ( builder , args , text . Text , ref charset ) ;
262+ AddKeywordArgument ( builder , args , text . Text , ref charset ) ;
240263 break ;
241264 case SearchTerm . NotRecent :
242265 builder . Append ( "OLD" ) ;
0 commit comments