This repository has been archived by the owner on May 29, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gmail.py
executable file
·169 lines (146 loc) · 5.11 KB
/
gmail.py
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
#! /usr/bin/python
"""This python app effectively creates a terminal version of gmail. It will be
able to compose new messages, list various messages, reply to them, and move
them within the gmail system."""
import argparse
import os
import tempfile
from message import Message
from subprocess import call
import authentication
import imap
def main():
"""The Gmail terminal app main function"""
parser = setup_parser()
args = parser.parse_args()
if args.mode is None or args.mode == 'list':
list_emails()
elif args.mode == 'compose':
compose(parse_compose(args))
elif args.mode == 'reply':
pass
elif args.mode == 'forward':
pass
elif args.mode == 'delete':
pass
else:
raise NotImplementedError('Operation not currently supported:' + args.mode)
def setup_parser():
"""Set up the argument parser to correctly match terminal arguments"""
parser = argparse.ArgumentParser(description='CLI Gmail App')
subparsers = parser.add_subparsers(
title='subcommands',
description='Valid Gmail Commands',
help='additional help',
dest='mode')
subparsers = setup_compose_parser(subparsers)
subparsers = setup_list_parser(subparsers)
return parser
def setup_compose_parser(subparsers):
"""Set up the argument parser to correctly match composition arguments"""
parser_compose = subparsers.add_parser('compose')
parser_compose.add_argument(
'-d',
'--draft',
default=False,
action='store_true',
help='Store as a draft instead of sending right away')
parser_compose.add_argument(
'-s',
'--subject',
help='Use this as the subject of a new message')
parser_compose.add_argument(
'-t',
'-to',
dest='to',
help='A list of comma separated email addresses to send the message to')
parser_compose.add_argument(
'--cc',
help='A list of comma separated email addresses to cc the message to')
parser_compose.add_argument(
'--bcc',
help='A list of comma separated email addresses to bcc the message to')
parser_compose.add_argument(
'--body',
help='The body of the message')
parser_compose.add_argument(
'--from',
dest='send_from',
help='The email to send the message from, if not the default')
parser_compose.add_argument(
'--skip',
default=False,
action='store_true',
help='Skip opening the editor, send with options provided')
return subparsers
def setup_list_parser(subparsers):
"""Set up the argument parser to correctly match listing arguments"""
return subparsers
def list_emails():
connection = authentication.authenticate()
connection.select('INBOX')
imap.list_messages(connection)
def parse_compose(args):
"""Parse the arguments for the compose command and put them into a Message"""
message = Message()
if args.draft is True:
message.is_draft = True
if args.subject is not None:
message.subject = args.subject
if args.to is not None:
message.send_to = args.to
if args.cc is not None:
message.send_cc = args.cc
if args.bcc is not None:
message.send_bcc = args.bcc
if args.body is not None:
message.body = args.body
if args.send_from is not None:
message.send_from = args.send_from
if args.skip is True:
message.skip = True
return message
def compose(message):
"""Set up the message composition, then get the input"""
editor = os.environ.get('EDITOR', 'vim')
subject_str = 'SUBJECT: ' + message.subject + '\n'
to_str = 'TO: ' + message.send_to + '\n'
cc_str = 'CC: ' + message.send_cc + '\n'
bcc_str = 'BCC: ' + message.send_bcc + '\n'
from_str = 'FROM: ' + message.send_from + '\n'
body_str = 'BODY: \n\n' + message.body
with tempfile.NamedTemporaryFile(suffix=".tmp") as new_msg:
new_msg.write(bytes(subject_str, 'UTF-8'))
new_msg.write(bytes(to_str, 'UTF-8'))
new_msg.write(bytes(cc_str, 'UTF-8'))
new_msg.write(bytes(bcc_str, 'UTF-8'))
new_msg.write(bytes(from_str, 'UTF-8'))
new_msg.write(bytes(body_str, 'UTF-8'))
new_msg.flush()
if message.skip is False:
call([editor, new_msg.name])
new_msg.seek(0)
separate_new_message(new_msg.read().decode('UTF-8').split('\n'))
def separate_new_message(lines):
"""Separates text lines into a message object"""
i = 1
new_message = {}
area = ""
areas = ['SUBJECT:', 'TO:', 'CC:', 'BCC:', 'FROM:', 'BODY:']
for line in lines:
if len(area) == 0:
area = line
else:
if i < len(areas) and line.startswith(areas[i]):
area = area.replace(areas[i-1], '', 1)
new_message[areas[i-1]] = area
area = line
i += 1
else:
area += line
area = area.replace(areas[i-1], '', 1)
new_message[areas[i-1]] = area
for area in new_message.values():
print(area)
if __name__ == "__main__":
main()