From bad4973408065500f9db451b19953afe57ba53c5 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 13 Aug 2011 02:00:04 +0300 Subject: [PATCH] * mu-maildir.[ch]: re-implement message flag parsing, message moving --- src/mu-maildir.c | 379 +++++++++++++++++++--------------------- src/mu-maildir.h | 47 +++-- src/mu-msg.c | 198 +-------------------- src/mu-msg.h | 23 +-- src/tests/test-mu-msg.c | 7 +- 5 files changed, 233 insertions(+), 421 deletions(-) diff --git a/src/mu-maildir.c b/src/mu-maildir.c index adee7a79..9599aa53 100644 --- a/src/mu-maildir.c +++ b/src/mu-maildir.c @@ -618,20 +618,11 @@ mu_maildir_clear_links (const gchar* path, GError **err) return rv; } - -/* - * is this a 'new' msg or a 'cur' msg?; if new, we return - * (in info) a ptr to the info part - */ -enum _MsgType { MSG_TYPE_CUR, MSG_TYPE_NEW, MSG_TYPE_OTHER }; -typedef enum _MsgType MsgType; - -static MsgType -check_msg_type (const char *path, char **info) +MuFlags +mu_maildir_get_flags_from_path (const char *path) { - char *dir, *file; - MsgType mtype; - + g_return_val_if_fail (path, MU_FLAG_INVALID); + /* try to find the info part */ /* note that we can use either the ':' or '!' as separator; * the former is the official, but as it does not work on e.g. VFAT @@ -640,96 +631,43 @@ check_msg_type (const char *path, char **info) * documentation at http://docs.python.org/lib/mailbox-maildir.html * mentions the '!' as well as a 'popular choice' */ - - *info = NULL; - dir = g_path_get_dirname(path); - file = g_path_get_basename(path); + + /* we check the dir -- */ + if (strstr (path, G_DIR_SEPARATOR_S "new" G_DIR_SEPARATOR_S)) { - if (!(*info = strrchr(file, ':'))) - *info = strrchr(file, '!'); /* Tinymail */ - if (*info) - ++(*info); /* skip the ':' or '!' */ + char *dir, *dir2; + MuFlags flags; + + dir = g_path_get_dirname (path); + dir2 = g_path_get_basename (dir); + + if (g_strcmp0 (dir2, "new") == 0) + flags = MU_FLAG_NEW; + + g_free (dir); + g_free (dir2); - if (g_str_has_suffix(dir, G_DIR_SEPARATOR_S "cur")) { - if (!*info) - g_debug("'cur' file, but no info part: %s", path); - mtype = MSG_TYPE_CUR; - } else if (g_str_has_suffix(dir, G_DIR_SEPARATOR_S "new")) { - if (*info) - g_debug("'new' file, ignoring info part: %s", path); - mtype = MSG_TYPE_NEW; - } else - mtype = MSG_TYPE_OTHER; /* file has been added explicitly as - a single message */ - if (*info) - *info = g_strdup(*info); - - g_free(dir); - g_free(file); - - return mtype; -} - - -MuFlags -mu_maildir_get_flags_from_path (const char *path) -{ - MuFlags flags; - MsgType mtype; - char *info = NULL; - - g_return_val_if_fail (path, MU_FLAG_NONE); - g_return_val_if_fail (!g_str_has_suffix(path, G_DIR_SEPARATOR_S), - MU_FLAG_NONE); - - mtype = check_msg_type (path, &info); - if (mtype == MSG_TYPE_NEW) { /* we ignore any new-msg flags */ - /* note NEW implies UNREAD */ - flags = MU_FLAG_NEW | MU_FLAG_UNREAD; - goto leave; + /* NOTE: new/ message should not have :2,-stuff, as + * per http://cr.yp.to/proto/maildir.html. If they, do + * we ignore it + */ + if (flags == MU_FLAG_NEW) + return flags; } - flags = MU_FLAG_NONE; - if ((mtype != MSG_TYPE_CUR && mtype != MSG_TYPE_OTHER) || - !(info && info[0] == '2' && info[1] == ',')) - goto leave; + /* get the file flags */ + { + char *info; - flags |= mu_flags_from_str (info + 2, MU_FLAG_TYPE_MAILFILE); - - /* the UNREAD pseudo flag => NEW OR NOT SEEN */ - if (!(flags & MU_FLAG_SEEN)) - flags |= MU_FLAG_UNREAD; -leave: - g_free(info); - return flags; -} - -/* note: returns static string, non-reentrant */ -static const char* -get_flags_str_s (MuFlags flags) -{ - int i; - static char flagstr[7]; - - i = 0; - - /* now, determine the flags to use */ - if (flags & MU_FLAG_DRAFT) - flagstr[i++] = 'D'; - if (flags & MU_FLAG_FLAGGED) - flagstr[i++] = 'F'; - if (flags & MU_FLAG_PASSED) - flagstr[i++] = 'P'; - if (flags & MU_FLAG_REPLIED) - flagstr[i++] = 'R'; - if (flags & MU_FLAG_SEEN) - flagstr[i++] = 'S'; - if (flags & MU_FLAG_TRASHED) - flagstr[i++] = 'T'; - - flagstr[i] = '\0'; - - return flagstr; + info = strrchr (path, '2'); + if (!info || info == path || + (info[-1] != ':' && info[-1] != '!') || + (info[1] != ',')) + return MU_FLAG_NONE; + else + return mu_flags_from_str (&info[2], + MU_FLAG_TYPE_MAILFILE); + } } @@ -746,114 +684,163 @@ get_flags_str_s (MuFlags flags) * so only difference is whether MuFlags matches MU_FLAG_NEW is set or not * */ -static char* -get_new_dir_name (const char* oldpath, MuFlags flags) -{ - char *newpath, *dirpart; - - /* g_path_get_dirname is not explicit about whether it ends in - * a dir-separator (\ or /), so we need to check both */ - const char* cur4 = G_DIR_SEPARATOR_S "cur"; - const char* cur5 = G_DIR_SEPARATOR_S "cur" G_DIR_SEPARATOR_S; - const char* new4 = G_DIR_SEPARATOR_S "new"; - const char* new5 = G_DIR_SEPARATOR_S "new" G_DIR_SEPARATOR_S; - - g_return_val_if_fail (oldpath, NULL); - /* if MU_FLAG_NEW is set, it must be the only flag */ - /* g_return_val_if_fail (flags & MU_FLAG_NEW ? */ - /* flags == MU_FLAG_NEW : TRUE, NULL); */ - - newpath = g_path_get_dirname (oldpath); - if (g_str_has_suffix (newpath, cur4) || g_str_has_suffix (newpath, new4)) - dirpart = &newpath[strlen(newpath) - strlen(cur4)]; - else if (g_str_has_suffix (newpath, cur5) || g_str_has_suffix (newpath, new5)) - dirpart = &newpath[strlen(newpath) - strlen(cur5)]; +static gchar* +get_new_path (const char *mdir, const char *mfile, MuFlags flags) +{ + if (flags & MU_FLAG_NEW) + return g_strdup_printf ("%s%cnew%c%s", + mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, + mfile); else { - g_warning ("invalid maildir path: %s", oldpath); - g_free (newpath); - return NULL; - } - - /* now, copy the desired dir part behind this */ - if (flags & MU_FLAG_NEW) - memcpy (dirpart, new4, strlen(new4) + 1); - else - memcpy (dirpart, cur4, strlen(cur4) + 1); + const char *flagstr; + flagstr = mu_flags_to_str_s (flags, MU_FLAG_TYPE_MAILFILE); - return newpath; + return g_strdup_printf ("%s%ccur%c%s:2,%s", + mdir, G_DIR_SEPARATOR, G_DIR_SEPARATOR, + mfile, flagstr); + } } -/* - * get a new filename for the message, based on the new flags; if the - * message has MU_FLAG_NEW, it will loose its flags - * - */ -static char* -get_new_file_name (const char *oldpath, MuFlags flags) -{ - gchar *newname, *sep; - gchar sepa; - - /* if MU_FLAG_NEW is set, it must be the only flag */ - /* g_return_val_if_fail (flags & MU_FLAG_NEW ? */ - /* flags == MU_FLAG_NEW : TRUE, NULL); */ - - /* the normal separator is ':', but on e.g. vfat, '!' is seen - * as well */ - newname = g_path_get_basename (oldpath); - if (!newname) { - g_warning ("invalid path: '%s'", oldpath); - return NULL; - } - - /* 'INVALID' means: "don't change flags" */ - if (flags == (unsigned)MU_FLAG_INVALID) - return newname; - - /* the filename may or may not end in "[:!]2,..." */ - sepa = ':'; /* FIXME: this will break on vfat, but we don't - * want to generate '!' files on non-VFAT */ - if ((sep = g_strrstr (newname, ":")) || - (sep = g_strrstr (newname, "!"))) { - sepa = *sep; - *sep = '\0'; - } - - { - gchar *tmp; - tmp = g_strdup_printf ("%s%c2,%s", newname, sepa, - get_flags_str_s (flags)); - g_free (newname); - newname = tmp; - } - - return newname; -} char* -mu_maildir_get_path_from_flags (const char *oldpath, MuFlags newflags) +mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, + MuFlags newflags) { - char *newname, *newdir, *newpath; - + char *mfile, *mdir, *newpath, *cur; + g_return_val_if_fail (oldpath, NULL); - /* if MU_FLAG_NEW is set, it must be the only flag */ - /* g_return_val_if_fail (newflags & MU_FLAG_NEW ? */ - /* newflags == MU_FLAG_NEW : TRUE, NULL); */ + + mfile = newpath = NULL; - newname = get_new_file_name (oldpath, newflags); - if (!newname) - return NULL; - - newdir = get_new_dir_name (oldpath, newflags); - if (!newdir) { - g_free (newname); - return NULL; + /* determine the maildir */ + mdir = g_path_get_dirname (oldpath); + if (!g_str_has_suffix (mdir, "cur") && !g_str_has_suffix (mdir, "new")) { + g_warning ("%s: not a valid maildir path: %s", + __FUNCTION__, oldpath); + goto leave; } - - newpath = g_strdup_printf ("%s%c%s", newdir, G_DIR_SEPARATOR, newname); - g_free (newname); - g_free (newdir); - + /* remove the 'cur' or 'new' */ + mdir[strlen(mdir) - 4] = '\0'; + + /* determine the name of the mailfile, stripped of its flags */ + mfile = g_path_get_basename (oldpath); + for (cur = &mfile[strlen(mfile)-1]; cur > mfile; --cur) { + if ((*cur == ':' || *cur == '!') && + (cur[1] == '2' && cur[2] == ',')) { + cur[0] = '\0'; /* strip the flags */ + break; + } + } + + newpath = get_new_path (new_mdir ? new_mdir : mdir, + mfile, newflags); + +leave: g_free (mfile); + g_free (mdir); + return newpath; } + +static gboolean +msg_move_check_pre (const gchar *src, const gchar *dst, GError **err) +{ + if (!g_path_is_absolute(src)) { + g_set_error (err, 0, MU_ERROR_FILE, + "source is not an absolute path: '%s'", src); + return FALSE; + } + + if (!g_path_is_absolute(dst)) { + g_set_error (err, 0, MU_ERROR_FILE, + "target is not an absolute path: '%s'", dst); + return FALSE; + } + + if (access (src, R_OK) != 0) { + g_set_error (err, 0, MU_ERROR_FILE, "cannot read %s", + src); + return FALSE; + } + + if (access (dst, F_OK) == 0) { + g_set_error (err, 0, MU_ERROR_FILE, "%s already exists", + dst); + return FALSE; + } + + return TRUE; +} + +static gboolean +msg_move_check_post (const char *src, const char *dst, GError **err) +{ + /* double check -- is the target really there? */ + if (access (dst, F_OK) != 0) { + g_set_error (err, 0, MU_ERROR_FILE, "can't find target (%s)", + dst); + return FALSE; + } + + if (access (src, F_OK) == 0) { + g_set_error (err, 0, MU_ERROR_FILE, "source is still there (%s)", + src); + return FALSE; + } + + return TRUE; +} + + +static gboolean +msg_move (const char* src, const char *dst, GError **err) +{ + if (!msg_move_check_pre (src, dst, err)) + return FALSE; + + if (rename (src, dst) != 0) { + g_set_error (err, 0, MU_ERROR_FILE, "error moving %s to %s", + src, dst); + return FALSE; + } + + if (!msg_move_check_post (src, dst, err)) + return FALSE; + + return TRUE; +} + +gchar* +mu_maildir_move_message (const char* oldpath, const char* targetmdir, + MuFlags newflags, GError **err) +{ + char *newfullpath; + gboolean rv; + + g_return_val_if_fail (oldpath, FALSE); + + newfullpath = mu_maildir_get_new_path (oldpath, targetmdir, + newflags); + if (!newfullpath) { + g_set_error (err, 0, MU_ERROR_FILE, + "failed to determine target full path"); + return FALSE; + } + + if (g_strcmp0 (oldpath, newfullpath) == 0) { + g_set_error (err, 0, MU_ERROR_FILE, + "target equals source"); + return FALSE; + } + + rv = msg_move (oldpath, newfullpath, err); + if (!rv) { + g_free (newfullpath); + return NULL; + } + + return newfullpath; +} + + + diff --git a/src/mu-maildir.h b/src/mu-maildir.h index 423613cd..abf2f90a 100644 --- a/src/mu-maildir.h +++ b/src/mu-maildir.h @@ -136,22 +136,49 @@ MuFlags mu_maildir_get_flags_from_path (const char* pathname); /** * get the new pathname for a message, based on the old path and the - * new flags. Note that setting/removing the MU_MSG_FLAG_NEW will - * change the directory in which a message lives. The flags are as - * specified in http://cr.yp.to/proto/maildir.html, plus - * MU_MSG_FLAG_NEW for new messages, ie the ones that live in - * new/. The flags are logically OR'ed. Note that the file does not - * have to exist; the flags are based on the path only. + * new flags and (optionally) a new maildir. Note that + * setting/removing the MU_FLAG_NEW will change the directory in which + * a message lives. The flags are as specified in + * http://cr.yp.to/proto/maildir.html, plus MU_FLAG_NEW for new + * messages, ie the ones that live in new/. The flags are logically + * OR'ed. Note that the file does not have to exist; the flags are + * based on the path only. + * * * @param oldpath the old (current) full path to the message - * (including the filename) * - * @param newflags the new flags for this message + * (including the filename) + * @param new_mdir the new maildir for this message, or NULL to keep + * it in the current one. The maildir is the absolute file system + * path, without the 'cur' or 'new' + * @param new_flags the new flags for this message * * @return a new path name; use g_free when done with. NULL in case of * error. */ -char* mu_maildir_get_path_from_flags (const char *oldpath, - MuFlags newflags); +char* mu_maildir_get_new_path (const char *oldpath, const char *new_mdir, + MuFlags new_flags); + +/** + * move a message file to another maildir; the function returns the full + * path to the new message. + * + * @param msgpath an absolute file system path to an existing message in an + * actual maildir + * @param targetmdir the target maildir; note that this the base-level + * Maildir, ie. /home/user/Maildir/archive, and must _not_ include the + * 'cur' or 'new' part. Note that the target maildir must be on the + * same filesystem. If you specify NULL for targetmdir, only the flags + * of the message are affected; note that this may still involve a + * moved to another directory (say, from new/ to cur/) + * @param flags to set for the target (influences the filename, path) + * @param err (may be NULL) may contain error information; note if the + * function return FALSE, err is not set for all error condition + * (ie. not for parameter errors) + * @return return the full path name of the target file (g_free) if + * the move succeeded, NULL otherwise + */ +gchar* mu_maildir_move_message (const char* oldpath, const char* targetmdir, + MuFlags newflags, GError **err); G_END_DECLS diff --git a/src/mu-msg.c b/src/mu-msg.c index 168afd41..6883a1d5 100644 --- a/src/mu-msg.c +++ b/src/mu-msg.c @@ -680,199 +680,6 @@ mu_msg_is_readable (MuMsg *self) == 0) ? TRUE : FALSE; } -enum _MaildirType { - MAILDIR_TYPE_CUR, - MAILDIR_TYPE_NEW, - MAILDIR_TYPE_OTHER -}; -typedef enum _MaildirType MaildirType; - -static MaildirType -get_maildir_type (const char *path) -{ - MaildirType mtype; - gchar *dirname; - - dirname = g_path_get_dirname (path); - /* g_path_get_dirname does not specify if the name includes - * the closing '/'... if it does, remove it */ - if (dirname[strlen(dirname) - 1 ] == G_DIR_SEPARATOR) - dirname[strlen(dirname) - 1] = '\0'; - - if (g_str_has_suffix (dirname, "cur")) - mtype = MAILDIR_TYPE_CUR; - else if (g_str_has_suffix (dirname, "new")) - mtype = MAILDIR_TYPE_NEW; - else - mtype = MAILDIR_TYPE_OTHER; - - g_free (dirname); - - return mtype; -} - -char* -get_new_fullpath (const char *oldpath, const char *targetmdir, - MaildirType mtype, MuFlags flags) -{ - char *filename, *newfullpath; - const char* mdirsub; - - filename = g_path_get_basename (oldpath); - - if (mtype == MAILDIR_TYPE_CUR) - mdirsub = "cur"; - else if (mtype == MAILDIR_TYPE_NEW) - mdirsub = "new"; - else { - g_free (filename); - g_return_val_if_reached (NULL); - return NULL; - } - - newfullpath = g_strdup_printf ("%s%c%s%c%s", - targetmdir, - G_DIR_SEPARATOR, - mdirsub, - G_DIR_SEPARATOR, - filename); - g_free (filename); - - /* we update the filename for the new flags; in case the NEW - * flag is set/unset, this can also influence the dir */ - if (flags != MU_FLAG_NONE) { - gchar *tmp; - tmp = mu_maildir_get_path_from_flags (newfullpath, flags); - g_free (newfullpath); - newfullpath = tmp; - } - - return newfullpath; -} - - -static gboolean -msg_move (const char* oldpath, const char *newfullpath, GError **err) -{ - if (access (oldpath, R_OK) != 0) { - g_set_error (err, 0, MU_ERROR_FILE, "cannot read %s", - oldpath); - return FALSE; - } - - - if (access (newfullpath, F_OK) == 0) { - g_set_error (err, 0, MU_ERROR_FILE, "%s already exists", - newfullpath); - return FALSE; - } - - if (rename (oldpath, newfullpath) != 0) { - g_set_error (err, 0, MU_ERROR_FILE, "error moving %s to %s", - oldpath, newfullpath); - return FALSE; - } - - /* double check -- is the target really there? */ - if (access (newfullpath, F_OK) != 0) { - g_set_error (err, 0, MU_ERROR_FILE, "can't find target (%s)", - newfullpath); - return FALSE; - } - - if (access (oldpath, F_OK) == 0) { - g_set_error (err, 0, MU_ERROR_FILE, "source is still there (%s)", - oldpath); - return FALSE; - } - - return TRUE; -} - - -static gboolean -check_source_file (const char *src, MaildirType *mtype, GError **err) -{ - if (!g_path_is_absolute(src)) { - g_set_error (err, 0, MU_ERROR_FILE, - "source is not an absolute path: '%s'", src); - return FALSE; - } - - *mtype = get_maildir_type (src); - if (*mtype != MAILDIR_TYPE_CUR && *mtype != MAILDIR_TYPE_NEW) { - g_set_error (err, 0, MU_ERROR_FILE, - "source is not in a maildir: '%s'", src); - return FALSE; - } - - return TRUE; -} - -static gboolean -check_target_dir (const char* targetmdir, GError **err) -{ - if (!g_path_is_absolute(targetmdir)) { - g_set_error (err, 0, MU_ERROR_FILE, - "target is not an absolute path: '%s'", targetmdir); - return FALSE; - } - - if (!mu_util_check_dir (targetmdir, TRUE, TRUE)) { - g_set_error (err, 0, MU_ERROR_FILE, - "target is not a read-writable dir: '%s'", targetmdir); - return FALSE; - } - - return TRUE; -} - - -/* - * move a msg to another maildir, trying to maintain 'integrity', - * ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be - * super-paranoid here... - */ -gchar* -mu_msg_file_move_to_maildir (const char* oldpath, const char* targetmdir, - MuFlags flags, GError **err) -{ - MaildirType mtype; - char *newfullpath; - gboolean rv; - - g_return_val_if_fail (oldpath, FALSE); - g_return_val_if_fail (targetmdir, FALSE); - - if (!check_source_file (oldpath, &mtype, err)) - return FALSE; - - if (!check_target_dir (targetmdir, err)) - return FALSE; - - newfullpath = get_new_fullpath (oldpath, targetmdir, mtype, flags); - if (!newfullpath) { - g_set_error (err, 0, MU_ERROR_FILE, - "failed to determine target full path"); - return FALSE; - } - - if (g_strcmp0 (oldpath, newfullpath) == 0) { - g_set_error (err, 0, MU_ERROR_FILE, - "target equals source"); - return FALSE; - } - - rv = msg_move (oldpath, newfullpath, err); - if (!rv) { - g_free (newfullpath); - return NULL; - } - - return newfullpath; -} - - /* * move a msg to another maildir, trying to maintain 'integrity', * ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be @@ -885,10 +692,9 @@ mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir, char *newfullpath; g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (targetmdir, FALSE); - newfullpath = mu_msg_file_move_to_maildir (mu_msg_get_path (self), - targetmdir, flags, err); + newfullpath = mu_maildir_move_message (mu_msg_get_path (self), + targetmdir, flags, err); if (newfullpath) /* update our path to new one... */ mu_msg_cache_set_str (self->_cache, MU_MSG_FIELD_ID_PATH, newfullpath, TRUE); /* the cache will free the string */ diff --git a/src/mu-msg.h b/src/mu-msg.h index 1da47e1b..826fe476 100644 --- a/src/mu-msg.h +++ b/src/mu-msg.h @@ -381,33 +381,28 @@ gboolean mu_msg_is_readable (MuMsg *self); */ char* mu_msg_to_sexp (MuMsg *msg, gboolean dbonly); - - /** - * move a message to another maildir; the function returns the full - * path to the new message, and changes the msg to now point to the - * new maildir. mu_msg_file_move_to_maildir, but takes a msgpath as it - * argument + * move a message to another maildir * * @param msg a message with an existing file system path in an actual * maildir - * @param msgpath an absolute file system path to an existing message in an - * actual maildir * @param targetmdir the target maildir; note that this the base-level * Maildir, ie. /home/user/Maildir/archive, and must _not_ include the * 'cur' or 'new' part. mu_msg_move_to_maildir will make sure that the - * copy is from new/ to new/ and cur/ to cur/. Also note that the target - * maildir must be on the same filesystem. * - * @param flags to set for the target (influences the filename) + * copy is from new/ to new/ and cur/ to cur/. Also note that the + * target maildir must be on the same filesystem. If you specify NULL + * for targetmdir, only the flags of the message are affected; note + * that this may still involve a moved to another directory (say, from + * new/ to cur/) + * @param flags to set for the target (influences the filename, path) * @param err (may be NULL) may contain error information; note if the * function return FALSE, err is not set for all error condition * (ie. not for parameter errors) - * @return TRUE if it worked, FALSE otherwise (mu_msg_move_to_maildir) or the full path name of the target file (g_free) for mu_msg_file_move_to_maildir + * @return TRUE if it worked, FALSE otherwise */ gboolean mu_msg_move_to_maildir (MuMsg *msg, const char* targetmdir, MuFlags flags, GError **err); -char* mu_msg_file_move_to_maildir (const char *msgpath, const char* targetmdir, - MuFlags flags, GError **err); + enum _MuMsgContactType { /* Reply-To:? */ MU_MSG_CONTACT_TYPE_TO = 0, diff --git a/src/tests/test-mu-msg.c b/src/tests/test-mu-msg.c index cfc1d349..88dc7133 100644 --- a/src/tests/test-mu-msg.c +++ b/src/tests/test-mu-msg.c @@ -168,7 +168,6 @@ test_mu_msg_03 (void) msg = mu_msg_new_from_file (MU_TESTMAILDIR "cur/1283599333.1840_11.cthulhu!2,", NULL, NULL); - g_assert_cmpstr (mu_msg_get_to(msg), ==, "Bilbo Baggins "); g_assert_cmpstr (mu_msg_get_subject(msg), @@ -182,11 +181,9 @@ test_mu_msg_03 (void) g_assert_cmpstr (mu_msg_get_body_text(msg), ==, "\nLet's write some fünkÿ text\nusing umlauts.\n\nFoo.\n"); - g_assert_cmpuint (mu_msg_get_flags(msg), - ==, MU_FLAG_UNREAD); - - + ==, MU_FLAG_NONE); + mu_msg_unref (msg); }