/usr/bin/write-mime-multipart is in cloud-image-utils 0.30-0ubuntu5.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/python3
# largely taken from python examples
# http://docs.python.org/library/email-examples.html
import os
import sys
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from optparse import OptionParser
import gzip
COMMASPACE = ', '
starts_with_mappings = {
'#include': 'text/x-include-url',
'#include-once': 'text/x-include-once-url',
'#!': 'text/x-shellscript',
'#cloud-config': 'text/cloud-config',
'#cloud-config-archive': 'text/cloud-config-archive',
'#upstart-job': 'text/upstart-job',
'#part-handler': 'text/part-handler',
'#cloud-boothook': 'text/cloud-boothook'
}
def try_decode(data):
try:
return (True, data.decode())
except UnicodeDecodeError:
return (False, data)
def get_type(fname, deftype):
rtype = deftype
with open(fname, "rb") as f:
(can_be_decoded, line) = try_decode(f.readline())
if can_be_decoded:
# slist is sorted longest first
slist = sorted(list(starts_with_mappings.keys()),
key=lambda e: 0 - len(e))
for sstr in slist:
if line.startswith(sstr):
rtype = starts_with_mappings[sstr]
break
else:
rtype = 'application/octet-stream'
return(rtype)
def main():
outer = MIMEMultipart()
parser = OptionParser()
parser.add_option("-o", "--output", dest="output",
help="write output to FILE [default %default]",
metavar="FILE", default="-")
parser.add_option("-z", "--gzip", dest="compress", action="store_true",
help="compress output", default=False)
parser.add_option("-d", "--default", dest="deftype",
help="default mime type [default %default]",
default="text/plain")
parser.add_option("--delim", dest="delim",
help="delimiter [default %default]", default=":")
(options, args) = parser.parse_args()
if (len(args)) < 1:
parser.error("Must give file list see '--help'")
for arg in args:
t = arg.split(options.delim, 1)
path = t[0]
if len(t) > 1:
mtype = t[1]
else:
mtype = get_type(path, options.deftype)
maintype, subtype = mtype.split('/', 1)
if maintype == 'text':
fp = open(path)
# Note: we should handle calculating the charset
msg = MIMEText(fp.read(), _subtype=subtype)
fp.close()
else:
fp = open(path, 'rb')
msg = MIMEBase(maintype, subtype)
msg.set_payload(fp.read())
fp.close()
# Encode the payload using Base64
encoders.encode_base64(msg)
# Set the filename parameter
msg.add_header('Content-Disposition', 'attachment',
filename=os.path.basename(path))
outer.attach(msg)
if options.output is "-":
if hasattr(sys.stdout, "buffer"):
# We want to write bytes not strings
ofile = sys.stdout.buffer
else:
ofile = sys.stdout
else:
ofile = open(options.output, "wb")
if options.compress:
gfile = gzip.GzipFile(fileobj=ofile, filename=options.output)
gfile.write(outer.as_string().encode())
gfile.close()
else:
ofile.write(outer.as_string().encode())
ofile.close()
if __name__ == '__main__':
main()
# vi: ts=4 expandtab
|