]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: Add UTF8=ACCEPT capability (RFC 6855)
authorArnt Gulbrandsen <arnt@gulbrandsen.priv.no>
Tue, 22 Nov 2022 11:38:14 +0000 (12:38 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 28 Jun 2024 09:48:14 +0000 (09:48 +0000)
This adds the capability and accepts UTF8 quoted-strings.

The SEARCH command is changed as required by RFC 6855, section 3, final
paragraph. There are no changes to the searching, as 6855 only changes
changes the syntax.

This does not add any kind of downgrading. Before this change, Dovecot would
accept an APPEND of a message such as

   From: grå@grå.org
   Subject: grå
   ...

and would just-send-8 that to any IMAP clients. This change maintains that policy.

configure.ac
src/imap/cmd-search.c
src/imap/imap-client.c
src/imap/imap-client.h
src/lib-storage/mail-storage.h

index 66e3f5eaba14101ceb0e164a3e0fdb87a7dc8a44..b8c9459fb6dfdb99647086d826143edd197dd82d 100644 (file)
@@ -50,10 +50,12 @@ AC_ARG_ENABLE([pro-build],
   [is_pro_build=no]
 )
 
+experimental_capabilities=""
 AC_ARG_ENABLE(experimental-mail-utf8,
 AS_HELP_STRING([--enable-experimental-mail-utf8], [Enable experimental support for SMTPUTF8 and UTF8=ACCEPT]),
        AS_IF([test x$enableval = xyes], [
               AC_DEFINE([EXPERIMENTAL_MAIL_UTF8],, [Build with SMTPUTF8 and UTF8=ACCEPT support])
+              experimental_capabilities="${experimental_capabilities} UTF8-ACCEPT"
        ])
 )
 
@@ -747,7 +749,7 @@ dnl **
 dnl IDLE doesn't really belong to banner. It's there just to make Blackberries
 dnl happy, because otherwise BIS server disables push email.
 capability_banner="IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE"
-capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY PREVIEW STATUS=SIZE SAVEDATE COMPRESS=DEFLATE INPROGRESS"
+capability="$capability_banner SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE SNIPPET=FUZZY PREVIEW=FUZZY PREVIEW STATUS=SIZE SAVEDATE COMPRESS=DEFLATE INPROGRESS ${experimental_capabilities}"
 AC_DEFINE_UNQUOTED(CAPABILITY_STRING, "$capability", [IMAP capabilities])
 AC_DEFINE_UNQUOTED(CAPABILITY_BANNER_STRING, "$capability_banner", [IMAP capabilities advertised in banner])
 
index 52be6f61dfb1c29f2b99ba33827b1b46f8de543e..616193159267c6d9889068b8072d2d9a84cb2313 100644 (file)
@@ -28,6 +28,12 @@ bool cmd_search(struct client_command_context *cmd)
 
        if (imap_arg_atom_equals(args, "CHARSET")) {
                /* CHARSET specified */
+               if ((client_enabled_mailbox_features(cmd->client) & MAILBOX_FEATURE_UTF8ACCEPT) != 0) {
+                       /* RFC 6855 Section 3 bans CHARSET after UTF8=ACCEPT */
+                       client_send_command_error(cmd,
+                               "Cannot set search charset when using UTF8=ACCEPT");
+                       return TRUE;
+               }
                if (!imap_arg_get_astring(&args[1], &charset)) {
                        client_send_command_error(cmd,
                                "Invalid charset argument.");
index 42c5d0cd8f447d9993e7e814a152fc3aee04faeb..8e5bfa62f32682e0eb3b6a0f6b7011579fdebeb9 100644 (file)
@@ -46,6 +46,7 @@ unsigned int imap_client_count = 0;
 
 unsigned int imap_feature_condstore = UINT_MAX;
 unsigned int imap_feature_qresync = UINT_MAX;
+unsigned int imap_feature_utf8accept = UINT_MAX;
 
 static const char *client_command_state_names[] = {
        "wait-input",
@@ -1596,6 +1597,14 @@ static void imap_client_enable_qresync(struct client *client)
        client_enable(client, imap_feature_condstore);
 }
 
+#ifdef EXPERIMENTAL_MAIL_UTF8
+static void imap_client_enable_utf8accept(struct client *client)
+{
+       if (client->mailbox != NULL)
+               mailbox_enable(client->mailbox, MAILBOX_FEATURE_UTF8ACCEPT);
+}
+#endif
+
 enum mailbox_feature client_enabled_mailbox_features(struct client *client)
 {
        enum mailbox_feature mailbox_features = 0;
@@ -1672,6 +1681,11 @@ void clients_init(void)
        imap_feature_qresync =
                imap_feature_register("QRESYNC", MAILBOX_FEATURE_CONDSTORE,
                                      imap_client_enable_qresync);
+#ifdef EXPERIMENTAL_MAIL_UTF8
+       imap_feature_utf8accept =
+               imap_feature_register("UTF8=ACCEPT", MAILBOX_FEATURE_UTF8ACCEPT,
+                                     imap_client_enable_utf8accept);
+#endif
 }
 
 void client_kick(struct client *client, bool shutdown)
index f3ca5e7c991c371eafdb880b63f13ec7ba98ecef..944bc5b70b88fc447502090c3e647049e1fdbce3 100644 (file)
@@ -273,6 +273,7 @@ extern unsigned int imap_client_count;
 
 extern unsigned int imap_feature_condstore;
 extern unsigned int imap_feature_qresync;
+extern unsigned int imap_feature_utf8accept;
 
 /* Create new client with specified input/output handles. socket specifies
    if the handle is a socket. */
index ff5926957e96157cab8d6106a1473984d225f6ee..2d8d61ea3841b8cbcdf3361d970cd8b3123ea706 100644 (file)
@@ -84,6 +84,7 @@ enum mailbox_flags {
 enum mailbox_feature {
        /* Enable tracking modsequences */
        MAILBOX_FEATURE_CONDSTORE       = 0x01,
+       MAILBOX_FEATURE_UTF8ACCEPT      = 0x02,
 };
 
 enum mailbox_existence {