1 Return-Path: <jani@nikula.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 0F5344150EF
\r
6 for <notmuch@notmuchmail.org>; Sun, 8 Jan 2012 13:49:00 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
8 X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"
\r
12 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5
\r
13 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
14 Received: from olra.theworths.org ([127.0.0.1])
\r
15 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
16 with ESMTP id HXpb9YYF4SQN for <notmuch@notmuchmail.org>;
\r
17 Sun, 8 Jan 2012 13:48:57 -0800 (PST)
\r
18 Received: from mail-ee0-f53.google.com (mail-ee0-f53.google.com
\r
19 [74.125.83.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client
\r
20 certificate requested) by olra.theworths.org (Postfix) with ESMTPS id
\r
21 94DB34150EC for <notmuch@notmuchmail.org>; Sun, 8 Jan 2012 13:48:55 -0800
\r
23 Received: by mail-ee0-f53.google.com with SMTP id d41so2496075eek.26
\r
24 for <notmuch@notmuchmail.org>; Sun, 08 Jan 2012 13:48:55 -0800 (PST)
\r
25 Received: by 10.14.14.167 with SMTP id d39mr1029406eed.3.1326059335180;
\r
26 Sun, 08 Jan 2012 13:48:55 -0800 (PST)
\r
27 Received: from localhost (dsl-hkibrasgw4-fe5cdc00-23.dhcp.inet.fi.
\r
29 by mx.google.com with ESMTPS id e12sm131493743eea.5.2012.01.08.13.48.53
\r
30 (version=SSLv3 cipher=OTHER); Sun, 08 Jan 2012 13:48:54 -0800 (PST)
\r
31 From: Jani Nikula <jani@nikula.org>
\r
32 To: notmuch@notmuchmail.org
\r
33 Subject: [PATCH v2 3/6] cli: add support for replying just to the sender in
\r
35 Date: Sun, 8 Jan 2012 23:48:32 +0200
\r
37 <6e37e058190d7c06519de3e67569fbee0be45461.1326058946.git.jani@nikula.org>
\r
38 X-Mailer: git-send-email 1.7.5.4
\r
39 In-Reply-To: <cover.1326058946.git.jani@nikula.org>
\r
40 References: <cover.1326058946.git.jani@nikula.org>
\r
41 In-Reply-To: <cover.1326058946.git.jani@nikula.org>
\r
42 References: <cover.1325794371.git.jani@nikula.org>
\r
43 <cover.1326058946.git.jani@nikula.org>
\r
44 X-BeenThere: notmuch@notmuchmail.org
\r
45 X-Mailman-Version: 2.1.13
\r
47 List-Id: "Use and development of the notmuch mail system."
\r
48 <notmuch.notmuchmail.org>
\r
49 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
50 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
51 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
52 List-Post: <mailto:notmuch@notmuchmail.org>
\r
53 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
54 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
55 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
56 X-List-Received-Date: Sun, 08 Jan 2012 21:49:00 -0000
\r
58 Add new option --reply-to=(all|sender) to "notmuch reply" to select whether
\r
59 to reply to all (sender and all recipients), or just sender. Reply to all
\r
60 remains the default.
\r
62 Credits to Mark Walters <markwalters1009@gmail.com> for his similar earlier
\r
63 work where I picked up the basic idea of handling reply-to-sender in
\r
64 add_recipients_from_message(). All bugs are mine, though.
\r
66 Signed-off-by: Jani Nikula <jani@nikula.org>
\r
70 Settled on --reply-to=(all|sender) per Carl's earlier suggestion
\r
71 (id:87pqn5cg4g.fsf@yoom.home.cworth.org) and David's approval on IRC.
\r
73 man/man1/notmuch-reply.1 | 28 +++++++++++++---
\r
74 notmuch-reply.c | 78 ++++++++++++++++++++++++++++++++++++----------
\r
75 2 files changed, 84 insertions(+), 22 deletions(-)
\r
77 diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1
\r
78 index 099d808..21afa35 100644
\r
79 --- a/man/man1/notmuch-reply.1
\r
80 +++ b/man/man1/notmuch-reply.1
\r
81 @@ -14,11 +14,13 @@ Constructs a reply template for a set of messages.
\r
82 To make replying to email easier,
\r
84 takes an existing set of messages and constructs a suitable mail
\r
85 -template. The Reply-to header (if any, otherwise From:) is used for
\r
86 -the To: address. Vales from the To: and Cc: headers are copied, but
\r
87 -not including any of the current user's email addresses (as configured
\r
88 -in primary_mail or other_email in the .notmuch\-config file) in the
\r
90 +template. The Reply-to: header (if any, otherwise From:) is used for
\r
91 +the To: address. Unless
\r
92 +.BR \-\-reply-to=sender
\r
93 +is specified, values from the To: and Cc: headers are copied, but not
\r
94 +including any of the current user's email addresses (as configured in
\r
95 +primary_mail or other_email in the .notmuch\-config file) in the
\r
98 It also builds a suitable new subject, including Re: at the front (if
\r
99 not already present), and adding the message IDs of the messages being
\r
100 @@ -45,6 +47,22 @@ Includes subject and quoted message body.
\r
101 Only produces In\-Reply\-To, References, To, Cc, and Bcc headers.
\r
106 +.BR \-\-reply\-to= ( all | sender )
\r
109 +.BR all " (default)"
\r
110 +Replies to all addresses.
\r
113 +Replies only to the sender. If Reply-to: header (if any, otherwise
\r
114 +From:) is any of the current user's configured email addresses
\r
115 +(replying to user's own message), try To:, Cc:, and Bcc: headers in
\r
116 +this order, and use the addresses in the first that contains something
\r
117 +other than only the user's addresses for the To: address.
\r
121 See \fBnotmuch-search-terms\fR(7)
\r
122 for details of the supported syntax for <search-terms>.
\r
123 diff --git a/notmuch-reply.c b/notmuch-reply.c
\r
124 index 000f6da..71946b3 100644
\r
125 --- a/notmuch-reply.c
\r
126 +++ b/notmuch-reply.c
\r
127 @@ -170,7 +170,7 @@ address_is_users (const char *address, notmuch_config_t *config)
\r
129 /* For each address in 'list' that is not configured as one of the
\r
130 * user's addresses in 'config', add that address to 'message' as an
\r
131 - * address of 'type'.
\r
132 + * address of 'type', if 'add' is true.
\r
134 * The first address encountered that *is* the user's address will be
\r
135 * returned, (otherwise NULL is returned).
\r
136 @@ -179,7 +179,8 @@ static const char *
\r
137 add_recipients_for_address_list (GMimeMessage *message,
\r
138 notmuch_config_t *config,
\r
139 GMimeRecipientType type,
\r
140 - InternetAddressList *list)
\r
141 + InternetAddressList *list,
\r
142 + notmuch_bool_t add)
\r
144 InternetAddress *address;
\r
146 @@ -197,7 +198,7 @@ add_recipients_for_address_list (GMimeMessage *message,
\r
149 add_recipients_for_address_list (message, config,
\r
150 - type, group_list);
\r
151 + type, group_list, add);
\r
153 InternetAddressMailbox *mailbox;
\r
155 @@ -211,7 +212,7 @@ add_recipients_for_address_list (GMimeMessage *message,
\r
156 if (address_is_users (addr, config)) {
\r
160 + } else if (add) {
\r
161 g_mime_message_add_recipient (message, type, name, addr);
\r
164 @@ -222,7 +223,7 @@ add_recipients_for_address_list (GMimeMessage *message,
\r
166 /* For each address in 'recipients' that is not configured as one of
\r
167 * the user's addresses in 'config', add that address to 'message' as
\r
168 - * an address of 'type'.
\r
169 + * an address of 'type', if 'add' is true.
\r
171 * The first address encountered that *is* the user's address will be
\r
172 * returned, (otherwise NULL is returned).
\r
173 @@ -231,7 +232,8 @@ static const char *
\r
174 add_recipients_for_string (GMimeMessage *message,
\r
175 notmuch_config_t *config,
\r
176 GMimeRecipientType type,
\r
177 - const char *recipients)
\r
178 + const char *recipients,
\r
179 + notmuch_bool_t add)
\r
181 InternetAddressList *list;
\r
183 @@ -242,7 +244,7 @@ add_recipients_for_string (GMimeMessage *message,
\r
187 - return add_recipients_for_address_list (message, config, type, list);
\r
188 + return add_recipients_for_address_list (message, config, type, list, add);
\r
191 /* Does the address in the Reply-To header of 'message' already appear
\r
192 @@ -286,13 +288,19 @@ reply_to_header_is_redundant (notmuch_message_t *message)
\r
194 /* Augments the recipients of reply from the headers of message.
\r
196 + * If 'reply_all' is true, use sender and all recipients, otherwise use the
\r
197 + * first header that contains something other than the user's addresses
\r
198 + * (typically this would be reply-to-sender, but also handles reply to user's
\r
199 + * own message in a sensible way).
\r
201 * If any of the user's addresses were found in these headers, the first
\r
202 * of these returned, otherwise NULL is returned.
\r
204 static const char *
\r
205 add_recipients_from_message (GMimeMessage *reply,
\r
206 notmuch_config_t *config,
\r
207 - notmuch_message_t *message)
\r
208 + notmuch_message_t *message,
\r
209 + notmuch_bool_t reply_all)
\r
212 const char *header;
\r
213 @@ -305,6 +313,7 @@ add_recipients_from_message (GMimeMessage *reply,
\r
214 { "bcc", NULL, GMIME_RECIPIENT_TYPE_BCC }
\r
216 const char *from_addr = NULL;
\r
217 + notmuch_bool_t add_recipients = TRUE;
\r
220 /* Some mailing lists munge the Reply-To header despite it being A Bad
\r
221 @@ -325,6 +334,7 @@ add_recipients_from_message (GMimeMessage *reply,
\r
223 for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {
\r
224 const char *addr, *recipients;
\r
225 + GMimeRecipientType recipient_type;
\r
227 recipients = notmuch_message_get_header (message,
\r
228 reply_to_map[i].header);
\r
229 @@ -332,11 +342,37 @@ add_recipients_from_message (GMimeMessage *reply,
\r
230 recipients = notmuch_message_get_header (message,
\r
231 reply_to_map[i].fallback);
\r
233 - addr = add_recipients_for_string (reply, config,
\r
234 - reply_to_map[i].recipient_type,
\r
236 + /* Force recipient type in reply-to-sender mode just in case replying to
\r
237 + * user's own message finds recipients in Cc/Bcc fields only.
\r
240 + recipient_type = reply_to_map[i].recipient_type;
\r
242 + recipient_type = GMIME_RECIPIENT_TYPE_TO;
\r
244 + addr = add_recipients_for_string (reply, config, recipient_type,
\r
245 + recipients, add_recipients);
\r
247 if (from_addr == NULL)
\r
250 + if (!reply_all) {
\r
251 + /* Stop adding new recipients in reply-to-sender mode if we have
\r
252 + * added some recipient(s) above.
\r
254 + * This also handles the case of user replying to his own message,
\r
255 + * where reply-to/from is not a recipient. In this case there may be
\r
256 + * more than one recipient even if not replying to all.
\r
258 + InternetAddressList *list;
\r
259 + list = g_mime_message_get_recipients (reply, recipient_type);
\r
260 + if (list && internet_address_list_length (list))
\r
261 + add_recipients = FALSE;
\r
263 + /* Check if we've got a from address and all recipients we need. */
\r
264 + if (!add_recipients && from_addr)
\r
270 @@ -480,7 +516,8 @@ static int
\r
271 notmuch_reply_format_default(void *ctx,
\r
272 notmuch_config_t *config,
\r
273 notmuch_query_t *query,
\r
274 - notmuch_show_params_t *params)
\r
275 + notmuch_show_params_t *params,
\r
276 + notmuch_bool_t reply_all)
\r
278 GMimeMessage *reply;
\r
279 notmuch_messages_t *messages;
\r
280 @@ -509,7 +546,8 @@ notmuch_reply_format_default(void *ctx,
\r
281 g_mime_message_set_subject (reply, subject);
\r
284 - from_addr = add_recipients_from_message (reply, config, message);
\r
285 + from_addr = add_recipients_from_message (reply, config, message,
\r
288 if (from_addr == NULL)
\r
289 from_addr = guess_from_received_header (config, message);
\r
290 @@ -558,7 +596,8 @@ static int
\r
291 notmuch_reply_format_headers_only(void *ctx,
\r
292 notmuch_config_t *config,
\r
293 notmuch_query_t *query,
\r
294 - unused (notmuch_show_params_t *params))
\r
295 + unused (notmuch_show_params_t *params),
\r
296 + notmuch_bool_t reply_all)
\r
298 GMimeMessage *reply;
\r
299 notmuch_messages_t *messages;
\r
300 @@ -598,7 +637,7 @@ notmuch_reply_format_headers_only(void *ctx,
\r
301 g_mime_object_set_header (GMIME_OBJECT (reply),
\r
302 "References", references);
\r
304 - (void)add_recipients_from_message (reply, config, message);
\r
305 + (void)add_recipients_from_message (reply, config, message, reply_all);
\r
307 reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));
\r
308 printf ("%s", reply_headers);
\r
309 @@ -625,9 +664,10 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
\r
310 notmuch_query_t *query;
\r
311 char *query_string;
\r
312 int opt_index, ret = 0;
\r
313 - int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params);
\r
314 + int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all);
\r
315 notmuch_show_params_t params = { .part = -1 };
\r
316 int format = FORMAT_DEFAULT;
\r
317 + int reply_all = TRUE;
\r
318 notmuch_bool_t decrypt = FALSE;
\r
320 notmuch_opt_desc_t options[] = {
\r
321 @@ -635,6 +675,10 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
\r
322 (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT },
\r
323 { "headers-only", FORMAT_HEADERS_ONLY },
\r
325 + { NOTMUCH_OPT_KEYWORD, &reply_all, "reply-to", 'r',
\r
326 + (notmuch_keyword_t []){ { "all", TRUE },
\r
327 + { "sender", FALSE },
\r
329 { NOTMUCH_OPT_BOOLEAN, &decrypt, "decrypt", 'd', 0 },
\r
332 @@ -688,7 +732,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
\r
336 - if (reply_format_func (ctx, config, query, ¶ms) != 0)
\r
337 + if (reply_format_func (ctx, config, query, ¶ms, reply_all) != 0)
\r
340 notmuch_query_destroy (query);
\r