diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-04-19 11:31:41 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-04-19 13:06:46 +0300 |
commit | 7e05a160e2e135006ce612881080d99ed34d4a77 (patch) | |
tree | b905fdb5cea2abf4fd5a125ac300e8b958e95803 | |
parent | ff1a8a6e673923ab9407815155834971f1f2235f (diff) | |
download | mailutils-7e05a160e2e135006ce612881080d99ed34d4a77.tar.gz mailutils-7e05a160e2e135006ce612881080d99ed34d4a77.tar.bz2 |
New option --mime
* mail/mail.c (mime_option): New variable.
(main): assume --mime if either or both of --content-type and
--content-encoding are set. Set the mime variable if so.
* mail/mail.h (mailvar_is_true): New prototype.
* mail/send.c (add_attachments): Continue if the mime variable
is set.
(add_body): Rewrite, treating the text read from the stdin as
MIME part in itself.
* mailvar.c (mailvar_tab): New variable "mime"
(mailvar_is_true): New function.
* NEWS: Document --mime
* doc/texinfo/programs.texi: Rewrite the Attachments subsection.
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | doc/texinfo/programs.texi | 81 | ||||
-rw-r--r-- | mail/mail.c | 10 | ||||
-rw-r--r-- | mail/mail.h | 1 | ||||
-rw-r--r-- | mail/mailvar.c | 10 | ||||
-rw-r--r-- | mail/send.c | 137 |
6 files changed, 152 insertions, 103 deletions
@@ -1,4 +1,4 @@ -GNU mailutils NEWS -- history of user-visible changes. 2017-04-13 +GNU mailutils NEWS -- history of user-visible changes. 2017-04-19 Copyright (C) 2002-2017 Free Software Foundation, Inc. See the end of file for copying conditions. @@ -90,6 +90,20 @@ defined. Instead, the following constants are defined in config.h: * mail: sending multipart messages +** New option --mime + +This option instructs mail to compose output messages in MIME format. +The options --content-type and --encoding turn this option on. As a +side effect, both --content-type and --encoding now affect the message +body read from the standard input as well. + +** New variable 'mime' + +The 'mime' variable, if set instructs mail to compose output messages +in MIME format. In fact, the '--mime' option is equivalent to +'-E set mime', except that it takes effect after all options are +processed. + ** New option --alternative When used with --attach or --attach-fd options, this option sets the diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi index 1586df2ab..52d11d4c9 100644 --- a/doc/texinfo/programs.texi +++ b/doc/texinfo/programs.texi @@ -2987,7 +2987,7 @@ Configuration Files}, for a detailed description of their format. * Invoking Mail:: Command Line Options. * Specifying Messages:: How to Specify Message Sets. * Composing Mail:: Composing Mail. -* Attachments:: Attaching Files. +* MIME:: How to Attach Files. * Reading Mail:: Reading Mail. * Scripting:: Scripting. * Mail Variables:: How to Alter the Behavior of @command{mail}. @@ -3084,6 +3084,14 @@ Print header summary to stdout and exit. @itemx --ignore Ignore interrupts when composing the message. +@item -M +@itemx --mime +@itemx --no-mime +The @option{--mime} option instructs @command{mail} to compose MIME +messages. It is equivalent for @option{-E 'set mime'}, except that it +is processed after all other options. The @option{--no-mime} disables +the MIME compose mode, and is a shortcut for @option{-E 'set nomime'}, + @item -N @itemx --nosum Do not display initial header summary. @@ -3522,8 +3530,53 @@ the old contents of your message. @c ********************************************************************* -@node Attachments -@subsection Sending Attachments +@node MIME +@subsection Composing Multipart Messages + +Multipart messages (or MIME, for short) can be used to send text in +character set other than ASCII, attach non-text files, send multiple +parts in alternative formats, etc. + +Technically speaking, the boolean variable @code{mime} +controls this feature. If it is set (@pxref{Setting and Unsetting +the Variables}), @command{MIME} will create MIME messages by default. +The variable can be set in the global or user configuration file +(@pxref{Mail Configuration Files}), using the following command: + +@example +set mime +@end example + +It can also be set from the command line, using the @option{--mime} +option. + +GNU @command{mail} automatically turns on the MIME mode, when it is +requested to send a non-plaintext message, or a message in character +set other than ASCII, when the encoding is specified, or when +attachments are given. + +To send a message in another character set, specify it with the +@option{--content-type} option: + +@example +mail --content-type 'text/plain; charset=utf-8' +@end example + +The @option{--encoding} specifies the encoding to use: + +@example +mail --content-type 'text/plain; charset=utf-8' --encoding=base64 +@end example + +Its argument is any encoding supported by GNU mailutils. The two most +often used encodings are @samp{base64} and @samp{quoted-printable}. + +To specify the charset from @command{mail} interactive section, enable +the ``edit headers'' mode (@code{set editheaders}) and add the +needed @code{Content-Type} header manually. + +GNU @command{mail} also gives you a possibility to attach files to the +message being sent. The simplest way to attach a file from command line is by using the @option{--attach} (@option{-A}) option. Its argument specifies the @@ -3545,9 +3598,9 @@ $ mail --content-type=text/html --attach=in.html @end example The @option{--content-type} option affects all @option{--attach} -options that follow it. To change the content type, simply add -another @option{--content-type} option. For example, to send both -the HTML file and the archive: +options that follow it, and the message body (if any). To change the +content type, simply add another @option{--content-type} option. For +example, to send both the HTML file and the archive: @example $ mail --content-type=text/html --attach=in.html \ @@ -3556,8 +3609,9 @@ $ mail --content-type=text/html --attach=in.html \ Similarly, the encoding to use is set up by the @option{--encoding} option. As well as @option{--content-type}, this option affects all -attachments supplied after it in the command line, until changed by -the eventual next appearance of the same option. Extending the above +attachments supplied after it in the command line as well as the +message body read from the standard input, until changed by +the eventual next instance of the same option. Extending the above example: @example @@ -5066,6 +5120,17 @@ set metamail set metamail="metamail -m mail -p" @end example +@kwindex mime +@item mime +@*Type: String +@*Default: Unset (false) +@vrindex mime, mail variable + +If set, this variable instructs @command{mail} to compose MIME +messages. + +It can be set from the command line using @option{--mime} option. + @kwindex mimenoask @item mimenoask @*Type: String diff --git a/mail/mail.c b/mail/mail.c index 4a50460a6..d6ed8dd4c 100644 --- a/mail/mail.c +++ b/mail/mail.c @@ -36,6 +36,7 @@ int hint; char *file; char *user; +int mime_option; int skip_empty_attachments; char *default_encoding; char *default_content_type; @@ -274,6 +275,10 @@ static struct mu_option mail_options[] = { N_("attach from file descriptor FD"), mu_c_string, NULL, cli_attach_fd }, + { "mime", 'M', NULL, MU_OPTION_DEFAULT, + N_("compose MIME messages"), + mu_c_bool, &mime_option }, + MU_OPTION_END }, *options[] = { mail_options, NULL }; @@ -483,6 +488,11 @@ main (int argc, char **argv) /* argument parsing */ mu_cli (argc, argv, &cli, mail_capa, NULL, &argc, &argv); + if (default_content_type || default_encoding) + mime_option = 1; + if (mime_option) + util_cache_command (&command_list, "set mime"); + if (read_recipients) { argv += argc; diff --git a/mail/mail.h b/mail/mail.h index ab04896a1..e2a4dd7db 100644 --- a/mail/mail.h +++ b/mail/mail.h @@ -380,6 +380,7 @@ extern int util_get_crt (void); extern struct mailvar_variable *mailvar_find_variable (const char *var, int create); extern int mailvar_get (void *ptr, const char *variable, enum mailvar_type type, int warn); +int mailvar_is_true (char const *name); extern void mailvar_print (int set); extern void mailvar_variable_format (mu_stream_t, diff --git a/mail/mailvar.c b/mail/mailvar.c index 79829209f..9593f8a49 100644 --- a/mail/mailvar.c +++ b/mail/mailvar.c @@ -276,6 +276,10 @@ struct mailvar_symbol mailvar_tab[] = { { "xmailer", }, MAILVAR_TYPEMASK (mailvar_type_boolean), N_("add the `X-Mailer' header to the outgoing messages") }, + + { { "mime" }, + MAILVAR_TYPEMASK (mailvar_type_boolean), + N_("always compose MIME messages") }, /* These will be implemented later */ { { "onehop", }, MAILVAR_HIDDEN, NULL }, @@ -450,6 +454,12 @@ mailvar_get (void *ptr, const char *variable, enum mailvar_type type, int warn) return 0; } +int +mailvar_is_true (char const *name) +{ + return mailvar_get (NULL, name, mailvar_type_boolean, 0) == 0; +} + /* Initialize mailvar_list entry: clear set indicator and free any memory associated with the data */ void diff --git a/mail/send.c b/mail/send.c index b8b74c2ea..72ebd3608 100644 --- a/mail/send.c +++ b/mail/send.c @@ -499,98 +499,51 @@ saveatt (void *item, void *data) } static int -add_body (mu_message_t inmsg, mu_iterator_t itr, mu_mime_t mime) +add_body (mu_message_t inmsg, compose_env_t *env) { - mu_body_t body; - mu_message_t part; - mu_stream_t str, output; - mu_header_t outhdr; - char *p; int rc; - + mu_body_t body; + mu_stream_t str; + struct atchinfo *aptr; + mu_message_get_body (inmsg, &body); - if (skip_empty_attachments || multipart_alternative) - { - size_t size; - rc = mu_body_size (body, &size); - if (rc) - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_body_size", NULL, rc); - return -1; - } - if (size == 0) - return 0; - } - - /* Add original message as the first part */ - - /* 1. Create the part and obtain a reference to its stream */ - if ((rc = mu_message_create (&part, NULL)) == 0) - { - mu_body_t pbody; - - mu_message_get_body (part, &pbody); - mu_body_get_streamref (pbody, &output); - } - else - { - mu_diag_funcall (MU_DIAG_ERROR, "mu_message_create", NULL, rc); - return -1; - } - - /* 2. Get original body stream and copy it out to the part's body */ mu_body_get_streamref (body, &str); - mu_stream_copy (output, str, 0, NULL); - mu_stream_close (output); - mu_stream_destroy (&output); - - /* 3. Copy "Content-*" headers from the original message */ - mu_message_get_header (part, &outhdr); - for (mu_iterator_first (itr); !mu_iterator_is_done (itr); - mu_iterator_next (itr)) - { - const char *name, *value; - - if (mu_iterator_current_kv (itr, (const void **)&name, - (void**)&value) == 0) - { - if (mu_c_strncasecmp (name, "Content-", 8) == 0) - mu_header_set_value (outhdr, name, value, 0); - } - } + aptr = mu_alloc (sizeof (*aptr)); + aptr->id = NULL; + aptr->encoding = default_encoding ? mu_strdup (default_encoding) : NULL; + aptr->content_type = mu_strdup (default_content_type ? + default_content_type : "text/plain"); + aptr->name = NULL; + aptr->filename = NULL; + aptr->source = str; + aptr->skip_empty = skip_empty_attachments || multipart_alternative; + if (!env->attlist) + env->attlist = attlist_new (); + rc = mu_list_prepend (env->attlist, aptr); + if (rc) + mu_diag_funcall (MU_DIAG_ERROR, "mu_list_prepend", NULL, rc); + return rc; +} - /* 4. Add the content type and content ID headers. */ - mu_header_set_value (outhdr, MU_HEADER_CONTENT_TYPE, - default_content_type ? default_content_type : "text/plain", - 0); - mu_rfc2822_msg_id (0, &p); - mu_header_set_value (outhdr, MU_HEADER_CONTENT_ID, p, 1); - free (p); - - /* 5. Add part to the mime object */ - mu_mime_add_part (mime, part); - mu_message_unref (part); - - return 0; -} - static int add_attachments (compose_env_t *env, mu_message_t *pmsg) { mu_message_t inmsg, outmsg; mu_header_t inhdr, outhdr; mu_iterator_t itr; - mu_mime_t mime; int rc; + inmsg = *pmsg; + + if (mailvar_is_true ("mime") && add_body (inmsg, env)) + return 1; + if (mu_list_is_empty (env->attlist)) return 0; - inmsg = *pmsg; - /* Create a mime object */ - rc = mu_mime_create (&mime, NULL, + rc = mu_mime_create (&env->mime, NULL, env->alt ? MU_MIME_MULTIPART_ALT : MU_MIME_MULTIPART_MIXED); if (rc) @@ -600,39 +553,35 @@ add_attachments (compose_env_t *env, mu_message_t *pmsg) } mu_message_get_header (inmsg, &inhdr); - mu_header_get_iterator (inhdr, &itr); - - if (add_body (inmsg, itr, mime)) - { - mu_mime_destroy (&mime); - mu_iterator_destroy (&itr); - return 1; - } - - env->mime = mime; /* Add the respective attachments */ rc = mu_list_foreach (env->attlist, saveatt, env); if (rc) - { - mu_mime_destroy (&mime); - mu_iterator_destroy (&itr); - return 1; - } + return 1; /* Get the resulting message */ - rc = mu_mime_get_message (mime, &outmsg); + rc = mu_mime_get_message (env->mime, &outmsg); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_mime_get_message", NULL, rc); - mu_mime_destroy (&mime); - mu_iterator_destroy (&itr); return 1; } /* Copy rest of headers from the original message */ - mu_message_get_header (outmsg, &outhdr); + rc = mu_message_get_header (outmsg, &outhdr); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", NULL, rc); + return 1; + } + + rc = mu_header_get_iterator (inhdr, &itr); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_header_get_iterator", NULL, rc); + return 1; + } for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { @@ -1356,7 +1305,7 @@ mail_send0 (compose_env_t *env, int save_to) mu_message_set_header (msg, env->header, NULL); env->header = NULL; - + status = add_attachments (env, &msg); if (status) break; |