* <many> add support for displaying, searching the Bcc: field

This commit is contained in:
Dirk-Jan C. Binnema
2011-05-01 18:31:00 +03:00
parent 301de1bb81
commit c07b8e4529
11 changed files with 106 additions and 44 deletions

View File

@ -1,10 +1,8 @@
.TH MU FIND 1 "April 2011" "User Manuals" .TH MU FIND 1 "May 2011" "User Manuals"
.SH NAME .SH NAME
mu find \- find e-mail messages in the mu find \- find e-mail messages in the \fBmu\fR database.
.B mu
database
.SH SYNOPSIS .SH SYNOPSIS
@ -97,10 +95,11 @@ can abbreviate \fBsubject:\fR to just \fBs:\fR. Here is the full table of the
search fields and their abbreviations: search fields and their abbreviations:
.nf .nf
cc,c CC (Carbon-Copy) recipient cc,c Cc (carbon-copy) recipient(s)
bcc,h Bcc (blind-carbon-copy) recipient(s)
from,f Message sender from,f Message sender
subject,s Message subject subject,s Message subject
to,t To: recipient to,t To: recipient(s)
maildir,m Maildir maildir,m Maildir
msgid,i Message-ID msgid,i Message-ID
prio,p Message priority ('low', 'normal' or 'high') prio,p Message priority ('low', 'normal' or 'high')
@ -264,7 +263,8 @@ search parameters; the complete list:
.nf .nf
t \fBt\fRo: recipient t \fBt\fRo: recipient
c \fBc\fRc: (Carbon-Copy) recipient c \fBc\fRc: (carbon-copy) recipient
h Bcc: (blind carbon-copy, \fBh\fRidden) recipient
d Sent \fBd\fRate of the message d Sent \fBd\fRate of the message
f Message sender (\fBf\fRrom:) f Message sender (\fBf\fRrom:)
g Message flags (fla\fBg\fRs) g Message flags (fla\fBg\fRs)
@ -288,14 +288,15 @@ specifies the field to sort the search results by, and the direction. The
following fields are supported: following fields are supported:
.nf .nf
cc,c CC (Carbon-Copy) recipient cc,c Cc (carbon-copy) recipient(s)
bcc,h Bcc (blind-carbon-copy) recipient(s)
date,d message sent date date,d message sent date
from,f message sender from,f message sender
maildir,m maildir maildir,m maildir
msgid,i message id msgid,i message id
prio,p message priority prio,p message priority
subject,s message subject subject,s message subject
to,t To:-recipient to,t To:-recipient(s)
.fi .fi
Thus, for example, to sort messages by date, you could specify: Thus, for example, to sort messages by date, you could specify:

View File

