-
Notifications
You must be signed in to change notification settings - Fork 2
/
mdexportab.py
executable file
·130 lines (105 loc) · 3.81 KB
/
mdexportab.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
#!/usr/bin/env python3
#########################################################################################
# Script to export the MDaemon Addresbook for all users in one or various domain folders
#
# Author: [email protected] @stdevPavelmc in github
#
# Instructions:
# - Install Python 3.5 or later for windows
# - Copy this script to the "Users" folder where MDaemon put it's domain folders
# - Run the script from inside that folder
#########################################################################################
import os
from xml.etree import ElementTree as ET
from quopri import encodestring as qpencode
def detect_folders_inside(fpath):
"""Detect folders inside a specific path, retuned as a list"""
folders = []
for d in os.listdir(fpath):
if os.path.isdir(os.path.join(fpath, d)):
folders.append(d)
return folders
def get_mrk_files(fpath):
"""Get the addressbook files for a given path"""
files = []
# r=root, d=directories, f= files
for r, d, f in os.walk(fpath):
for file in f:
if '.mrk' in file:
files.append(os.path.join(r, file))
return files
def parse_mrk_file(userab, ab):
"""Parse the ab file, ignoring already parsed entries"""
for c in ab.iter('contact'):
contact = []
try:
name = c.find('fullName').text
email = c.find('email').text
except:
pass
continue
# create the contact list
if email != "":
contact.append(name)
contact.append(email)
# append if not already
if not contact in userab:
userab.append(contact)
return userab
def vcfWriter(contact):
"""Adapted from the file format produced by mozilla thunderbird and some examples online"""
name, email = contact
vcfLines = []
vcfLines.append('begin:vcard')
vcfLines.append('version:2.1')
if name != email:
ename = qpencode(name.encode()).decode()
vcfLines.append('fn;quoted-printable:{}'.format(ename))
vcfLines.append('email;internet:{}'.format(email))
vcfLines.append('end:vcard')
vcfString = '\n'.join(vcfLines) + '\n\n'
return vcfString
if __name__ == "__main__":
# work on local path
path = './'
# create the output directory
opath = os.path.join(path, "output")
os.makedirs(opath, exist_ok=True)
# domains, detecting all the domain folders
domains = detect_folders_inside(path)
for d in domains:
# ignode the output directory
if d == "output":
continue
# Advice
print("> Working on domain folder: {}".format(d))
# domain path and detect users
dpath = os.path.join(path, d)
users = detect_folders_inside(os.path.join(dpath))
# parsing users
for u in users:
upath = os.path.join(dpath, u)
# users address book
userab = []
files = get_mrk_files(upath)
for f in files:
# load the file
try:
xf = ET.parse(f)
ab = xf.getroot()
except:
pass
continue
# detect if the file has valid entries
if len(ab) != 0:
userab = parse_mrk_file(userab, ab)
if len(userab) > 0:
# notice
print(">> User: {}, rescued {} contacts".format(u, len(userab)))
# write the file for that user
ud = os.path.join(opath, d)
os.makedirs(ud, exist_ok=True)
uf = os.path.join(ud, u + ".vcf")
with open(uf, mode='wt', encoding='utf-8') as myfile:
for c in userab:
myfile.write(vcfWriter(c))