~registry/cloud-utils/trunk

« back to all changes in this revision

Viewing changes to bin/write-mime-multipart

  • Committer: Scott Moser
  • Date: 2018-12-10 21:23:53 UTC
  • Revision ID: smoser@ubuntu.com-20181210212353-cbiujmg3l0tfsza7
Development has been moved to git.

cloud-utils development has moved its revision control to git.
It is available at
  https://git.launchpad.net/cloud-utils

Clone with:
  git clone https://git.launchpad.net/cloud-utils
or with read-write:
  git clone ssh://git.launchpad.net/cloud-utils

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python3
2
 
# largely taken from python examples
3
 
# http://docs.python.org/library/email-examples.html
4
 
 
5
 
import os
6
 
import sys
7
 
 
8
 
from email import encoders
9
 
from email.mime.base import MIMEBase
10
 
from email.mime.multipart import MIMEMultipart
11
 
from email.mime.text import MIMEText
12
 
from optparse import OptionParser
13
 
import gzip
14
 
 
15
 
COMMASPACE = ', '
16
 
 
17
 
starts_with_mappings = {
18
 
    '#include': 'text/x-include-url',
19
 
    '#include-once': 'text/x-include-once-url',
20
 
    '#!': 'text/x-shellscript',
21
 
    '#cloud-config': 'text/cloud-config',
22
 
    '#cloud-config-archive': 'text/cloud-config-archive',
23
 
    '#upstart-job': 'text/upstart-job',
24
 
    '#part-handler': 'text/part-handler',
25
 
    '#cloud-boothook': 'text/cloud-boothook'
26
 
}
27
 
 
28
 
 
29
 
def try_decode(data):
30
 
    try:
31
 
        return (True, data.decode())
32
 
    except UnicodeDecodeError:
33
 
        return (False, data)
34
 
 
35
 
 
36
 
def get_type(fname, deftype):
37
 
    rtype = deftype
38
 
 
39
 
    with open(fname, "rb") as f:
40
 
        (can_be_decoded, line) = try_decode(f.readline())
41
 
 
42
 
    if can_be_decoded:
43
 
        # slist is sorted longest first
44
 
        slist = sorted(list(starts_with_mappings.keys()),
45
 
                       key=lambda e: 0 - len(e))
46
 
        for sstr in slist:
47
 
            if line.startswith(sstr):
48
 
                rtype = starts_with_mappings[sstr]
49
 
                break
50
 
    else:
51
 
        rtype = 'application/octet-stream'
52
 
 
53
 
    return(rtype)
54
 
 
55
 
 
56
 
def main():
57
 
    outer = MIMEMultipart()
58
 
    parser = OptionParser()
59
 
 
60
 
    parser.add_option("-o", "--output", dest="output",
61
 
                      help="write output to FILE [default %default]",
62
 
                      metavar="FILE", default="-")
63
 
    parser.add_option("-z", "--gzip", dest="compress", action="store_true",
64
 
                      help="compress output", default=False)
65
 
    parser.add_option("-d", "--default", dest="deftype",
66
 
                      help="default mime type [default %default]",
67
 
                      default="text/plain")
68
 
    parser.add_option("--delim", dest="delim",
69
 
                      help="delimiter [default %default]", default=":")
70
 
 
71
 
    (options, args) = parser.parse_args()
72
 
 
73
 
    if (len(args)) < 1:
74
 
        parser.error("Must give file list see '--help'")
75
 
 
76
 
    for arg in args:
77
 
        t = arg.split(options.delim, 1)
78
 
        path = t[0]
79
 
        if len(t) > 1:
80
 
            mtype = t[1]
81
 
        else:
82
 
            mtype = get_type(path, options.deftype)
83
 
 
84
 
        maintype, subtype = mtype.split('/', 1)
85
 
        if maintype == 'text':
86
 
            fp = open(path)
87
 
            # Note: we should handle calculating the charset
88
 
            msg = MIMEText(fp.read(), _subtype=subtype)
89
 
            fp.close()
90
 
        else:
91
 
            fp = open(path, 'rb')
92
 
            msg = MIMEBase(maintype, subtype)
93
 
            msg.set_payload(fp.read())
94
 
            fp.close()
95
 
            # Encode the payload using Base64
96
 
            encoders.encode_base64(msg)
97
 
 
98
 
        # Set the filename parameter
99
 
        msg.add_header('Content-Disposition', 'attachment',
100
 
                       filename=os.path.basename(path))
101
 
 
102
 
        outer.attach(msg)
103
 
 
104
 
    if options.output is "-":
105
 
        if hasattr(sys.stdout, "buffer"):
106
 
            # We want to write bytes not strings
107
 
            ofile = sys.stdout.buffer
108
 
        else:
109
 
            ofile = sys.stdout
110
 
    else:
111
 
        ofile = open(options.output, "wb")
112
 
 
113
 
    if options.compress:
114
 
        gfile = gzip.GzipFile(fileobj=ofile, filename=options.output)
115
 
        gfile.write(outer.as_string().encode())
116
 
        gfile.close()
117
 
    else:
118
 
        ofile.write(outer.as_string().encode())
119
 
 
120
 
    ofile.close()
121
 
 
122
 
if __name__ == '__main__':
123
 
    main()
124
 
 
125
 
# vi: ts=4 expandtab