diff --git a/NEWS b/NEWS index aebe0f2b..13eea019 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ ** Release 0.9.8 <> - '--descending' has been renamed into '--reverse' + - search for attachment MIME-type using 'attmime:' or 'y:' + - experimental emacs-based mail client * Release 0.9.7 <> diff --git a/man/mu-easy.1 b/man/mu-easy.1 index ea44c921..9759d96a 100644 --- a/man/mu-easy.1 +++ b/man/mu-easy.1 @@ -1,6 +1,6 @@ -.TH MU-EASY 1 "August 2011" "User Manuals" +.TH MU-EASY 1 "November 2011" "User Manuals" -.SH NAME +.SH NAME mu easy \- a quick introduction to mu @@ -24,7 +24,7 @@ you won't be able to index/search your mail. Before you can search e-mails, you'll first need to index them: .nf - \fB$ mu index\fR + \fB$ mu index\fR .fi The process can take a few minutes, depending on the amount of mail you have, @@ -54,7 +54,7 @@ some examples for common cases. First, let's search for all messages sent to Julius Caesar regarding fruit: .nf -\fB$ mu find t:julius fruit\fR +\fB$ mu find t:julius fruit\fR .fi This should return something like: @@ -73,7 +73,7 @@ date/sender/subject. However, we can change this using the \fI--fields\fR parameter (see the \fBmu-find\fR man page for the details): .nf - \fB$ mu find --fields="t s" t:julius fruit\fR + \fB$ mu find --fields="t s" t:julius fruit\fR .fi In other words, display the 'To:'-field (t) and the subject (s). This should @@ -90,7 +90,7 @@ is, it displays messages that match all the parameters. However, we can use logical OR as well: .nf - \fB$ mu find t:julius OR f:socrates\fR + \fB$ mu find t:julius OR f:socrates\fR .fi In other words, display messages that are either sent to Julius Caesar @@ -106,7 +106,7 @@ a 'summary' of the first lines of the message using the \fI--summary\fR option, which will 'summarize' the first \fIn\fR lines of the message: .nf - \fB$ mu find --summary napoleon m:/archive\fR + \fB$ mu find --summary napoleon m:/archive\fR .fi .nf @@ -130,21 +130,21 @@ version 0.9 or later. Get all important messages which are signed: .nf - \fB$ mu find flag:signed prio:high \fR + \fB$ mu find flag:signed prio:high \fR .fi Get all messages from Jim without an attachment: .nf - \fB$ mu find from:jim AND NOT flag:attach\fR + \fB$ mu find from:jim AND NOT flag:attach\fR .fi Get all unread messages where the subject mentions Ångström: .nf - \fB$ mu find subject:Ångström flag:unread\fR + \fB$ mu find subject:Ångström flag:unread\fR .fi which is equivalent to: .nf - \fB$ mu find subject:angstrom flag:unread\fR + \fB$ mu find subject:angstrom flag:unread\fR .fi because does mu is case-insensitive and accent-insensitive. @@ -159,7 +159,7 @@ Get all messages received today: \fB$ mu find date:today..now\fR .fi -Get all message we got in the last two weeks about emacs: +Get all messages we got in the last two weeks about emacs: .nf \fB$ mu find date:2w..now emacs\fR .fi @@ -182,6 +182,25 @@ filename, for example: .fi will get you all message with an attachment starting with 'pic'. +If you want to find attachments with a certain MIME-type, you can use the +following: + +Get all messages with PDF attachments: +.nf + \fB$ mu find attmime:application/pdf\fR +.fi + +or even: + +Get all messages with image attachments: +.nf + \fB$ mu find 'attmime:image/*'\fR +.fi + +Note that (1) the '*' wildcard can only be used as the rightmost thing in a +search query, and (2) that you need to quote the search term, because +otherwise your shell will interpret the '*' (expanding it to all files in the +current directory -- probably not what you want). .SH DISPLAYING MESSAGES @@ -195,14 +214,14 @@ need its path. To get the path (think \fBl\fRocation) for our first example we can use: .nf - \fB$ mu find --fields="l" t:julius fruit\fR + \fB$ mu find --fields="l" t:julius fruit\fR .fi And we'll get someting like: .nf /home/someuser/Maildir/archive/cur/1266188485_0.6850.cthulhu:2, .fi -We can now display this message: +We can now display this message: .nf \fB$ mu view /home/someuser/Maildir/archive/cur/1266188485_0.6850.cthulhu:2,\fR @@ -225,7 +244,7 @@ find \fIcontacts\fR, that is, names + addresses. Without any search expression, \fBmu cfind\fR lists all of your contacts. .nf - \fB$ mu cfind julius\fR + \fB$ mu cfind julius\fR .fi will find all contacts with 'julius' in either name or e-mail address. Note @@ -237,7 +256,7 @@ program. For example, to export your contact information to a \fBmutt\fR address book file, you can use something like: .nf - \fB$ mu cfind --format=mutt-alias > ~/mutt-aliases \fR + \fB$ mu cfind --format=mutt-alias > ~/mutt-aliases \fR .fi Then, you can use them in \fBmutt\fR if you add something like \fBsource diff --git a/man/mu-find.1 b/man/mu-find.1 index f84932e3..a015926c 100644 --- a/man/mu-find.1 +++ b/man/mu-find.1 @@ -1,4 +1,4 @@ -.TH MU FIND 1 "July 2011" "User Manuals" +.TH MU FIND 1 "November 2011" "User Manuals" .SH NAME @@ -123,6 +123,7 @@ search fields and their abbreviations: date,d Date-Range size,z Message size attach,a Attachment filename + attmime,y Attachment MIME-type tag,x Tag for the message (contents of the \fIX-Label\fR field) .fi @@ -474,6 +475,23 @@ Find all unread messages with attachments: .fi +Find all messages with PDF-attachments: + +.nf + $ mu find attmime:application/pdf +.fi + +Find all messages with attached images: + +.nf + $ mu find 'attmime:image/*' +.fi + +Note[1]: the argument needs to be quoted, or the shell will interpret the '*' +Note[2]: the '*' wild card can only be used as the last (rightmost) part of a +search term. + + .SS Integrating mu find with mail clients .TP diff --git a/src/mu-msg-fields.c b/src/mu-msg-fields.c index de1e9726..6a160022 100644 --- a/src/mu-msg-fields.c +++ b/src/mu-msg-fields.c @@ -34,24 +34,31 @@ enum _FieldFlags { FLAG_GMIME = 1 << 0, /* field retrieved through * gmime */ FLAG_XAPIAN_INDEX = 1 << 1, /* field is indexed in - * xapian */ + * xapian (i.e., the text + * is processed */ FLAG_XAPIAN_TERM = 1 << 2, /* field stored as term in - * xapian */ + * xapian (so it can be searched) */ FLAG_XAPIAN_VALUE = 1 << 3, /* field stored as value in - * xapian */ + * xapian (so the literal + * value can be + * retrieved) */ FLAG_XAPIAN_CONTACT = 1 << 4, /* field contains one or more * e-mail-addresses */ FLAG_XAPIAN_ESCAPE = 1 << 5, /* field needs escaping for - * xapian */ + * xapian (so the xapian + * query does not get + * confused) */ FLAG_XAPIAN_BOOLEAN = 1 << 6, /* use 'add_boolean_prefix' * for Xapian queries */ FLAG_XAPIAN_PREFIX_ONLY = 1 << 7, /* whether this fields * matches only when the * prefix is explicitly - * included */ + * included in the search + * query -- e.g., the text + * body */ FLAG_NORMALIZE = 1 << 8, /* field needs flattening for * case/accents */ - FLAG_DONT_CACHE = 1 << 9 /* don't cache this field in + FLAG_DONT_CACHE = 1 << 9, /* don't cache this field in * the MuMsg cache */ }; typedef enum _FieldFlags FieldFlags; @@ -81,8 +88,14 @@ static const MuMsgField FIELD_DATA[] = { MU_MSG_FIELD_ID_ATTACH, MU_MSG_FIELD_TYPE_STRING, "attach" , 'a', 'A', - FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_NORMALIZE | - FLAG_DONT_CACHE + FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_NORMALIZE | FLAG_DONT_CACHE + }, + + { + MU_MSG_FIELD_ID_ATTACH_MIME_TYPE, + MU_MSG_FIELD_TYPE_STRING, + "attmime" , 'y', 'Y', + FLAG_XAPIAN_TERM | FLAG_XAPIAN_ESCAPE }, { @@ -213,6 +226,13 @@ static const MuMsgField FIELD_DATA[] = { "tag", 'x', 'X', FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_PREFIX_ONLY | FLAG_NORMALIZE | FLAG_XAPIAN_ESCAPE + }, + + { /* special, internal field, to get a unique key */ + MU_MSG_FIELD_ID_UID, + MU_MSG_FIELD_TYPE_STRING, + "uid", 0, 'U', + FLAG_XAPIAN_TERM } /* note, mu-store also use the 'Q' internal prefix for its uids */ diff --git a/src/mu-msg-fields.h b/src/mu-msg-fields.h index 1c19364e..25f0843b 100644 --- a/src/mu-msg-fields.h +++ b/src/mu-msg-fields.h @@ -29,7 +29,9 @@ G_BEGIN_DECLS enum _MuMsgFieldId { /* first all the string-based ones */ - MU_MSG_FIELD_ID_ATTACH = 0, + MU_MSG_FIELD_ID_ATTACH = 0, + MU_MSG_FIELD_ID_ATTACH_MIME_TYPE, /* mime-type */ + MU_MSG_FIELD_ID_BCC, MU_MSG_FIELD_ID_BODY_HTML, MU_MSG_FIELD_ID_BODY_TEXT, @@ -40,6 +42,9 @@ enum _MuMsgFieldId { MU_MSG_FIELD_ID_PATH, MU_MSG_FIELD_ID_SUBJECT, MU_MSG_FIELD_ID_TO, + + MU_MSG_FIELD_ID_UID, /* special, generated from path */ + /* MU_MSG_STRING_FIELD_ID_NUM, see below */ /* string list items... */ @@ -59,7 +64,7 @@ typedef guint8 MuMsgFieldId; /* some specials... */ static const MuMsgFieldId MU_MSG_FIELD_ID_NONE = (MuMsgFieldId)-1; -#define MU_MSG_STRING_FIELD_ID_NUM (MU_MSG_FIELD_ID_TO + 1) +#define MU_MSG_STRING_FIELD_ID_NUM (MU_MSG_FIELD_ID_UID + 1) #define mu_msg_field_id_is_valid(MFID) \ ((MFID) < MU_MSG_FIELD_ID_NUM) diff --git a/src/mu-msg-file.c b/src/mu-msg-file.c index b84ec9f5..fe09a93a 100644 --- a/src/mu-msg-file.c +++ b/src/mu-msg-file.c @@ -594,7 +594,7 @@ get_body (MuMsgFile *self, gboolean want_html) /* note, str may be NULL (no body), but that's not necessarily * an error; we only warn when an actual error occured */ if (err) - g_warning ("error occured while retrieving %s body" + g_warning ("error occured while retrieving %s body " "for message %s", want_html ? "html" : "text", self->_path); return str; diff --git a/src/mu-store-priv.hh b/src/mu-store-priv.hh index adbf5bdc..6b9ef7bd 100644 --- a/src/mu-store-priv.hh +++ b/src/mu-store-priv.hh @@ -225,9 +225,4 @@ private: }; -/* Xapian DB prefix for the UID value */ -#define MU_STORE_UID_PREFIX "Q" - - - #endif /*__MU_STORE_PRIV_HH__*/ diff --git a/src/mu-store-read.cc b/src/mu-store-read.cc index 57de42a6..f6ae6ac6 100644 --- a/src/mu-store-read.cc +++ b/src/mu-store-read.cc @@ -50,6 +50,8 @@ _MuStore::get_uid_term (const char* path) unsigned djbhash, bkdrhash, bkdrseed; unsigned u; static char hex[18]; + static const char uid_prefix = + mu_msg_field_xapian_prefix(MU_MSG_FIELD_ID_UID); djbhash = 5381; bkdrhash = 0; @@ -60,9 +62,8 @@ _MuStore::get_uid_term (const char* path) bkdrhash = bkdrhash * bkdrseed + path[u]; } - snprintf (hex, sizeof(hex), - MU_STORE_UID_PREFIX "%08x%08x", - djbhash, bkdrhash); + snprintf (hex, sizeof(hex), "%c%08x%08x", + uid_prefix, djbhash, bkdrhash); return hex; } diff --git a/src/mu-store-write.cc b/src/mu-store-write.cc index 988aa0c2..417ac72a 100644 --- a/src/mu-store-write.cc +++ b/src/mu-store-write.cc @@ -405,19 +405,32 @@ struct PartData { static void each_part (MuMsg *msg, MuMsgPart *part, PartData *pdata) { + static const std::string + att (prefix(MU_MSG_FIELD_ID_ATTACH)), + mime (prefix(MU_MSG_FIELD_ID_ATTACH_MIME_TYPE)); + if (mu_msg_part_looks_like_attachment (part, TRUE) && (part->file_name)) { char val[MuStore::MAX_TERM_LENGTH + 1]; strncpy (val, part->file_name, sizeof(val)); - /* now, let's create a terms... */ + /* now, let's create a term... */ mu_str_normalize_in_place (val, TRUE); mu_str_ascii_xapian_escape_in_place (val); pdata->_doc.add_term - (prefix(pdata->_mfid) + - std::string(val, 0, MuStore::MAX_TERM_LENGTH)); + (att + std::string(val, 0, MuStore::MAX_TERM_LENGTH)); + + /* save the mime type */ + if (part->type) { + gchar *str; + str = g_strdup_printf ("%s/%s", part->type, part->subtype); + pdata->_doc.add_term + (mime + std::string(str, 0, MuStore::MAX_TERM_LENGTH)); + g_free (str); + } else + pdata->_doc.add_term (mime + "application/octet-stream"); } } @@ -482,9 +495,12 @@ add_terms_values (MuMsgFieldId mfid, MsgDoc* msgdoc) case MU_MSG_FIELD_ID_BODY_TEXT: add_terms_values_body (*msgdoc->_doc, msgdoc->_msg, mfid); break; - case MU_MSG_FIELD_ID_ATTACH: + case MU_MSG_FIELD_ID_ATTACH: /* also takes care of MU_MSG_FIELD_ID_ATTACH_MIME */ add_terms_values_attach (*msgdoc->_doc, msgdoc->_msg, mfid); break; + case MU_MSG_FIELD_ID_ATTACH_MIME_TYPE: + case MU_MSG_FIELD_ID_UID: + break; /* already taken care of elsewhere */ default: if (mu_msg_field_is_numeric (mfid)) add_terms_values_number (*msgdoc->_doc, msgdoc->_msg,