3 # Kerberos login to IMAP server and upload of provided files as a draft email.
5 # From: Rick van Rein <rick@openfortress.nl>
10 from base64 import b64encode, b64decode
14 import email.mime.base as mime
15 import email.mime.text as text
16 import email.mime.multipart as multipart
27 def wrap (self, plaintext):
28 """Once a GSSAPI Context is complete, it can wrap plaintext
29 into ciphertext. This function operates on binary strings.
31 kerberos.authGSSClientWrap (self.ctx, b64encode (plaintext))
32 cipherdata = kerberos.authGSSClientResponse (self.ctx)
33 return (b64decode (cipherdata) if cipherdata else "")
35 def unwrap (self, ciphertext):
36 """Once a GSSAPI Context is complete, it can unwrap ciphertext
37 into plaintext. This function operates on binary strings.
39 kerberos.authGSSClientUnwrap (self.ctx, b64encode (ciphertext))
40 return b64decode (kerberos.authGSSClientResponse (self.ctx))
42 def processor (self, hostname):
43 # Currying function (needed to bind 'self')
45 #DEBUG# print 'New Call with Complete:', self.complete
46 #DEBUG# print 'Received:', '"' + b64encode (rcv) + '"'
48 # Initiate the GSSAPI Client
49 #ALT# rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname, gssflags=kerberos.GSS_C_SEQUENCE_FLAG)
50 #STD# rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname)
52 rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname)
53 rc = kerberos.authGSSClientStep (self.ctx, b64encode (rcv))
54 #DEBUG# print 'ClientStep Result Code:', ['CONTINUE', 'COMPLETE'] [rc]
55 if rc == kerberos.AUTH_GSS_COMPLETE:
58 # print 'Error making a step'
60 snd = kerberos.authGSSClientResponse (self.ctx)
61 return (b64decode (snd) if snd else "")
63 # Unwrap and interpret the information token
64 rc = kerberos.authGSSClientUnwrap (self.ctx, b64encode (rcv))
66 # print 'Error unwrapping'
68 token = b64decode (kerberos.authGSSClientResponse (self.ctx))
70 #DEBUG# print 'Error unwrapping token after GSSAPI handshake'
72 flags = ord (token [0])
73 #DEBUG# print 'Flags:', '0x%02x' % flags
74 if flags & kerberos.GSS_C_INTEG_FLAG:
75 pass #DEBUG# print 'Integrity Supported'
76 if flags & kerberos.GSS_C_CONF_FLAG:
77 pass #DEBUG# print 'Confidentialtiy Supported'
78 maxlen = (ord (token [1]) << 16) | (ord (token [2]) << 8) | (ord (token [3]))
79 #DEBUG# print 'Maxlen:', maxlen
80 rettok = (chr (0) * 4) + 'ofo'
81 return self.wrap (rettok)
82 # kerberos.authGSSClientWrap (self.ctx, b64encode (rettok))
83 # snd = kerberos.authGSSClientResponse (self.ctx)
84 # return (b64decode (snd) if snd else "")
86 # The Currying surroundings return the internal function
87 # This is a strange necessity due to the IMAP assumption
88 # that it can call a closure, or a stateless function.
89 # What a lot of work to evade global variables... and it's
90 # all due to an ill-designed API, I think.
95 # Process the commandline
97 if len (sys.argv) < 2:
98 sys.stderr.write ('Usage: ' + sys.argv [0] + ' attachment...\n\tThis command will create a draft email with the given files attached.\n')
102 for arg in sys.argv [1:]:
103 ana = os.popen ('file --mime-type "' + arg + '"').read ()
104 (filenm,mimetp) = ana.split (': ', 1)
105 (major,minor) = mimetp.strip ().split ('/', 1)
106 filenm = arg.split (os.sep) [-1]
107 content = mime.MIMEBase (major, minor)
108 content.set_param ('name', filenm)
109 content.add_header ('Content-disposition', 'attachment', filename=filenm)
110 attachments.append (content)
113 remote_hostname = 'popmini.opera'
118 im = imaplib.IMAP4 (remote_hostname, 143)
119 authctx = SASLTongue ()
120 authcpu = authctx.processor (remote_hostname)
121 #DEBUG# print 'AuthCPU:', authcpu, '::', type (authcpu)
122 im.authenticate ('GSSAPI', authcpu)
125 # Select a mailbox for uploading to
128 ok,msgs = im.select (draftbox)
130 ok,msgs = im.select ()
132 sys.stderr.write ('Warning: No ' + draftbox + ' folder found, posting to INBOX\n')
135 sys.stderr.write ('Failed to select both Drafts folder or even INBOX\n')
140 # Insert the content into the attachments
142 for (av,at) in zip (sys.argv [1:], attachments):
144 at.set_payload ( open (av, 'r').read () )
146 at.set_payload (b64encode (open (av, 'r').read ()))
149 # Construct the email message to upload
153 Attached, you will find
155 intro = text.MIMEText (introtxt)
156 attachments.insert (0, intro)
158 msg = multipart.MIMEMultipart ()
159 for at in attachments:
162 ok,data = im.append (draftbox, '(\\Flagged \\Draft)', None, msg.as_string ())
164 sys.stderr.write ('Problem appending the file')