diff options
| author | Sam Varshavchik | 2018-07-14 15:51:42 -0400 |
|---|---|---|
| committer | Sam Varshavchik | 2018-07-16 21:20:25 -0400 |
| commit | 9643d3d5adcbc6357833a818e2928eb8e76717ed (patch) | |
| tree | 367ec86c8ccfb3aa2ab40b2440ebabfea382e0ce /maildir | |
| parent | 3359e8155147662382d2fd982bcf75a1644901a0 (diff) | |
| download | courier-libs-9643d3d5adcbc6357833a818e2928eb8e76717ed.tar.bz2 | |
Add maidirmake options to convert pre-unicode mailboxes to unicode mailboxes.
Diffstat (limited to 'maildir')
| -rw-r--r-- | maildir/Makefile.am | 4 | ||||
| -rw-r--r-- | maildir/maildirfilter.c | 5 | ||||
| -rw-r--r-- | maildir/maildirfilter.h | 1 | ||||
| -rw-r--r-- | maildir/maildirfilter2.c | 2 | ||||
| -rw-r--r-- | maildir/maildirinfo.h | 4 | ||||
| -rw-r--r-- | maildir/maildirinfo2.c | 148 | ||||
| -rw-r--r-- | maildir/maildirmake.c | 434 | ||||
| -rw-r--r-- | maildir/maildirmake.sgml | 319 | ||||
| -rw-r--r-- | maildir/testmaildirfilter.c | 2 |
9 files changed, 898 insertions, 21 deletions
diff --git a/maildir/Makefile.am b/maildir/Makefile.am index 148c75c..60f0681 100644 --- a/maildir/Makefile.am +++ b/maildir/Makefile.am @@ -34,7 +34,7 @@ libmaildir_la_SOURCES=autoresponse.c autoresponse.h \ maildirfilter.h maildirfiltertypelist.h\ maildirflags.c maildirmkdir.c \ maildirgetquota.c maildirgetquota.h \ - maildirinfo.c maildirinfo.h \ + maildirinfo.c maildirinfo.h maildirinfo2.c \ maildirkeywords.c maildirkeywords2.c maildirkeywords3.c \ maildirkeywords4.cpp \ maildirkeywords.h maildirlist.c maildirlock.c \ @@ -63,7 +63,7 @@ maildirmake_DEPENDENCIES=libmaildir.la \ ../rfc822/librfc822.la maildirmake_LDADD=libmaildir.la \ ../numlib/libnumlib.la \ - ../rfc822/librfc822.la -lcourier-unicode + ../rfc822/librfc822.la -lcourier-unicode @LIBPCRE@ maildirmake_LDFLAGS=-static testmaildirfilter_SOURCES=maildirfiltertypelist.h testmaildirfilter.c diff --git a/maildir/maildirfilter.c b/maildir/maildirfilter.c index a04ba0d..82702a1 100644 --- a/maildir/maildirfilter.c +++ b/maildir/maildirfilter.c @@ -175,7 +175,7 @@ static int maildir_filter_ruleupdate_utf8(struct maildirfilter *r, /* rule name: may not already exist */ *errcode=MF_ERR_EXISTS; - + for (pom=r->first; pom->next; pom=pom->next) { if (p!=pom && !strcmp(name, pom->rulename_utf8)) return (-1); @@ -508,8 +508,7 @@ static void print_pattern(FILE *f, int flags, const char *v) } int maildir_filter_saverules(struct maildirfilter *r, const char *filename, - const char *maildir, - const char *maildirpath, const char *fromaddr) + const char *maildirpath, const char *fromaddr) { FILE *f=fopen(filename, "w"); struct maildirfilterrule *p; diff --git a/maildir/maildirfilter.h b/maildir/maildirfilter.h index 3d4bfdf..44a32de 100644 --- a/maildir/maildirfilter.h +++ b/maildir/maildirfilter.h @@ -113,7 +113,6 @@ int maildir_filter_ruleupdate(struct maildirfilter *, struct maildirfilterrule * int maildir_filter_saverules(struct maildirfilter *, const char *, /* Filename */ - const char *, /* Maildir */ const char *, /* Path to maildir from mailfilter */ const char *); /* The return address */ diff --git a/maildir/maildirfilter2.c b/maildir/maildirfilter2.c index 3a541d3..922ad13 100644 --- a/maildir/maildirfilter2.c +++ b/maildir/maildirfilter2.c @@ -213,7 +213,7 @@ int maildir_filter_savemaildirfilter(struct maildirfilter *mf, const char *maild strcat(strcpy(createInfo.newname, maildir), "/maildirfilter.tmp"); rc=maildir_filter_saverules(mf, createInfo.tmpname, - maildir, maildirpath, from); + maildirpath, from); if (rc == 0 && rename(createInfo.tmpname, createInfo.newname)) rc= -1; maildir_tmpcreate_free(&createInfo); diff --git a/maildir/maildirinfo.h b/maildir/maildirinfo.h index 85eca68..418b81c 100644 --- a/maildir/maildirinfo.h +++ b/maildir/maildirinfo.h @@ -20,6 +20,10 @@ struct maildir_info { char *owner; }; +char *imap_foldername_to_filename(int utf8_format, const char *foldername); + +char *imap_filename_to_foldername(int utf8_format, const char *filename); + void maildir_info_destroy(struct maildir_info *); /* Deallocate memory */ int maildir_info_imap_find(struct maildir_info *info, const char *path, diff --git a/maildir/maildirinfo2.c b/maildir/maildirinfo2.c new file mode 100644 index 0000000..fcae14c --- /dev/null +++ b/maildir/maildirinfo2.c @@ -0,0 +1,148 @@ +/* +** Copyright 2018 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "maildirinfo.h" +#include <courier-unicode.h> + + +/* Count the size of the converted filename or foldername string */ +static void count_utf8(const char *str, size_t n, void *arg) +{ + *(size_t *)arg += n; +} + +/* Save the converted filename or foldername string */ +static void save_utf8(const char *str, size_t n, void *arg) +{ + char **p=(char **)arg; + + memcpy( (*p), str, n); + *p += n; +} + +/* +** Split a string at periods, convert each split range between charsets. +*/ +static int foldername_filename_convert(const char *src_chset, + const char *dst_chset, + const char *foldername, + void (*closure)(const char *, size_t, + void *), + void *arg) +{ + unicode_convert_handle_t h; + char *cbufptr; + size_t cbufsize; + size_t l; + int conversion_error; + + while (*foldername) + { + if (*foldername == '.') + { + (*closure)(foldername, 1, arg); + ++foldername; + continue; + } + + h=unicode_convert_tocbuf_init(src_chset, + dst_chset, + &cbufptr, + &cbufsize, + 0); + if (!h) + { + errno=EINVAL; + return -1; + } + + for (l=0; foldername[l] && foldername[l] != '.'; ++l) + ; + + unicode_convert(h, foldername, l); + + if (unicode_convert_deinit(h, &conversion_error) == 0) + { + closure(cbufptr, cbufsize, arg); + free(cbufptr); + if (conversion_error) + { + errno=EILSEQ; + return -1; + } + } + else + return -1; + foldername += l; + } + return 0; +} + +/* Convert either a foldername or a filename to the other */ + +static char *foldername_filename_convert_tobuf(const char *src_chset, + const char *dst_chset, + const char *foldername) +{ + char *utf8, *p; + size_t l=1; + + if (foldername_filename_convert(src_chset, + dst_chset, + foldername, count_utf8, &l)) + return NULL; + + utf8=malloc(l+1); + + if (!utf8) + return NULL; + + p=utf8; + if (foldername_filename_convert(src_chset, + dst_chset, + foldername, save_utf8, &p)) + { + free(utf8); + return NULL; + } + + *p=0; + + return utf8; +} + +char *imap_foldername_to_filename(int utf8_format, const char *foldername) +{ + if (utf8_format) + return strdup(foldername); + + return foldername_filename_convert_tobuf + (unicode_x_imap_modutf7, + "utf-8", + foldername); +} + +char *imap_filename_to_foldername(int utf8_format, const char *filename) +{ + if (utf8_format) + return strdup(filename); + + return foldername_filename_convert_tobuf + ("utf-8", + unicode_x_imap_modutf7, + filename); +} diff --git a/maildir/maildirmake.c b/maildir/maildirmake.c index 9e14eb4..6d35899 100644 --- a/maildir/maildirmake.c +++ b/maildir/maildirmake.c @@ -1,5 +1,5 @@ /* -** Copyright 1998 - 2006Double Precision, Inc. +** Copyright 1998 - 2018 Double Precision, Inc. ** See COPYING for distribution information. */ @@ -25,8 +25,10 @@ #include "maildircreate.h" #include "maildirmisc.h" +#include "maildirinfo.h" #include "maildirsharedrc.h" #include "maildirquota.h" +#include "maildirfilter.h" #include <courier-unicode.h> static void usage() @@ -194,6 +196,421 @@ int found; exit(0); } +/***************************************************************************** + +Convert modified-UTF7 folder names to UTF-8 (sort-of). + +*****************************************************************************/ + +struct convertutf8_list { + struct convertutf8_list *next; + char *rename_from; + char *rename_to; +}; + +struct convertutf8_status { + struct convertutf8_list *list; + int status; +}; + +/* Find folders that need to change */ + +static void convertutf8_build_list(const char *inbox_name, + void *arg) +{ + struct convertutf8_status *status= + (struct convertutf8_status *)arg; + struct convertutf8_list *list; + + char *converted=imap_foldername_to_filename(0, inbox_name); + + if (!converted) + { + fprintf(stderr, + "Error: %s: does not appear to be valid" + " modified-UTF7\n", + inbox_name); + status->status=1; + return; + } + + if (strcmp(converted, inbox_name) == 0) + { + free(converted); + return; + } + list=(struct convertutf8_list *)malloc(sizeof(struct convertutf8_list)); + + if (!list || !(list->rename_from=strdup(inbox_name))) + { + perror("malloc"); + exit(1); + } + + list->rename_to=converted; + list->next=status->list; + status->list=list; +} + +void convertutf8(const char *maildir, const char *mailfilter, int doit) +{ + struct convertutf8_status status; + struct convertutf8_list *list; + char *courierimapsubscribed; + char *courierimapsubscribed_new; + FILE *courierimapsubscribed_fp; + struct maildirfilter mf; + int mf_status; + char *mailfilter_newname=0; + + memset(&status, 0, sizeof(status)); + memset(&mf, 0, sizeof(mf)); + + printf("Checking %s:\n", maildir); + + maildir_list(maildir, convertutf8_build_list, &status); + + if (status.status) + exit(status.status); + + if (mailfilter) + { + struct maildirfilterrule *r; + + /* + ** Try to convert folder references from mailfilter + */ + + mailfilter_newname=malloc(strlen(mailfilter)+10); + + strcat(strcpy(mailfilter_newname, mailfilter), ".new"); + mf_status=maildir_filter_loadrules(&mf, mailfilter); + + if (mf_status != MF_LOADOK && mf_status != MF_LOADNOTFOUND) + { + fprintf(stderr, "Error: cannot load %s\n", + mailfilter); + } + + for (r=mf.first; r; r=r->next) + { + char *converted; + + /* Look for deliveries to a folder */ + + if (strncmp(r->tofolder, "INBOX.", 6)) + continue; + + converted=imap_foldername_to_filename(0, r->tofolder); + + if (!converted) + { + fprintf(stderr, "Error: %s: " + "%s: does not appear to be valid " + "modified-UTF7\n", + mailfilter, + r->tofolder); + status.status=1; + } + + if (strcmp(converted, r->tofolder) == 0) + { + free(converted); + continue; + } + + printf("Mail filter to %s updated to %s\n", + r->tofolder, converted); + + free(r->tofolder); + r->tofolder=converted; + } + + if (mf_status == MF_LOADOK) + { + FILE *fp=fopen(mailfilter, "r"); + char detected_from[1024]; + char detected_tomaildir[1024]; + char buffer[1024]; + struct stat st_buf; + + /* + ** We need to know the FROM address and the MAILDIR + ** reference. Attempt to ham-fistedly parse the + ** current filter file. + */ + + detected_from[0]=0; + detected_tomaildir[0]=0; + + if (!fp) + { + perror(mailfilter); + exit(1); + } + + while (fgets(buffer, sizeof(buffer), fp)) + { + char *p, *q; + + if (strncmp(buffer, "FROM='", 6) == 0) + { + char *p=strchr(buffer+6, '\''); + + if (!p) + { + fprintf(stderr, + "Cannot parse %s\n", + mailfilter); + status.status=1; + } + else + { + *p=0; + strcpy(detected_from, buffer+6); + + /* + Unescape, because saverules() + escapes it. + */ + + for (q=p=detected_from; *p; p++) + { + if (*p == '\\' && p[1]) + ++p; + *q=*p; + ++q; + } + *q=0; + } + } + + if (strncmp(buffer, "to \"", 4) == 0) + { + p=strstr(buffer+4, "/.\""); + + if (!p) + { + fprintf(stderr, + "Cannot parse %s\n", + mailfilter); + status.status=1; + } + else + { + *p=0; + } + strcpy(detected_tomaildir, buffer+4); + } + } + fclose(fp); + if (detected_from[0] == 0 || + detected_tomaildir[0] == 0) + { + fprintf(stderr, + "Failed to parse %s\n", + mailfilter); + status.status=1; + } + maildir_filter_saverules(&mf, mailfilter_newname, + detected_tomaildir, + detected_from); + + if (stat(mailfilter, &st_buf) || + chmod(mailfilter_newname, st_buf.st_mode)) + { + perror(mailfilter); + exit(1); + } + /* + ** If we're root, preserve the ownership and permission + */ + if (geteuid() == 0) + { + if (chown(mailfilter_newname, st_buf.st_uid, + st_buf.st_gid)) + { + perror(mailfilter_newname); + exit(1); + } + } + } + } + else + { + mf_status=MF_LOADNOTFOUND; + } + + courierimapsubscribed=malloc(strlen(maildir)+100); + courierimapsubscribed_new=malloc(strlen(maildir)+100); + + strcat(strcpy(courierimapsubscribed, maildir), + "/courierimapsubscribed"); + strcat(strcpy(courierimapsubscribed_new, maildir), + "/courierimapsubscribed.new"); + + /* + ** Update folder references in the IMAP subscription file. + */ + + if ((courierimapsubscribed_fp=fopen(courierimapsubscribed, "r")) + != NULL) + { + char buffer[2048]; + FILE *new_fp=fopen(courierimapsubscribed_new, "w"); + char *converted; + struct stat st_buf; + + while (fgets(buffer, sizeof(buffer), courierimapsubscribed_fp)) + { + char *p=strchr(buffer, '\n'); + + if (!p) + { + fprintf(stderr, "Error: courierimapsubscribed: " + "folder name too long\n"); + status.status=1; + continue; + } + + *p=0; + + converted=imap_foldername_to_filename(0, buffer); + + if (!converted) + { + fprintf(stderr, "Error: courierimapsubscribed: " + "%s: does not appear to be valid " + "modified-UTF7\n", + buffer); + status.status=1; + continue; + } + fprintf(new_fp, "%s\n", converted); + + if (strcmp(buffer, converted)) + { + printf("Subscription to %s changed to %s\n", + buffer, converted); + } + free(converted); + } + if (fflush(new_fp) || fclose(new_fp)) + { + exit(1); + } + fclose(courierimapsubscribed_fp); + + /* + ** If we're root, preserve the ownership and permission + */ + if (stat(courierimapsubscribed, &st_buf) || + chmod(courierimapsubscribed_new, st_buf.st_mode)) + { + perror(courierimapsubscribed); + exit(1); + } + + if (geteuid() == 0) + { + if (chown(courierimapsubscribed_new, st_buf.st_uid, + st_buf.st_gid)) + { + perror(courierimapsubscribed_new); + exit(1); + } + } + } + + if (status.status) + { + unlink(courierimapsubscribed_new); + if (mf_status == MF_LOADOK) + unlink(mailfilter_newname); + exit(status.status); + } + for (list=status.list; list; list=list->next) + { + char *frompath, *topath; + + printf("Rename %s to %s\n", list->rename_from, list->rename_to); + + frompath=malloc(strlen(maildir)+strlen(list->rename_from)); + topath=malloc(strlen(maildir)+strlen(list->rename_to)); + + if (!frompath || !topath) + { + perror("malloc"); + exit(1); + } + + strcat(strcpy(frompath, maildir), "/"); + strcat(strcpy(topath, maildir), "/"); + + /* They all have the INBOX. prefix, strip it off */ + strcat(frompath, strchr(list->rename_from, '.')); + strcat(topath, strchr(list->rename_to, '.')); + + if (doit) + { + if (rename(frompath, topath)) + { + fprintf(stderr, + "FATAL ERROR RENAMING %s to %s: %s\n", + frompath, topath, strerror(errno)); + status.status=1; + } + } + free(frompath); + free(topath); + } + + if (doit) + { + if (courierimapsubscribed_fp) + { + printf("Updating %s\n", courierimapsubscribed); + + if (rename(courierimapsubscribed_new, + courierimapsubscribed)) + { + fprintf(stderr, + "FATAL ERROR RENAMING %s to %s: %s\n", + courierimapsubscribed_new, + courierimapsubscribed, strerror(errno)); + status.status=1; + } + } + + if (mf_status == MF_LOADOK) + { + printf("Updating %s\n", mailfilter); + + if (rename(mailfilter_newname, mailfilter)) + { + fprintf(stderr, + "FATAL ERROR RENAMING %s to %s: %s\n", + mailfilter_newname, mailfilter, + strerror(errno)); + status.status=1; + } + } + } + else + { + if (courierimapsubscribed_fp) + { + printf("Verified %s\n", courierimapsubscribed); + } + + if (mf_status == MF_LOADOK) + { + printf("Verified %s\n", mailfilter); + } + } + exit(status.status); +} + int main(int argc, char *argv[]) { const char *maildir, *folder=0; @@ -297,6 +714,21 @@ char *tmp=0; continue; } + if (strcmp(argv[argn], "--convutf8") == 0 && argc-argn > 1) + { + char *maildir=argv[++argn]; + char *mailfilter=argn < argc ? argv[++argn]:0; + convertutf8(maildir, mailfilter, 1); + exit(0); + } + + if (strcmp(argv[argn], "--checkutf8") == 0 && argc-argn > 1) + { + char *maildir=argv[++argn]; + char *mailfilter=argn < argc ? argv[++argn]:0; + convertutf8(maildir, mailfilter, 0); + exit(0); + } usage(); } diff --git a/maildir/maildirmake.sgml b/maildir/maildirmake.sgml index b1a7d6d..e60ef61 100644 --- a/maildir/maildirmake.sgml +++ b/maildir/maildirmake.sgml @@ -1,5 +1,5 @@ <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> -<!-- Copyright 1998 - 2009 Double Precision, Inc. See COPYING for --> +<!-- Copyright 1998 - 2018 Double Precision, Inc. See COPYING for --> <!-- distribution information. --> <refentry> <info><author><firstname>Sam</firstname><surname>Varshavchik</surname><contrib>Author</contrib></author><productname>Courier Mail Server</productname></info> @@ -28,7 +28,7 @@ <para> The <command>maildirmake</command> command creates maildirs, and -maildir folders. +maildir folders and performs some routine maintenance on them. This documentation describes the <command>maildirmake</command> command from the <application>Courier</application> mail server, @@ -46,9 +46,7 @@ slightly different permissions which allows creation of publicly-shared folders.</simpara> </listitem> </varlistentry> - </variablelist> - <variablelist> <varlistentry><term><literal>-q</literal> <replaceable>quota</replaceable></term> <listitem><simpara>install a quota on the maildir. See @@ -59,17 +57,13 @@ folders.</simpara> </simpara> </listitem> </varlistentry> - </variablelist> - <variablelist> <varlistentry><term><literal>-f</literal> <replaceable>folder</replaceable></term> <listitem><simpara>do not create a maildir, but create a folder in an existing maildir.</simpara> </listitem> </varlistentry> - </variablelist> - <variablelist> <varlistentry><term><literal>-F</literal> <replaceable>folder</replaceable></term> <listitem><simpara>Like the <literal>-f</literal> option, except that the folder's name is given using the system locale's @@ -80,9 +74,7 @@ existing maildir.</simpara> set..</simpara> </listitem> </varlistentry> - </variablelist> - <variablelist> <varlistentry><term><literal>-s</literal> <replaceable>mode</replaceable></term> <listitem><simpara>create a publicly accessible folder in an existing sharable maildir. First, use the <option>-S</option> option to @@ -100,9 +92,7 @@ your own system group to access messages in this folder (instead of everyone).</simpara> </listitem> </varlistentry> - </variablelist> - <variablelist> <varlistentry><term><literal>--add</literal> <replaceable>name</replaceable>=<replaceable>pathname</replaceable>, <literal>--del</literal> <replaceable>name</replaceable></term> <listitem><simpara> @@ -110,6 +100,29 @@ create or delete the directories and links needed to access shared folders. See below for more information.</simpara> </listitem> </varlistentry> + <varlistentry> + <term><literal>--checkutf8</literal> <replaceable>maildir</replaceable> <replaceable>maildirfilter</replaceable></term> + <listitem> + <simpara> + Perform a sanity check to verify that a pre-unicode format + maildir can be converted to a unicode-format maildir. + See <quote>Converting pre-unicode format maildirs</quote>, below, + for more information. + </simpara> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>--convutf8</literal> <replaceable>maildir</replaceable> <replaceable>maildirfilter</replaceable></term> + <listitem> + <simpara> + Convert a pre-unicode format + maildir can be converted to a unicode-format maildir. + See <quote>Converting pre-unicode format maildirs</quote>, below, + for more information. + </simpara> + </listitem> + </varlistentry> </variablelist> <refsect2> @@ -270,6 +283,288 @@ own.</para> </refsect2> </refsect1> + + <refsect1> + <title>Converting pre-unicode format maildirs</title> + + <para> + This section is relevant to: + + </para> + + <itemizedlist> + <listitem> + <para> + Updating <application>Courier-IMAP</application> to version 5.0, and + later, from prior versions of <application>Courier-IMAP</application>, or: + </para> + </listitem> + <listitem> + <para> + Updating <application>SqWebmail</application> to version 6.0, and + later, from prior versions of <application>SqWebmail</application>, or: + </para> + </listitem> + <listitem> + <para> + Updating Courier to version 1.0, and + later, from prior versions of Courier. + </para> + </listitem> + </itemizedlist> + + <para> + These versions have been updated to implement native Unicode + support in several E-mail-related protocols. It is already expected + that updating Internet standards to use native Unicode-formatted + E-mail messages will not be 100% backwards-compatible, in terms of + E-mail client support. + Given that, this major update to Unicode will also introduce some + backwards-incompatible changes to the internal structure of maildirs, + as a long term major to simplify Unicode support going forward. + Might as well go through the pain of a major upgrade once. + </para> + + <para> + <command>maildirmake</command>'s <option>--checkutf8</option> and + <option>--convutf8</option> options are tools to aid in conversion of + existing mailbox to the new Unicode-based naming standard. + </para> + + <refsect2> + <title>Background</title> + + <para> + Mail folders in a maildir are hidden subdirectories. For example: + a folder name <quote>Mailing list</quote> is a maildir subdirectory + named <filename>$HOME/Maildir/.Mailing list</filename> (with + <filename>$HOME/Maildir</filename> being the main mailbox). + </para> + + <para> + Prior to the unicode update, non-English characters in folder names + were implemented using a convention that was derived from the + non-standard <quote>modified-UTF7</quote> encoding used by IMAP. + A folder named <quote>Résumé</quote> was in a maildir subdirectory + named <filename>$HOME/Maildir/.R&AOk-sum&AOk-</filename>. + The current versions of Courier, <application>Courier-IMAP</application>, and SqWebmail, + will simply create <filename>$HOME/Maildir/.Résumé</filename> + using the <acronym>UTF8</acronym> encoding, which will appear simply + as a <quote>.Résumé</quote> (hidden) subdirectory on modern + UTF8-based systems. + </para> + + <para> + Consequently, any existing maildirs that have non-English folders + must be converted as part of updating to the current version of + Courier, <application>Courier-IMAP</application>, and SqWebmail from pre-unicode versions. + At this time + this does not occur as part of automatically updating to the current + version, and must be done manually given the wide variety of individual + mail server configurations that are possible. + </para> + </refsect2> + + <refsect2> + <title>Unicode conversion overview</title> + + <para> + Updating from pre-unicode versions involves: + </para> + + <itemizedlist> + <listitem> + <para> + Renaming the actual maildir folders, + <filename>$HOME/Maildir/.<replaceable>names</replaceable></filename> + into unicode names (using <acronym>UTF8</acronym>). + </para> + </listitem> + + <listitem> + <para> + Updating the + <filename>$HOME/Maildir/courierimapsubscribed</filename>, + which is a list of subscribed IMAP folders, if it exists. + </para> + </listitem> + + <listitem> + <para> + Updating any + <application>maildrop</application> + mail filtering recipe, + <filename>$HOME/.mailfilter</filename>, if it exists, to reference + the unicode maildir folders; or updating any custom site mail + filtering engine that delivers to maildir folders, to reference + the correct subdirectory names. + </para> + </listitem> + </itemizedlist> + </refsect2> + <refsect2> + <title>Unicode conversion steps</title> + + <para> + The <option>--checkutf8</option> and + <option>--convutf8</option> options to + <command>maildirmake</command> convert a single maildir to the new + unicode format: + </para> + + <blockquote> + <informalexample> + <programlisting> +$ ./maildirmake --checkutf8 ~/Maildir ~/.mailfilter +Checking /home/mrsam/Maildir: +Mail filter to INBOX.R&AOk-sum&AOk- updated to INBOX.Résumé +Subscription to INBOX.R&AOk-sum&AOk- changed to INBOX.Résumé +Rename INBOX.R&AOk-sum&AOk- to INBOX.Résumé +Verified /home/mrsam/Maildir/courierimapsubscribed +Verified /home/mrsam/.mailfilter +$ ./maildirmake --convutf8 ~/Maildir ~/.mailfilter +Checking /home/mrsam/Maildir: +Mail filter to INBOX.R&AOk-sum&AOk- updated to INBOX.Résumé +Subscription to INBOX.R&AOk-sum&AOk- changed to INBOX.Résumé +Rename INBOX.R&AOk-sum&AOk- to INBOX.Résumé +Updating /home/mrsam/Maildir/courierimapsubscribed +Updating /home/mrsam/.mailfilter</programlisting> + </informalexample> + </blockquote> + + <para> + <option>--checkutf8</option> goes through the motions of converting + a single maildir to Unicode, but without making any actual changes. + <option>--convutf8</option> does the conversion for real. + The first required parameter is the maildir to convert. The + second parameter is optional, and specifies the corresponding + <command>maildrop</command> filtering recipe, + <emphasis>but only if <application>SqWebMail</application></emphasis> + generates the mail filtering recipes. + <application>SqWebMail</application>'s mail filtering recipes are + parsable, and can be automatically-converted. + Non-<application>SqWebMail</application>-generated + <filename>.mailfilter</filename>s cannot be converted automatically. + The second parameter must be omitted, and the mail filtering recipe + must be converted by hand. + </para> + + <note> + <para> + Any manual work is only needed if maildirs have folders with + non-English names. Ignore everything you've just read if all + folder names are English-only. + <option>--checkutf8</option> and + <option>--convutf8</option> will not do anything, and nothing + needs to be done. + </para> + </note> + + <para> + To convert all mailboxes to Unicode all at once: + </para> + + <itemizedlist> + <listitem> + <para> + Write a shell script to run <option>--checkutf8</option> on + all your mailboxes. It's ok to explicitly specify each mailbox's + <filename>.mailfilter</filename>, when using + <application>SqWebMail</application> even if a particular + mailbox does not use it. It will be ignored. + </para> + + <para> + It is safe to run <option>--checkutf8</option> without shutting + down your mail server. A non-zero exit from + <option>--checkutf8</option> indicates a problem (see below) + for a particular maildir. + </para> + </listitem> + + <listitem> + <para> + Once <option>--checkutf8</option> does not find any problems + with any mailbox, shut down the mail server, run + <option>--checkutf8</option> one more time for all mailboxes, + then if everything goes well, upgrade + <application>Courier</application>, + <application>Courier-IMAP</application>, or + <application>SqWebMail</application> and + run + <option>--convutf8</option> on every mailbox before restarting + the server. + </para> + </listitem> + </itemizedlist> + + <note> + <para> + <option>--convutf8</option> is a one-shot deal. Do not run + <option>--convutf8</option> a second time after it successfully + converted a maildir. In nearly all cases nothing will happen, + but there are rare edge cases where some folder names may + get garbled, or it fails completely. + </para> + </note> + </refsect2> + + <refsect2> + <title>Resolving unicode conversion problems</title> + + <para> + The only likely problems that might be encountered is the fall-out + from buggy IMAP clients that did not follow the pre-Unicode naming + convention for non-Latin folder names. The customized IMAP + <quote>modified-UTF7</quote> encoding convention for non-Latin + folder names is mostly an IMAP client convention, and the + pre-Unicode version of <application>Courier-IMAP</application> did + not enforce it. The server just uses the name from the IMAP client, + as is. + </para> + + <para> + Unicode conversion (<option>--checkutf8</option> or + <option>--convutf8</option>) fails if it finds a folder name that + does not correctly use IMAP's + <quote>modified-UTF7</quote> encoding. This can only be resolved + manually, by renaming the folder. This may also involve manually + editing <filename>courierimapsubscribed</filename> and + <filename>.mailfilter</filename> if they exist. The bad folder name + should be removed from + <filename>courierimapsubscribed</filename>. For + <filename>.mailfilter</filename> it is sufficient to remove only + the comments that precede the actual <command>maildrop</command> rule, + and <option>--convutf8</option> will remove the entire rule, by itself. + <option>--convutf8</option> actually reads only the machine-parsable + comments in <command>SqWebMail</command>-generated + <filename>.mailfilter</filename> (plus a few other things in the + file), and replaces the + <filename>.mailfilter</filename> with the Unicode version based + solely on the parsed data. + </para> + </refsect2> + + <refsect2> + <title>After the Unicode conversion</title> + + <para> + The current, Unicode version of <application>Courier-IMAP</application> + supports both Unicode and non-Unicode + IMAP clients; however unlike the pre-Unicode version, + <application>Courier-IMAP</application> rejects requests from + non-Unicode IMAP clients to use or create folders that are not + properly encoded. + </para> + + <para> + Encountering a bad folder during conversion strongly suggests the + usage of an IMAP client that does not correctly encode non-English + folder names. Such an IMAP client will likely have problems after + the conversion. + </para> + </refsect2> + </refsect1> <refsect1> <title>SEE ALSO</title> diff --git a/maildir/testmaildirfilter.c b/maildir/testmaildirfilter.c index c50d358..a8804d5 100644 --- a/maildir/testmaildirfilter.c +++ b/maildir/testmaildirfilter.c @@ -79,7 +79,7 @@ const char *charset=getenv("CHARSET"); } unlink("maildirsize"); - errcode=maildir_filter_saverules(&mf, "testrules2", ".", "Maildir", "nobody@example.com"); + errcode=maildir_filter_saverules(&mf, "testrules2", "Maildir", "nobody@example.com"); if (errcode) { fprintf(stderr, "Error saving testrules2: %d\n", errcode); |