@ -35,52 +35,54 @@ MuMsgContact *
mu_msg_contact_new (const char *name, const char *address, mu_msg_contact_new (const char *name, const char *address,
MuMsgContactType type) MuMsgContactType type)
{ {
MuMsgContact *contact; MuMsgContact *self;
g_return_val_if_fail (name, NULL); g_return_val_if_fail (name, NULL);
g_return_val_if_fail (address, NULL); g_return_val_if_fail (address, NULL);
g_return_val_if_fail (!mu_msg_contact_type_is_valid(type), g_return_val_if_fail (!mu_msg_contact_type_is_valid(type),
NULL); NULL);
contact = g_slice_new (MuMsgContact); self = g_slice_new (MuMsgContact);
contact->name = g_strdup(name); self->name = g_strdup(name);
contact->address = g_strdup(address); self->address = g_strdup(address);
contact->type = type; self->type = type;
return contact; return self;
} }
void void
mu_msg_contact_destroy (MuMsgContact *contacts) mu_msg_contact_destroy (MuMsgContact *self)
{ {
if (contacts) {
g_free ((gchar*)contacts->name); if (!self)
g_free ((gchar*)contacts->address); return;
g_slice_free (MuMsgContact, contacts);
} g_free ((void*)self->name);
g_free ((void*)self->address);
g_slice_free (MuMsgContact, self);
} }
static gboolean static gboolean
fill_contact (MuMsgContact *contact, InternetAddress *addr, fill_contact (MuMsgContact *self, InternetAddress *addr,
MuMsgContactType ctype) MuMsgContactType ctype)
{ {
if (!addr) if (!addr)
return FALSE; return FALSE;
contact->name = internet_address_get_name (addr); self->name = internet_address_get_name (addr);
contact->type = ctype; self->type = ctype;
/* we only support internet mailbox addresses; if we don't /* we only support internet mailbox addresses; if we don't
* check, g_mime hits an assert * check, g_mime hits an assert
*/ */
if (INTERNET_ADDRESS_IS_MAILBOX(addr)) { if (INTERNET_ADDRESS_IS_MAILBOX(addr))
contact->address = internet_address_mailbox_get_addr self->address = internet_address_mailbox_get_addr
(INTERNET_ADDRESS_MAILBOX(addr)); (INTERNET_ADDRESS_MAILBOX(addr));
} else else
contact->address = NULL; self->address = NULL;
return TRUE; return TRUE;
} }
@ -110,8 +112,6 @@ address_list_foreach (InternetAddressList *addrlist,
if (!(func)(&contact, user_data)) if (!(func)(&contact, user_data))
break; break;
} }
return;
} }
@ -128,6 +128,7 @@ get_contacts_from (MuMsg *msg, MuMsgContactForeachFunc func,
* splitting in names and addresses for us */ * splitting in names and addresses for us */
lst = internet_address_list_parse_string ( lst = internet_address_list_parse_string (
g_mime_message_get_sender (msg->_mime_msg)); g_mime_message_get_sender (msg->_mime_msg));
if (lst) { if (lst) {
address_list_foreach (lst, MU_MSG_CONTACT_TYPE_FROM, address_list_foreach (lst, MU_MSG_CONTACT_TYPE_FROM,
func, user_data); func, user_data);

View File

@ -26,9 +26,9 @@
G_BEGIN_DECLS G_BEGIN_DECLS
enum _MuMsgContactType { /* Reply-To:? */ enum _MuMsgContactType { /* Reply-To:? */
MU_MSG_CONTACT_TYPE_TO = 0, MU_MSG_CONTACT_TYPE_TO = 0,
MU_MSG_CONTACT_TYPE_FROM, MU_MSG_CONTACT_TYPE_FROM,
MU_MSG_CONTACT_TYPE_CC, MU_MSG_CONTACT_TYPE_CC,
MU_MSG_CONTACT_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC,
MU_MSG_CONTACT_TYPE_NUM MU_MSG_CONTACT_TYPE_NUM
@ -39,10 +39,10 @@ typedef guint MuMsgContactType;
((MCT) < MU_MSG_CONTACT_TYPE_NUM) ((MCT) < MU_MSG_CONTACT_TYPE_NUM)
struct _MuMsgContact { struct _MuMsgContact {
const char *name; /* Foo Bar */ const char *name; /* Foo Bar */
const char *address; /* foo@bar.cuux */ const char *address; /* foo@bar.cuux */
MuMsgContactType type; /*MU_MSG_CONTACT_TYPE_{ TO, MuMsgContactType type; /* MU_MSG_CONTACT_TYPE_{ TO,
* CC, BCC, FROM}*/ * CC, BCC, FROM} */
}; };
typedef struct _MuMsgContact MuMsgContact; typedef struct _MuMsgContact MuMsgContact;
@ -59,7 +59,8 @@ typedef struct _MuMsgContact MuMsgContact;
* needed. * needed.
*/ */
MuMsgContact *mu_msg_contact_new (const char *name, const char *address, MuMsgContact *mu_msg_contact_new (const char *name, const char *address,
MuMsgContactType type); MuMsgContactType type)
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
/** /**
* destroy a MuMsgConcact object * destroy a MuMsgConcact object

View File

@ -59,6 +59,14 @@ typedef struct _MuMsgField MuMsgField;
* misinterpreted by the query-preprocesser which turns queries into * misinterpreted by the query-preprocesser which turns queries into
* lowercase */ * lowercase */
static const MuMsgField FIELD_DATA[] = { static const MuMsgField FIELD_DATA[] = {
{
MU_MSG_FIELD_ID_BCC,
MU_MSG_FIELD_TYPE_STRING,
"bcc" , 'h', 'H', /* 'hidden */
FLAG_GMIME | FLAG_XAPIAN_CONTACT | FLAG_XAPIAN_VALUE
},
{ {
MU_MSG_FIELD_ID_BODY_TEXT, MU_MSG_FIELD_ID_BODY_TEXT,
MU_MSG_FIELD_TYPE_STRING, MU_MSG_FIELD_TYPE_STRING,

View File

@ -26,8 +26,10 @@ G_BEGIN_DECLS
/* don't change the order, add new types at the end, as these numbers /* don't change the order, add new types at the end, as these numbers
* are used in the database */ * are used in the database */
enum _MuMsgFieldId { enum _MuMsgFieldId {
MU_MSG_FIELD_ID_BODY_TEXT = 0,
MU_MSG_FIELD_ID_BCC = 0,
MU_MSG_FIELD_ID_BODY_TEXT,
MU_MSG_FIELD_ID_BODY_HTML, MU_MSG_FIELD_ID_BODY_HTML,
MU_MSG_FIELD_ID_CC, MU_MSG_FIELD_ID_CC,
MU_MSG_FIELD_ID_DATE, MU_MSG_FIELD_ID_DATE,

View File

@ -287,6 +287,13 @@ mu_msg_iter_get_cc (MuMsgIter *iter)
return get_field (iter, MU_MSG_FIELD_ID_CC); return get_field (iter, MU_MSG_FIELD_ID_CC);
} }
const char*
mu_msg_iter_get_bcc (MuMsgIter *iter)
{
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
return get_field (iter, MU_MSG_FIELD_ID_BCC);
}
const char* const char*
mu_msg_iter_get_subject (MuMsgIter *iter) mu_msg_iter_get_subject (MuMsgIter *iter)

View File

@ -205,7 +205,7 @@ const char* mu_msg_iter_get_to (MuMsgIter *iter);
/** /**
* get the message recipient (Cc:) of the message * get the 'carbon-copy' recipient(s) (Cc:) of the message
* *
* @param iter a valid MuMsgIter iterator * @param iter a valid MuMsgIter iterator
* *
@ -213,6 +213,17 @@ const char* mu_msg_iter_get_to (MuMsgIter *iter);
*/ */
const char* mu_msg_iter_get_cc (MuMsgIter *iter); const char* mu_msg_iter_get_cc (MuMsgIter *iter);
/**
* get the 'blind carbon-copy' message recipient(s) (Bcc:) of the
* message
*
* @param iter a valid MuMsgIter iterator
*
* @return the Bcc-recipient(s), or NULL in case of error
*/
const char* mu_msg_iter_get_bcc (MuMsgIter *iter);
/** /**
* get the subject of the message * get the subject of the message
* *

View File

@ -38,6 +38,7 @@ enum _StringFields {
TO_FIELD, /* To: */ TO_FIELD, /* To: */
CC_FIELD, /* Cc: */ CC_FIELD, /* Cc: */
BCC_FIELD, /* Bcc: */
PATH_FIELD, /* full path */ PATH_FIELD, /* full path */
MDIR_FIELD, /* the maildir */ MDIR_FIELD, /* the maildir */

View File

@ -292,7 +292,7 @@ get_recipient (MuMsg *msg, GMimeRecipientType rtype, StringFields field)
* internet_address_list_to_string? */ * internet_address_list_to_string? */
recep = (char*)internet_address_list_to_string (receps, recep = (char*)internet_address_list_to_string (receps,
TRUE); TRUE);
if (recep && recep[0]=='\0') if (mu_str_is_empty(recep))
g_free (recep); g_free (recep);
else else
msg->_fields[field] = recep; msg->_fields[field] = recep;
@ -316,6 +316,13 @@ mu_msg_get_cc (MuMsg *msg)
return get_recipient (msg, GMIME_RECIPIENT_TYPE_CC, CC_FIELD); return get_recipient (msg, GMIME_RECIPIENT_TYPE_CC, CC_FIELD);
} }
const char*
mu_msg_get_bcc (MuMsg *msg)
{
g_return_val_if_fail (msg, NULL);
return get_recipient (msg, GMIME_RECIPIENT_TYPE_BCC, BCC_FIELD);
}
time_t time_t
mu_msg_get_date (MuMsg *msg) mu_msg_get_date (MuMsg *msg)
@ -643,7 +650,14 @@ convert_to_utf8 (GMimePart *part, char *buffer)
{ {
GMimeContentType *ctype; GMimeContentType *ctype;
const char* charset; const char* charset;
char *cur;
/* optimization: if the buffer is plain ascii, no conversion
* is done... */
for (cur = buffer; *cur && *cur < 0x80; ++cur);
if (*cur == '\0')
return buffer;
ctype = g_mime_object_get_content_type (GMIME_OBJECT(part)); ctype = g_mime_object_get_content_type (GMIME_OBJECT(part));
g_return_val_if_fail (GMIME_IS_CONTENT_TYPE(ctype), NULL); g_return_val_if_fail (GMIME_IS_CONTENT_TYPE(ctype), NULL);
@ -910,6 +924,7 @@ mu_msg_get_field_string (MuMsg *msg, MuMsgFieldId mfid)
g_return_val_if_fail (msg, NULL); g_return_val_if_fail (msg, NULL);
switch (mfid) { switch (mfid) {
case MU_MSG_FIELD_ID_BCC: return mu_msg_get_bcc (msg);
case MU_MSG_FIELD_ID_BODY_TEXT: return mu_msg_get_body_text (msg); case MU_MSG_FIELD_ID_BODY_TEXT: return mu_msg_get_body_text (msg);
case MU_MSG_FIELD_ID_BODY_HTML: return mu_msg_get_body_html (msg); case MU_MSG_FIELD_ID_BODY_HTML: return mu_msg_get_body_html (msg);
case MU_MSG_FIELD_ID_CC: return mu_msg_get_cc (msg); case MU_MSG_FIELD_ID_CC: return mu_msg_get_cc (msg);

View File

@ -160,6 +160,19 @@ const char* mu_msg_get_to (MuMsg *msg);
*/ */
const char* mu_msg_get_cc (MuMsg *msg); const char* mu_msg_get_cc (MuMsg *msg);
/**
* get the blind carbon-copy recipients (Bcc:) of this message; this
* field usually only appears in outgoing messages
*
* @param msg a valid MuMsg* instance
*
* @return the Bcc: recipients of this Message or NULL in case of
* error or if there are no such recipients. the returned string
* should *not* be modified or freed.
*/
const char* mu_msg_get_bcc (MuMsg *msg);
/** /**
* get the file system path of this message * get the file system path of this message
* *

View File

@ -467,7 +467,9 @@ xapian_pfx (MuMsgContact *contact)
return prefix(MU_MSG_FIELD_ID_FROM); return prefix(MU_MSG_FIELD_ID_FROM);
case MU_MSG_CONTACT_TYPE_CC: case MU_MSG_CONTACT_TYPE_CC:
return prefix(MU_MSG_FIELD_ID_CC); return prefix(MU_MSG_FIELD_ID_CC);
default: /* dont;t support other type (e.g, bcc) */ case MU_MSG_CONTACT_TYPE_BCC:
return prefix(MU_MSG_FIELD_ID_BCC);
default:
g_warning ("unsupported contact type %u", g_warning ("unsupported contact type %u",
(unsigned)contact->type); (unsigned)contact->type);
return empty; return empty;