summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-04-19 11:31:41 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2017-04-19 13:06:46 +0300
commit7e05a160e2e135006ce612881080d99ed34d4a77 (patch)
treeb905fdb5cea2abf4fd5a125ac300e8b958e95803
parentff1a8a6e673923ab9407815155834971f1f2235f (diff)
downloadmailutils-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--NEWS16
-rw-r--r--doc/texinfo/programs.texi81
-rw-r--r--mail/mail.c10
-rw-r--r--mail/mail.h1
-rw-r--r--mail/mailvar.c10
-rw-r--r--mail/send.c137
6 files changed, 152 insertions, 103 deletions
diff --git a/NEWS b/NEWS
index f6fef0c7e..2c738989c 100644
--- a/NEWS
+++ b/NEWS
@@ -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;

Return to:

Send suggestions and report system problems to the System administrator.