Commit 96dd35f0 96dd35f02fe175507d5ff91ccdcc2c59ff5a24fd by Sergey Poznyakoff

mail: new option --skip-empty-attachments

* libmailutils/cli/cli.c (mu_cli): Use "no-" prefix to indicate negation
* mail/mail.c (skip_empty_attachments): New global.
(mail_options): New option --skip-empty-attachments
* mail/mail.h (skip_empty_attachments): New extern.
* mail/send.c (atchinfo) <skip_empty>: New field.
(send_attach_file): Initialize skip_empty
(saveatt): Optionally skip empty attachments

* NEWS: Mention the new option.
* doc/texinfo/programs.texi: Document the new option.
1 parent 888e2a9a
1 GNU mailutils NEWS -- history of user-visible changes. 2017-01-13 1 GNU mailutils NEWS -- history of user-visible changes. 2017-01-16
2 Copyright (C) 2002-2017 Free Software Foundation, Inc. 2 Copyright (C) 2002-2017 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
...@@ -40,6 +40,9 @@ obvious reasons, the interactive mode is suppressed in this case. ...@@ -40,6 +40,9 @@ obvious reasons, the interactive mode is suppressed in this case.
40 The `--attach-fd' option is useful when calling `mail' from another 40 The `--attach-fd' option is useful when calling `mail' from another
41 program. 41 program.
42 42
43 The new option `--skip-empty-attachments' instructs `mail' to omit
44 attachments that have zero-size body.
45
43 Example: 46 Example:
44 47
45 Suppose that the 'mail' binary is opened at file descriptor 5 and 48 Suppose that the 'mail' binary is opened at file descriptor 5 and
......
...@@ -3044,6 +3044,13 @@ Cause interrupts to terminate program. ...@@ -3044,6 +3044,13 @@ Cause interrupts to terminate program.
3044 Sets the return email address for outgoing mail. 3044 Sets the return email address for outgoing mail.
3045 @xref{return-address}. 3045 @xref{return-address}.
3046 3046
3047 @item --skip-empty-attachments
3048 @itemx --no-skip-empty-attachments
3049 Don't create attachments that would have zero-size body. This
3050 option affects all attachments created by @option{--attach} and
3051 @option{--attach-fd} options appearing after it in the command line.
3052 To cancel its effect, use the @option{--no-skip-empty-attachments} option.
3053
3047 @item -s @var{subj} 3054 @item -s @var{subj}
3048 @itemx --subject=@var{subj} 3055 @itemx --subject=@var{subj}
3049 Send a message with a Subject of @var{subj}. Valid only in sending 3056 Send a message with a Subject of @var{subj}. Valid only in sending
...@@ -3531,6 +3538,12 @@ Attachments created with this option have neither filename nor ...@@ -3531,6 +3538,12 @@ Attachments created with this option have neither filename nor
3531 description set, so normally the use of @option{--content-name} and/or 3538 description set, so normally the use of @option{--content-name} and/or
3532 @option{--content-filename} is advised. 3539 @option{--content-filename} is advised.
3533 3540
3541 The option @option{--skip-empty-attachments} instructs @command{mail}
3542 to skip creating attachments that would have zero-size body. This
3543 option affects all attachments created by @option{--attach} and
3544 @option{--attach-fd} options appearing after it in the command line.
3545 To cancel its effect, use the @option{--no-skip-empty-attachments} option.
3546
3534 The following Perl program serves as an example of using 3547 The following Perl program serves as an example of using
3535 @command{mail} from a script to construct a MIME message on the fly. 3548 @command{mail} from a script to construct a MIME message on the fly.
3536 It scans all mounted file systems for executable files that have 3549 It scans all mounted file systems for executable files that have
......
...@@ -710,6 +710,9 @@ mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa, ...@@ -710,6 +710,9 @@ mu_cli (int argc, char **argv, struct mu_cli_setup *setup, char **capa,
710 pohint.po_version_hook = mu_version_hook; 710 pohint.po_version_hook = mu_version_hook;
711 pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK; 711 pohint.po_flags |= MU_PARSEOPT_VERSION_HOOK;
712 712
713 pohint.po_negation = "no-";
714 pohint.po_flags |= MU_PARSEOPT_NEGATION;
715
713 cfhint.site_file = mu_site_config_file (); 716 cfhint.site_file = mu_site_config_file ();
714 cfhint.flags = MU_CFHINT_SITE_FILE | MU_CFHINT_PER_USER_FILE; 717 cfhint.flags = MU_CFHINT_SITE_FILE | MU_CFHINT_PER_USER_FILE;
715 718
......
...@@ -36,10 +36,11 @@ int hint; ...@@ -36,10 +36,11 @@ int hint;
36 char *file; 36 char *file;
37 char *user; 37 char *user;
38 38
39 int skip_empty_attachments;
39 char *default_encoding; 40 char *default_encoding;
40 char *default_content_type; 41 char *default_content_type;
41 char *content_name; 42 static char *content_name;
42 char *content_filename; 43 static char *content_filename;
43 44
44 static void 45 static void
45 cli_f_option (struct mu_parseopt *po, struct mu_option *opt, char const *arg) 46 cli_f_option (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
...@@ -108,14 +109,12 @@ cli_command_option (struct mu_parseopt *po, struct mu_option *opt, ...@@ -108,14 +109,12 @@ cli_command_option (struct mu_parseopt *po, struct mu_option *opt,
108 break; 109 break;
109 110
110 case 0: 111 case 0:
111 mu_parseopt_error (po, 112 mu_parseopt_error (po, _("--%s: option should have been recognized"),
112 _("--%s: option should have been recognized"),
113 opt->opt_long); 113 opt->opt_long);
114 exit (po->po_exit_error); 114 exit (po->po_exit_error);
115 115
116 default: 116 default:
117 mu_parseopt_error (po, 117 mu_parseopt_error (po, _("-%c: option should have been recognized"),
118 _("-%c: option should have been recognized"),
119 opt->opt_short); 118 opt->opt_short);
120 exit (po->po_exit_error); 119 exit (po->po_exit_error);
121 } 120 }
...@@ -240,6 +239,10 @@ static struct mu_option mail_options[] = { ...@@ -240,6 +239,10 @@ static struct mu_option mail_options[] = {
240 { "append", 'a', N_("HEADER: VALUE"), MU_OPTION_DEFAULT, 239 { "append", 'a', N_("HEADER: VALUE"), MU_OPTION_DEFAULT,
241 N_("append given header to the message being sent"), 240 N_("append given header to the message being sent"),
242 mu_c_string, NULL, cli_append }, 241 mu_c_string, NULL, cli_append },
242
243 { "skip-empty-attachments", 0, NULL, MU_OPTION_DEFAULT,
244 N_("skip attachments with empty body"),
245 mu_c_bool, &skip_empty_attachments },
243 246
244 { "exec" , 'E', N_("COMMAND"), MU_OPTION_DEFAULT, 247 { "exec" , 'E', N_("COMMAND"), MU_OPTION_DEFAULT,
245 N_("execute COMMAND"), 248 N_("execute COMMAND"),
......
...@@ -173,7 +173,8 @@ extern int interactive; ...@@ -173,7 +173,8 @@ extern int interactive;
173 extern const char *program_version; 173 extern const char *program_version;
174 extern char *default_encoding; 174 extern char *default_encoding;
175 extern char *default_content_type; 175 extern char *default_content_type;
176 176 extern int skip_empty_attachments;
177
177 /* Functions */ 178 /* Functions */
178 extern int mail_alias (int argc, char **argv); 179 extern int mail_alias (int argc, char **argv);
179 extern int mail_alt (int argc, char **argv); /* command alternates */ 180 extern int mail_alt (int argc, char **argv); /* command alternates */
......
...@@ -140,6 +140,7 @@ struct atchinfo ...@@ -140,6 +140,7 @@ struct atchinfo
140 char *name; 140 char *name;
141 char *filename; 141 char *filename;
142 mu_stream_t source; 142 mu_stream_t source;
143 int skip_empty;
143 }; 144 };
144 145
145 static mu_list_t attlist; 146 static mu_list_t attlist;
...@@ -256,6 +257,7 @@ send_attach_file (int fd, ...@@ -256,6 +257,7 @@ send_attach_file (int fd,
256 aptr->name = content_name ? mu_strdup (content_name) : NULL; 257 aptr->name = content_name ? mu_strdup (content_name) : NULL;
257 aptr->filename = content_filename ? mu_strdup (content_filename) : NULL; 258 aptr->filename = content_filename ? mu_strdup (content_filename) : NULL;
258 aptr->source = stream; 259 aptr->source = stream;
260 aptr->skip_empty = skip_empty_attachments;
259 rc = mu_list_append (attlist, aptr); 261 rc = mu_list_append (attlist, aptr);
260 if (rc) 262 if (rc)
261 { 263 {
...@@ -363,11 +365,31 @@ saveatt (void *item, void *data) ...@@ -363,11 +365,31 @@ saveatt (void *item, void *data)
363 rc = mu_attachment_copy_from_stream (part, aptr->source, aptr->encoding); 365 rc = mu_attachment_copy_from_stream (part, aptr->source, aptr->encoding);
364 if (rc) 366 if (rc)
365 { 367 {
366 mu_error (_("cannot attach %s: %s"), aptr->filename, 368 mu_error (_("cannot attach %s: %s"), aptr->id, mu_strerror (rc));
367 mu_strerror (rc));
368 return 1; 369 return 1;
369 } 370 }
370 371
372 if (aptr->skip_empty)
373 {
374 mu_body_t body;
375 size_t size;
376
377 rc = mu_message_get_body (part, &body);
378 if (rc)
379 {
380 mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_body", aptr->id, rc);
381 return 1;
382 }
383 rc = mu_body_size (body, &size);
384 if (rc)
385 {
386 mu_diag_funcall (MU_DIAG_ERROR, "mu_body_size", aptr->id, rc);
387 return 1;
388 }
389 if (size == 0)
390 return 0;
391 }
392
371 mu_mime_get_num_parts (mime, &nparts); 393 mu_mime_get_num_parts (mime, &nparts);
372 mu_message_get_header (part, &hdr); 394 mu_message_get_header (part, &hdr);
373 mu_rfc2822_msg_id (nparts, &p); 395 mu_rfc2822_msg_id (nparts, &p);
......