-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmailhack.py
More file actions
executable file
·169 lines (131 loc) · 5.62 KB
/
Copy pathmailhack.py
File metadata and controls
executable file
·169 lines (131 loc) · 5.62 KB
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
import imapclient
import json
import logging
import os.path
import sys
BATCH_SIZE=20
MAILHACK_FOLDER = 'Mailhack'
TRASH_FOLDER = 'Mailhack/Trash'
PERMIT_FOLDER = 'Mailhack/Permit'
BLOCK_FOLDER = 'Mailhack/Block'
INBOX_FOLDER = 'INBOX'
def address_to_string(addr):
if addr.mailbox is None or addr.host is None:
return None
return u'{0}@{1}'.format(addr.mailbox.lower(),addr.host.lower())
def always(envelope):
return True
def not_permitted(envelope):
return not permitted(envelope)
def permitted(envelope):
if envelope.from_ is None:
return False
for address in list(envelope.from_):
sender = address_to_string(address)
if sender is None:
continue
if sender in whitelist:
return True
return False
def from_addresses(folder):
server.select_folder(folder)
message_ids = server.search()
message_count = len(message_ids)
from_address_list = []
for batch_start in range(0,message_count,BATCH_SIZE):
if batch_start + BATCH_SIZE < message_count:
batch = message_ids[batch_start:batch_start + BATCH_SIZE]
else:
batch = message_ids[batch_start:]
data = server.fetch(batch,[b'ENVELOPE'])
for id, d in data.items():
envelope = d[b'ENVELOPE']
for address in list(envelope.from_):
sender = address_to_string(address)
if sender is None:
continue
else:
if sender not in from_address_list:
from_address_list.append(sender)
return from_address_list
def move(from_folder, to_folder, condition):
server.select_folder(from_folder)
message_ids = server.search()
message_count = len(message_ids)
print('there are {0} messages in the {1}'.format(message_count, from_folder))
total_moved = 0
for batch_start in range(0,message_count,BATCH_SIZE):
messages_to_move = []
if batch_start + BATCH_SIZE < message_count:
batch = message_ids[batch_start:batch_start + BATCH_SIZE]
else:
batch = message_ids[batch_start:]
data = server.fetch(batch,[b'ENVELOPE'])
for id, d in data.items():
envelope = d[b'ENVELOPE']
if condition(envelope):
messages_to_move.append(id)
if len(messages_to_move) > 0:
server.copy(messages_to_move,to_folder)
server.delete_messages(messages_to_move)
server.expunge()
total_moved += len(messages_to_move)
print('moved {0} messages from {1} to {2}'.format(total_moved, from_folder, to_folder))
if __name__ == '__main__':
# logging.basicConfig(
# format='%(asctime)s - %(levelname)s: %(message)s',
# level=logging.DEBUG
# )
here = os.path.abspath(os.path.dirname(sys.argv[0]))
# load the config file
config_file = os.path.join(here,'mailhack.json')
if os.path.exists(config_file):
with open(os.path.join(here,'mailhack.json'),'r') as f:
config = json.load(f)
print('loaded configuration from {0}'.format(config_file))
else:
sys.exit('require configuration file "{0}" not found'.format(config_file))
# load the white list
whitelist = []
whitelist_file = os.path.join(here,'whitelist.json')
if os.path.exists(whitelist_file):
with open(whitelist_file,'r') as f:
whitelist = json.load(f)
print('loaded white list from {0}'.format(whitelist_file))
# TODO process the Permit/Block folders on all servers first
for account in config['accounts']:
server = imapclient.IMAPClient(account['server'], port=account['port'])
response = server.login(account['username'],account['password'])
print('connected to {0}'.format(account['server']))
# check for required folders and create whatever doesn't exist
for folder in [MAILHACK_FOLDER,TRASH_FOLDER,PERMIT_FOLDER,BLOCK_FOLDER]:
if not server.folder_exists(folder):
server.create_folder(folder)
print('created folder: {0}'.format(folder))
# check the Permit folder
permit_list = from_addresses(PERMIT_FOLDER)
for address in permit_list:
if address not in whitelist:
whitelist.append(address)
print('{0} added to white list'.format(address))
move(PERMIT_FOLDER, INBOX_FOLDER, always)
# check the Block folder
block_list = from_addresses(BLOCK_FOLDER)
for address in block_list:
if address in whitelist:
whitelist.remove(address)
print('removed {0} from white list'.format(address))
move(BLOCK_FOLDER,TRASH_FOLDER, always)
server.logout()
# for each account
for account in config['accounts']:
server = imapclient.IMAPClient(account['server'], port=account['port'])
response = server.login(account['username'],account['password'])
print('connected to {0}'.format(account['server']))
move(INBOX_FOLDER,TRASH_FOLDER,not_permitted)
move(TRASH_FOLDER,INBOX_FOLDER, permitted)
server.logout()
print('done processing {0}'.format(account['server']))
with open(whitelist_file, 'w') as f:
json.dump(sorted(whitelist),f, indent = 3)
print('saved white list to {0}'.format(whitelist_file))