/* Return two stable query strings that identify exactly the matched * and unmatched messages currently in thread. If there are no * matched or unmatched messages, the returned buffers will be * NULL. */ static int get_thread_query (notmuch_thread_t *thread, char **matched_out, char **unmatched_out) { notmuch_messages_t *messages; char *escaped = NULL; size_t escaped_len = 0; *matched_out = *unmatched_out = NULL; for (messages = notmuch_thread_get_messages (thread); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { notmuch_message_t *message = notmuch_messages_get (messages); const char *mid = notmuch_message_get_message_id (message); /* Determine which query buffer to extend */ char **buf = notmuch_message_get_flag ( message, NOTMUCH_MESSAGE_FLAG_MATCH) ? matched_out : unmatched_out; /* Add this message's id: query. Since "id" is an exclusive * prefix, it is implicitly 'or'd together, so we only need to * join queries with a space. */ if (make_boolean_term (thread, "id", mid, &escaped, &escaped_len) < 0) return -1; if (*buf) *buf = talloc_asprintf_append_buffer (*buf, " %s", escaped); else *buf = talloc_strdup (thread, escaped); if (!*buf) return -1; } talloc_free (escaped); return 0; }
/* Return the number of files matching the query, or -1 for an error */ static int count_files (notmuch_query_t *query) { notmuch_messages_t *messages; notmuch_message_t *message; notmuch_filenames_t *filenames; notmuch_status_t status; int count = 0; status = notmuch_query_search_messages_st (query, &messages); if (print_status_query ("notmuch count", query, status)) return -1; for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); filenames = notmuch_message_get_filenames (message); for (; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames)) count++; notmuch_filenames_destroy (filenames); notmuch_message_destroy (message); } notmuch_messages_destroy (messages); return count; }
/* This format is currently tuned for a git send-email --notmuch hook */ static int notmuch_reply_format_headers_only(void *ctx, notmuch_config_t *config, notmuch_query_t *query, unused (notmuch_show_params_t *params), notmuch_bool_t reply_all, unused (sprinter_t *sp)) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; const char *in_reply_to, *orig_references, *references; char *reply_headers; for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); /* The 0 means we do not want headers in a "pretty" order. */ reply = g_mime_message_new (0); if (reply == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } in_reply_to = talloc_asprintf (ctx, "<%s>", notmuch_message_get_message_id (message)); g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to); orig_references = notmuch_message_get_header (message, "references"); /* We print In-Reply-To followed by References because git format-patch treats them * specially. Git does not interpret the other headers specially */ references = talloc_asprintf (ctx, "%s%s%s", orig_references ? orig_references : "", orig_references ? " " : "", in_reply_to); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references); (void)add_recipients_from_message (reply, config, message, reply_all); reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply)); printf ("%s", reply_headers); free (reply_headers); g_object_unref (G_OBJECT (reply)); reply = NULL; notmuch_message_destroy (message); } return 0; }
static notmuch_status_t show_messages (void *ctx, const notmuch_show_format_t *format, sprinter_t *sp, notmuch_messages_t *messages, int indent, notmuch_show_params_t *params) { notmuch_message_t *message; notmuch_bool_t match; notmuch_bool_t excluded; int next_indent; notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS; sp->begin_list (sp); for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { sp->begin_list (sp); message = notmuch_messages_get (messages); match = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH); excluded = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED); next_indent = indent; if ((match && (!excluded || !params->omit_excluded)) || params->entire_thread) { status = show_message (ctx, format, sp, message, indent, params); if (status && !res) res = status; next_indent = indent + 1; } else { sp->null (sp); } status = show_messages (ctx, format, sp, notmuch_message_get_replies (message), next_indent, params); if (status && !res) res = status; notmuch_message_destroy (message); sp->end (sp); } sp->end (sp); return res; }
/* * add each top level reply in the thread, and then add each * reply to the top level replies */ static void append_thread(CONTEXT *ctx, notmuch_thread_t *thread) { notmuch_messages_t *msgs; for (msgs = notmuch_thread_get_toplevel_messages(thread); notmuch_messages_valid(msgs); notmuch_messages_move_to_next(msgs)) { notmuch_message_t *m = notmuch_messages_get(msgs); append_message(ctx, m); append_replies(ctx, m); notmuch_message_destroy(m); } }
static void show_messages (void *ctx, const notmuch_show_format_t *format, notmuch_messages_t *messages, int indent, notmuch_show_params_t *params) { notmuch_message_t *message; notmuch_bool_t match; int first_set = 1; int next_indent; fputs (format->message_set_start, stdout); for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { if (!first_set) fputs (format->message_set_sep, stdout); first_set = 0; fputs (format->message_set_start, stdout); message = notmuch_messages_get (messages); match = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH); next_indent = indent; if (match || params->entire_thread) { show_message (ctx, format, message, indent, params); next_indent = indent + 1; fputs (format->message_set_sep, stdout); } show_messages (ctx, format, notmuch_message_get_replies (message), next_indent, params); notmuch_message_destroy (message); fputs (format->message_set_end, stdout); } fputs (format->message_set_end, stdout); }
/* call-seq: MESSAGES.each {|item| block } => MESSAGES * * Calls +block+ once for each message in +self+, passing that element as a * parameter. */ VALUE notmuch_rb_messages_each(VALUE self) { notmuch_message_t *message; notmuch_messages_t *messages; Data_Get_Notmuch_Messages(self, messages); for (; notmuch_messages_valid(messages); notmuch_messages_move_to_next(messages)) { message = notmuch_messages_get(messages); rb_yield(Data_Wrap_Struct(notmuch_rb_cMessage, NULL, NULL, message)); } return self; }
/* * add all the replies to a given messages into the display. * Careful, this calls itself recursively to make sure we get * everything. */ static void append_replies(CONTEXT *ctx, notmuch_message_t *top) { notmuch_messages_t *msgs; for (msgs = notmuch_message_get_replies(top); notmuch_messages_valid(msgs); notmuch_messages_move_to_next(msgs)) { notmuch_message_t *m = notmuch_messages_get(msgs); append_message(ctx, m); /* recurse through all the replies to this message too */ append_replies(ctx, m); notmuch_message_destroy(m); } }
static int notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all, unused (sprinter_t *sp)) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; mime_node_t *root; notmuch_status_t status; status = notmuch_query_search_messages_st (query, &messages); if (print_status_query ("notmuch reply", query, status)) return 1; for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); reply = create_reply_message (ctx, config, message, reply_all); /* If reply creation failed, we're out of memory, so don't * bother trying any more messages. */ if (!reply) { notmuch_message_destroy (message); return 1; } show_reply_headers (reply); g_object_unref (G_OBJECT (reply)); reply = NULL; if (mime_node_open (ctx, message, &(params->crypto), &root) == NOTMUCH_STATUS_SUCCESS) { format_part_reply (root); talloc_free (root); } notmuch_message_destroy (message); } return 0; }
static int do_search_messages (const search_format_t *format, notmuch_query_t *query, output_t output) { notmuch_message_t *message; notmuch_messages_t *messages; int first_message = 1; messages = notmuch_query_search_messages (query); if (messages == NULL) return 1; fputs (format->results_start, stdout); for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); if (! first_message) fputs (format->item_sep, stdout); if (output == OUTPUT_FILES) { format->item_id (message, "", notmuch_message_get_filename (message)); } else { /* output == OUTPUT_MESSAGES */ format->item_id (message, "id:", notmuch_message_get_message_id (message)); } first_message = 0; notmuch_message_destroy (message); } notmuch_messages_destroy (messages); fputs (format->results_end, stdout); return 0; }
/* Tag messages matching 'query_string' according to 'tag_ops' */ static int tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string, tag_op_list_t *tag_ops, tag_op_flag_t flags) { notmuch_query_t *query; notmuch_messages_t *messages; notmuch_message_t *message; int ret = NOTMUCH_STATUS_SUCCESS; if (! (flags & TAG_FLAG_REMOVE_ALL)) { /* Optimize the query so it excludes messages that already * have the specified set of tags. */ query_string = _optimize_tag_query (ctx, query_string, tag_ops); if (query_string == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } flags |= TAG_FLAG_PRE_OPTIMIZED; } query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } /* tagging is not interested in any special sort order */ notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED); for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages) && ! interrupted; notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); ret = tag_op_list_apply (message, tag_ops, flags); notmuch_message_destroy (message); if (ret != NOTMUCH_STATUS_SUCCESS) break; } notmuch_query_destroy (query); return ret || interrupted; }
static void read_mesgs_query(CONTEXT *ctx, notmuch_query_t *q, int dedup) { struct nm_ctxdata *data = get_ctxdata(ctx); int limit; notmuch_messages_t *msgs; if (!data) return; limit = get_limit(data); for (msgs = notmuch_query_search_messages(q); notmuch_messages_valid(msgs) && (limit == 0 || ctx->msgcount < limit); notmuch_messages_move_to_next(msgs)) { notmuch_message_t *m = notmuch_messages_get(msgs); append_message(ctx, q, m, dedup); notmuch_message_destroy(m); } }
static int do_search_messages (const search_format_t *format, notmuch_query_t *query, output_t output, int offset, int limit) { notmuch_message_t *message; notmuch_messages_t *messages; notmuch_filenames_t *filenames; int first_message = 1; int i; if (offset < 0) { offset += notmuch_query_count_messages (query); if (offset < 0) offset = 0; } messages = notmuch_query_search_messages (query); if (messages == NULL) return 1; fputs (format->results_start, stdout); for (i = 0; notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit); notmuch_messages_move_to_next (messages), i++) { if (i < offset) continue; message = notmuch_messages_get (messages); if (output == OUTPUT_FILES) { filenames = notmuch_message_get_filenames (message); for (; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames)) { if (! first_message) fputs (format->item_sep, stdout); format->item_id (message, "", notmuch_filenames_get (filenames)); first_message = 0; } notmuch_filenames_destroy( filenames ); } else { /* output == OUTPUT_MESSAGES */ if (! first_message) fputs (format->item_sep, stdout); format->item_id (message, "id:", notmuch_message_get_message_id (message)); first_message = 0; } notmuch_message_destroy (message); } notmuch_messages_destroy (messages); if (first_message) fputs (format->results_null, stdout); else fputs (format->results_end, stdout); return 0; }
int notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[])) { int *add_tags, *remove_tags; int add_tags_count = 0; int remove_tags_count = 0; char *query_string; notmuch_config_t *config; notmuch_database_t *notmuch; notmuch_query_t *query; notmuch_messages_t *messages; notmuch_message_t *message; struct sigaction action; int i; /* Setup our handler for SIGINT */ memset (&action, 0, sizeof (struct sigaction)); action.sa_handler = handle_sigint; sigemptyset (&action.sa_mask); action.sa_flags = SA_RESTART; sigaction (SIGINT, &action, NULL); add_tags = talloc_size (ctx, argc * sizeof (int)); if (add_tags == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } remove_tags = talloc_size (ctx, argc * sizeof (int)); if (remove_tags == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } if (argv[i][0] == '+') { add_tags[add_tags_count++] = i; } else if (argv[i][0] == '-') { remove_tags[remove_tags_count++] = i; } else { break; } } if (add_tags_count == 0 && remove_tags_count == 0) { fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to add or remove.\n"); return 1; } query_string = query_string_from_args (ctx, argc - i, &argv[i]); if (*query_string == '\0') { fprintf (stderr, "Error: notmuch tag requires at least one search term.\n"); return 1; } config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; notmuch = notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE); if (notmuch == NULL) return 1; query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } /* tagging is not interested in any special sort order */ notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED); for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages) && !interrupted; notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); notmuch_message_freeze (message); for (i = 0; i < remove_tags_count; i++) notmuch_message_remove_tag (message, argv[remove_tags[i]] + 1); for (i = 0; i < add_tags_count; i++) notmuch_message_add_tag (message, argv[add_tags[i]] + 1); notmuch_message_thaw (message); notmuch_message_destroy (message); } notmuch_query_destroy (query); notmuch_database_close (notmuch); return interrupted; }
static int database_dump_file (notmuch_database_t *notmuch, gzFile output, const char *query_str, int output_format) { notmuch_query_t *query; notmuch_messages_t *messages; notmuch_message_t *message; notmuch_tags_t *tags; if (! query_str) query_str = ""; query = notmuch_query_create (notmuch, query_str); if (query == NULL) { fprintf (stderr, "Out of memory\n"); return EXIT_FAILURE; } /* Don't ask xapian to sort by Message-ID. Xapian optimizes returning the * first results quickly at the expense of total time. */ notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED); char *buffer = NULL; size_t buffer_size = 0; for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { int first = 1; const char *message_id; message = notmuch_messages_get (messages); message_id = notmuch_message_get_message_id (message); if (output_format == DUMP_FORMAT_BATCH_TAG && strchr (message_id, '\n')) { /* This will produce a line break in the output, which * would be difficult to handle in tools. However, it's * also impossible to produce an email containing a line * break in a message ID because of unfolding, so we can * safely disallow it. */ fprintf (stderr, "Warning: skipping message id containing line break: \"%s\"\n", message_id); notmuch_message_destroy (message); continue; } if (output_format == DUMP_FORMAT_SUP) { gzprintf (output, "%s (", message_id); } for (tags = notmuch_message_get_tags (message); notmuch_tags_valid (tags); notmuch_tags_move_to_next (tags)) { const char *tag_str = notmuch_tags_get (tags); if (! first) gzputs (output, " "); first = 0; if (output_format == DUMP_FORMAT_SUP) { gzputs (output, tag_str); } else { if (hex_encode (notmuch, tag_str, &buffer, &buffer_size) != HEX_SUCCESS) { fprintf (stderr, "Error: failed to hex-encode tag %s\n", tag_str); return EXIT_FAILURE; } gzprintf (output, "+%s", buffer); } } if (output_format == DUMP_FORMAT_SUP) { gzputs (output, ")\n"); } else { if (make_boolean_term (notmuch, "id", message_id, &buffer, &buffer_size)) { fprintf (stderr, "Error quoting message id %s: %s\n", message_id, strerror (errno)); return EXIT_FAILURE; } gzprintf (output, " -- %s\n", buffer); } notmuch_message_destroy (message); } notmuch_query_destroy (query); return EXIT_SUCCESS; }
static notmuch_status_t show_messages (void *ctx, const notmuch_show_format_t *format, notmuch_messages_t *messages, int indent, notmuch_show_params_t *params) { notmuch_message_t *message; notmuch_bool_t match; notmuch_bool_t excluded; int first_set = 1; int next_indent; notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS; if (format->message_set_start) fputs (format->message_set_start, stdout); for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { if (!first_set && format->message_set_sep) fputs (format->message_set_sep, stdout); first_set = 0; if (format->message_set_start) fputs (format->message_set_start, stdout); message = notmuch_messages_get (messages); match = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH); excluded = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED); next_indent = indent; if ((match && (!excluded || !params->omit_excluded)) || params->entire_thread) { status = show_message (ctx, format, message, indent, params); if (status && !res) res = status; next_indent = indent + 1; if (!status && format->message_set_sep) fputs (format->message_set_sep, stdout); } status = show_messages (ctx, format, notmuch_message_get_replies (message), next_indent, params); if (status && !res) res = status; notmuch_message_destroy (message); if (format->message_set_end) fputs (format->message_set_end, stdout); } if (format->message_set_end) fputs (format->message_set_end, stdout); return res; }
static int notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; const char *subject, *from_addr = NULL; const char *in_reply_to, *orig_references, *references; const notmuch_show_format_t *format = &format_reply; for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); /* The 1 means we want headers in a "pretty" order. */ reply = g_mime_message_new (1); if (reply == NULL) { fprintf (stderr, "Out of memory\n"); return 1; } subject = notmuch_message_get_header (message, "subject"); if (subject) { if (strncasecmp (subject, "Re:", 3)) subject = talloc_asprintf (ctx, "Re: %s", subject); g_mime_message_set_subject (reply, subject); } from_addr = add_recipients_from_message (reply, config, message); if (from_addr == NULL) from_addr = guess_from_received_header (config, message); if (from_addr == NULL) from_addr = notmuch_config_get_user_primary_email (config); from_addr = talloc_asprintf (ctx, "%s <%s>", notmuch_config_get_user_name (config), from_addr); g_mime_object_set_header (GMIME_OBJECT (reply), "From", from_addr); in_reply_to = talloc_asprintf (ctx, "<%s>", notmuch_message_get_message_id (message)); g_mime_object_set_header (GMIME_OBJECT (reply), "In-Reply-To", in_reply_to); orig_references = notmuch_message_get_header (message, "references"); references = talloc_asprintf (ctx, "%s%s%s", orig_references ? orig_references : "", orig_references ? " " : "", in_reply_to); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references); show_reply_headers (reply); g_object_unref (G_OBJECT (reply)); reply = NULL; printf ("On %s, %s wrote:\n", notmuch_message_get_header (message, "date"), notmuch_message_get_header (message, "from")); show_message_body (notmuch_message_get_filename (message), format, params); notmuch_message_destroy (message); } return 0; }
int main (int argc, char** argv) { GFile *db_dir, *db_file; notmuch_status_t status; notmuch_database_t *db = NULL; notmuch_query_t *query = NULL; notmuch_messages_t *messages = NULL; notmuch_message_t *message = NULL; GMainLoop *loop = NULL; const char *query_string = "date:2014-02-01.."; if (argc != 2) { g_warning ("Usage: %s EVOLUTION_MAILDIR", argv[0]); return 1; } db_dir = g_file_new_for_path (argv[1]); db_file = g_file_get_child (db_dir, ".notmuch"); if (!g_file_query_exists (db_dir, NULL)) { g_object_unref (db_dir); g_object_unref (db_file); g_error ("directory %s does not exists"); return 2; } if (!g_file_query_exists (db_file, NULL)) status = notmuch_database_create (argv[1], &db); else status = notmuch_database_open (argv[1], NOTMUCH_DATABASE_MODE_READ_WRITE, &db); if (status) { g_error ("Could not open database: %d", status); g_object_unref (db_dir); g_object_unref (db_file); notmuch_database_destroy (db); return 3; } scan_directory (db, db_dir); //loop = g_main_loop_new (NULL, FALSE); //g_main_loop_run (loop); query = notmuch_query_create (db, query_string); if (!query) { g_error ("Could not create query from string = \"%s\"", query_string); notmuch_database_destroy (db); g_object_unref (db_file); g_object_unref (db_dir); return 4; } g_message ("Query results -\n\n"); for (messages = notmuch_query_search_messages (query); notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); g_message ("Message file: %s", notmuch_message_get_filename (message)); g_message ("Message ID: %s", notmuch_message_get_message_id (message)); g_message ("Message Sender: %s", notmuch_message_get_header (message, "from")); g_message ("Message Recipients: %s", notmuch_message_get_header (message, "to")); g_message ("Message Subject: %s", notmuch_message_get_header (message, "subject")); g_message ("Message date: %s\n", notmuch_message_get_header (message, "date")); notmuch_message_destroy (message); } notmuch_query_destroy (query); notmuch_database_destroy (db); g_object_unref (db_file); g_object_unref (db_dir); return 0; }
static int do_search_messages (search_context_t *ctx) { notmuch_message_t *message; notmuch_messages_t *messages; notmuch_filenames_t *filenames; sprinter_t *format = ctx->format; int i; notmuch_status_t status; if (ctx->offset < 0) { unsigned count; notmuch_status_t status; status = notmuch_query_count_messages_st (ctx->query, &count); if (print_status_query ("notmuch search", ctx->query, status)) return 1; ctx->offset += count; if (ctx->offset < 0) ctx->offset = 0; } status = notmuch_query_search_messages_st (ctx->query, &messages); if (print_status_query ("notmuch search", ctx->query, status)) return 1; format->begin_list (format); for (i = 0; notmuch_messages_valid (messages) && (ctx->limit < 0 || i < ctx->offset + ctx->limit); notmuch_messages_move_to_next (messages), i++) { if (i < ctx->offset) continue; message = notmuch_messages_get (messages); if (ctx->output == OUTPUT_FILES) { int j; filenames = notmuch_message_get_filenames (message); for (j = 1; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames), j++) { if (ctx->dupe < 0 || ctx->dupe == j) { format->string (format, notmuch_filenames_get (filenames)); format->separator (format); } } notmuch_filenames_destroy( filenames ); } else if (ctx->output == OUTPUT_MESSAGES) { /* special case 1 for speed */ if (ctx->dupe <= 1 || ctx->dupe <= _count_filenames (message)) { format->set_prefix (format, "id"); format->string (format, notmuch_message_get_message_id (message)); format->separator (format); } } else { if (ctx->output & OUTPUT_SENDER) { const char *addrs; addrs = notmuch_message_get_header (message, "from"); process_address_header (ctx, addrs); } if (ctx->output & OUTPUT_RECIPIENTS) { const char *hdrs[] = { "to", "cc", "bcc" }; const char *addrs; size_t j; for (j = 0; j < ARRAY_SIZE (hdrs); j++) { addrs = notmuch_message_get_header (message, hdrs[j]); process_address_header (ctx, addrs); } } } notmuch_message_destroy (message); } if (ctx->addresses && (ctx->output & OUTPUT_COUNT || ctx->dedup == DEDUP_ADDRESS)) g_hash_table_foreach (ctx->addresses, print_hash_value, ctx); notmuch_messages_destroy (messages); format->end (format); return 0; }