Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | /* vi: set sw=4 ts=4: */
/*
* makemime: create MIME-encoded message
*
* Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
//kbuild:lib-$(CONFIG_MAKEMIME) += makemime.o mail.o
#include "libbb.h"
#include "mail.h"
#if 0
# define dbg_error_msg(...) bb_error_msg(__VA_ARGS__)
#else
# define dbg_error_msg(...) ((void)0)
#endif
/*
makemime -c type [-o file] [-e encoding] [-C charset] [-N name] \
[-a "Header: Contents"] file
-m [ type ] [-o file] [-e encoding] [-a "Header: Contents"] file
-j [-o file] file1 file2
@file
file: filename - read or write from filename
- - read or write from stdin or stdout
&n - read or write from file descriptor n
\( opts \) - read from child process, that generates [ opts ]
Options:
-c type - create a new MIME section from "file" with this
Content-Type: (default is application/octet-stream).
-C charset - MIME charset of a new text/plain section.
-N name - MIME content name of the new mime section.
-m [ type ] - create a multipart mime section from "file" of this
Content-Type: (default is multipart/mixed).
-e encoding - use the given encoding (7bit, 8bit, quoted-printable,
or base64), instead of guessing. Omit "-e" and use
-c auto to set Content-Type: to text/plain or
application/octet-stream based on picked encoding.
-j file1 file2 - join mime section file2 to multipart section file1.
-o file - write the result to file, instead of stdout (not
allowed in child processes).
-a header - prepend an additional header to the output.
@file - read all of the above options from file, one option or
value on each line.
{which version of makemime is this? What do we support?}
*/
/* man makemime:
* -c TYPE: create a (non-multipart) MIME section with Content-Type: TYPE
* makemime -c TYPE [-e ENCODING] [-o OUTFILE] [-C CHARSET] [-N NAME] [-a HEADER...] FILE
* The -C option sets the MIME charset attribute for text/plain content.
* The -N option sets the name attribute for Content-Type:
* Encoding must be one of the following: 7bit, 8bit, quoted-printable, or base64.
* -m multipart/TYPE: create a multipart MIME collection with Content-Type: multipart/TYPE
* makemime -m multipart/TYPE [-e ENCODING] [-o OUTFILE] [-a HEADER...] FILE
* Type must be either "multipart/mixed", "multipart/alternative", or some other MIME multipart content type.
* Additionally, encoding can only be "7bit" or "8bit", and will default to "8bit" if not specified.
* Finally, filename must be a MIME-formatted section, NOT a regular file.
* The -m option creates an initial multipart MIME collection, that contains only one MIME section, taken from filename.
* The collection is written to standard output, or the pipe or to outputfile.
* -j FILE1: add a section to a multipart MIME collection
* makemime -j FILE1 [-o OUTFILE] FILE2
* FILE1 must be a MIME collection that was previously created by the -m option.
* FILE2 must be a MIME section that was previously created by the -c option.
* The -j options adds the MIME section in FILE2 to the MIME collection in FILE1.
*/
/* In busybox 1.15.0.svn, makemime generates output like this
* (empty lines are shown exactly!):
{headers added with -a HDR}
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="24269534-2145583448-1655890676"
--24269534-2145583448-1655890676
Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii}
Content-Disposition: inline; filename="A"
Content-Transfer-Encoding: base64
...file A contents...
--24269534-2145583448-1655890676
Content-Type: {set by -c, e.g. text/plain}; charset={set by -C, e.g. us-ascii}
Content-Disposition: inline; filename="B"
Content-Transfer-Encoding: base64
...file B contents...
--24269534-2145583448-1655890676--
*
* For reference: here is an example email to LKML which has
* 1st unnamed part (so it serves as an email body)
* and one attached file:
...other headers...
Content-Type: multipart/mixed; boundary="=-tOfTf3byOS0vZgxEWcX+"
...other headers...
Mime-Version: 1.0
...other headers...
--=-tOfTf3byOS0vZgxEWcX+
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
...email text...
...email text...
--=-tOfTf3byOS0vZgxEWcX+
Content-Disposition: attachment; filename="xyz"
Content-Type: text/plain; name="xyz"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
...file contents...
...file contents...
--=-tOfTf3byOS0vZgxEWcX+--
...random junk added by mailing list robots and such...
*/
//usage:#define makemime_trivial_usage
//usage: "[OPTIONS] [FILE]..."
//usage:#define makemime_full_usage "\n\n"
//usage: "Create multipart MIME-encoded message from FILEs\n"
/* //usage: "Transfer encoding is base64, disposition is inline (not attachment)\n" */
//usage: "\n -o FILE Output. Default: stdout"
//usage: "\n -a HDR Add header(s). Examples:"
//usage: "\n \"From: user@host.org\", \"Date: `date -R`\""
//usage: "\n -c CT Content type. Default: application/octet-stream"
//usage: "\n -C CS Charset. Default: " CONFIG_FEATURE_MIME_CHARSET
/* //usage: "\n -e ENC Transfer encoding. Ignored. base64 is assumed" */
//usage: "\n"
//usage: "\nOther options are silently ignored"
/*
* -c [Content-Type] should create just one MIME section
* with "Content-Type:", "Content-Transfer-Encoding:", and HDRs from "-a HDR".
* NB: without "Content-Disposition:" auto-added, unlike we do now
* NB2: -c has *optional* param which nevertheless _can_ be specified after a space :(
*
* -m [multipart/mixed] should create multipart MIME section
* with "Content-Type:", "Content-Transfer-Encoding:", and HDRs from "-a HDR",
* and add FILE to it _verbatim_:
* HEADERS
*
* --=_1_1321709112_1605
* FILE_CONTENTS
* --=_1_1321709112_1605
* without any encoding of FILE_CONTENTS. (Basically, it expects that FILE
* is the result of "makemime -c").
*
* -j MULTIPART_FILE1 SINGLE_FILE2 should output MULTIPART_FILE1 + SINGLE_FILE2
*
* Our current behavior is a mutant "-m + -c + -j" one: we create multipart MIME
* and we put "-c" encoded FILEs into many multipart sections.
*/
int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int makemime_main(int argc UNUSED_PARAM, char **argv)
{
llist_t *opt_headers = NULL, *l;
const char *opt_output;
const char *content_type = "application/octet-stream";
#define boundary opt_output
enum {
OPT_c = 1 << 0, // create (non-multipart) section
OPT_e = 1 << 1, // Content-Transfer-Encoding. Ignored. Assumed base64
OPT_o = 1 << 2, // output to
OPT_C = 1 << 3, // charset
OPT_N = 1 << 4, // COMPAT
OPT_a = 1 << 5, // additional headers
//OPT_m = 1 << 6, // create mutipart section
//OPT_j = 1 << 7, // join section to multipart section
};
INIT_G();
// parse options
opt_complementary = "a::";
opts = getopt32(argv,
"c:e:o:C:N:a:", // "m:j:",
&content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers //, NULL, NULL
);
//argc -= optind;
argv += optind;
// respect -o output
if (opts & OPT_o)
freopen(opt_output, "w", stdout);
// no files given on command line? -> use stdin
if (!*argv)
*--argv = (char *)"-";
// put additional headers
for (l = opt_headers; l; l = l->link)
puts(l->data);
// make a random string -- it will delimit message parts
srand(monotonic_us());
boundary = xasprintf("%u-%u-%u",
(unsigned)rand(), (unsigned)rand(), (unsigned)rand());
// put multipart header
printf(
"Mime-Version: 1.0\n"
"Content-Type: multipart/mixed; boundary=\"%s\"\n"
, boundary
);
// put attachments
while (*argv) {
printf(
"\n--%s\n"
"Content-Type: %s; charset=%s\n"
"Content-Disposition: inline; filename=\"%s\"\n"
"Content-Transfer-Encoding: base64\n"
, boundary
, content_type
, G.opt_charset
, bb_get_last_path_component_strip(*argv)
);
encode_base64(*argv++, (const char *)stdin, "");
}
// put multipart footer
printf("\n--%s--\n" "\n", boundary);
return EXIT_SUCCESS;
#undef boundary
}
|