Skip to content

Commit 61a3f63

Browse files
committed
merging gmv-1.9.1 in master
2 parents a759623 + 77b16c3 commit 61a3f63

File tree

14 files changed

+410
-120
lines changed

14 files changed

+410
-120
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*.pyc
33
*.o
44
*.class
5+
*.spec
56
gmvault.log
67
.DS_Store
78
dists/disstoolbox-dist/build

Makefile

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ PYTHONBIN=python #MacOSX machine
2626
PYTHONWINBIN=/c/Python27/python.exe #windows laptop
2727
PYTHONVERSION=2.7
2828

29+
PYINSTALLERMAC=/Library/Frameworks/Python.framework/Versions/2.7/bin/pyinstaller
30+
PYINSTALLERWIN=c:/Python27/Scripts/pyinstaller.exe
31+
2932
#MAKENSIS=/cygdrive/d/Programs/NSIS/makensis.exe #windows work
30-
MAKENSIS=/c/Program\ Files/NSIS/makensis.exe #windows laptop
33+
MAKENSIS=c:/Program\ Files/NSIS/makensis.exe #windows laptop
3134

3235
#VERSION is in gmv_cmd.py as GMVAULT_VERSION
3336
GMVVERSION=$(shell python $(BASEDIR)/etc/utils/find_version.py $(BASEDIR)/src/gmv/gmvault_utils.py)
@@ -123,15 +126,9 @@ gmv-linux-dist: clean init
123126
@echo "=================================================================="
124127

125128
gmv-mac-dist: clean init
126-
cp -R $(BASEDIR)/src/gmv $(GMVDIST)
127-
cp -R $(BASEDIR)/src/gmv_runner.py $(GMVDIST)
128-
cp $(BASEDIR)/src/setup_mac.py $(GMVDIST)
129-
cd $(GMVDIST); $(PYTHONBIN) setup_mac.py py2app --arch=intel
130-
mkdir -p $(GMVDIST)/$(GMVDISTNAME)/bin ; mkdir -p $(GMVDIST)/$(GMVDISTNAME)/lib
131-
cp $(BASEDIR)/etc/scripts/gmvault_mac $(GMVDIST)/$(GMVDISTNAME)/bin/gmvault
132-
cp -R $(BASEDIR)/README.md $(GMVDIST)/$(GMVDISTNAME)/bin/README.txt
133-
cp $(BASEDIR)/RELEASE-NOTE.txt $(GMVDIST)/$(GMVDISTNAME)/bin/RELEASE-NOTE.txt
134-
cp -R $(GMVDIST)/dist/gmv_runner.app $(GMVDIST)/$(GMVDISTNAME)/lib
129+
$(PYINSTALLERMAC) --onefile --name gmvault --distpath=$(GMVDIST)/$(GMVDISTNAME) $(BASEDIR)/src/gmv_runner.py
130+
cp -R $(BASEDIR)/README.md $(GMVDIST)/$(GMVDISTNAME)/README.txt
131+
cp $(BASEDIR)/RELEASE-NOTE.txt $(GMVDIST)/$(GMVDISTNAME)/RELEASE-NOTE.txt
135132
cd $(GMVDIST); tar zcvf ./$(GMVDISTNAME)-macosx-intel.tar.gz ./$(GMVDISTNAME)
136133
@echo ""
137134
@echo "========================================="
@@ -140,12 +137,8 @@ gmv-mac-dist: clean init
140137
@echo ""
141138
@echo "========================================="
142139

143-
gmv-win-dist: init
144-
mkdir -p $(GMVWINBUILDDIST)
145-
cp -R $(BASEDIR)/src/gmv $(GMVDIST)
146-
cp -R $(BASEDIR)/src/gmv_runner.py $(GMVDIST)
147-
cp $(BASEDIR)/src/setup_win.py $(GMVDIST)
148-
cd $(GMVDIST); $(PYTHONWINBIN) setup_win.py py2exe -d ../$(GMVWINBUILDDIST)
140+
gmv-win-dist: clean init
141+
$(PYINSTALLERWIN) --onefile --name gmv_runner --distpath=$(GMVWINBUILDDIST) $(BASEDIR)/src/gmv_runner.py
149142
cp $(BASEDIR)/etc/scripts/gmvault.bat $(GMVWINBUILDDIST)
150143
cp $(BASEDIR)/etc/scripts/gmvault-shell.bat $(GMVWINBUILDDIST)
151144
cd .; $(PYTHONWINBIN) $(BASEDIR)/etc/utils/add_version.py $(BASEDIR)/etc/scripts/gmv-msg.bat $(GMVWINBUILDDIST)/gmv-msg.bat $(GMVVERSION)
@@ -168,12 +161,11 @@ gmv-win-installer: gmv-win-dist
168161

169162
clean: clean-build
170163
mkdir -p $(GMVDIST)
171-
cd $(GMVDIST); rm -Rf ./etc; rm -f MANIFEST.in; rm -f RELEASE-NOTE.txt; rm -Rf build; rm -Rf gmvault.egg-info; rm -f setup*.py ; rm -Rf dist ; rm -Rf src; rm -f README* ;rm -Rf GMVault.egg-info; rm -Rf gmv; rm -Rf scripts; rm -f *.tar.gz
164+
rm -Rf $(GMVDIST)/*
172165

173166
clean-build:
174167
mkdir -p $(GMVBUILD)
175-
cd $(GMVBUILD); rm -Rf egg-dist;
168+
rm -Rf $(GMVBUILD)/egg-dist;
176169
rm -Rf $(GMVDIST)/$(GMVDISTNAME)
177170
rm -Rf $(GMVWINBUILDDIST)
178171

179-

RELEASE-NOTE.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
Release Notes for the different versions:
22
-------------------------------
33

4+
-------------------------------
5+
Version Gmvault-v1.9.1-beta:
6+
-------------------------------
7+
-------------------------------
8+
Date: 31.03.2016
9+
10+
Release fixing many bugs left in 1.0-beta and improving deployment on Mac OS X and Windows (use now pyinstaller).
11+
12+
Bug Fixes:
13+
----------
14+
- Fix bug preventing to use encryption [Github issue #84]
15+
- Fix many character encoding bugs in emails [Github issue #211, #213, #152, #218, ]
16+
- Fix encoding bug in labels [Github issue #180]
17+
- Fix encoding bug in commandline parameters [Github issue #195]
18+
- Fix bug preventing email containing null characters to be restored [Github #212]
19+
- Fix bug corrupting oauth2 credential when saved in file [Github #209]
20+
21+
Shoutouts to:
22+
-------------
23+
24+
Shout out to everybody who continued supporting the project while I was away.
25+
26+
Also shoutouts to all the users that sent me support emails and raised issues by emails.
27+
28+
Gmvault Pantheon:
29+
-----------------
30+
31+
A million time thank you for the benevolent donors that are forever in the Gmvault Pantheon and All of Fame for their gesture.
32+
33+
Jason Stangroome, Mathieu Pinson, Mathieu Clavel, Stijn Jonker, Douglas Carter, Steven Moschidis, GoVelvet LLC, Daniel Brass , Joseph Colburn, Joanne Kaye, Bernie Santos, Wolfgang Schwaiger, Kraut Computing, Matt Burke, Ademario Araujo Jr, Roque Pinel, George Armhold, Randi Veiberg, Gregory Szilagyi, Antony Moore, Filip Moerman, Axel Amigo Arnold, Jonathan Sarasin, Kirby Moyers, Alberto Cottica, Richard Lee, Suneel Kanuri, Owen Phelps, Clint Chapman, Donmez Ismail, Tomas Bäckman, Keith Petersen, Holden Karau, James Mcfarland, Clayton Stanley, Stefan Habetz, Francesco Bellomo, Brian Yanosik, Bjarte Aune Olsen, Joel Sylvester, Billy Amon, Alexander Halperin, John Zendano, Alex Van't Hof, JJ Tiziou Photography, Sally Carr, Jacek Szczech, Baden Holt, Eleonora Borelli, Patrick Van Humbeeck
34+
435
-------------------------------
536
Version Gmvault-v1.9-beta:
637
-------------------------------

etc/nsis-install/gmvault_setup.nsi

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ File gmv-icon.ico
118118
File gmvault-shell.bat
119119
File RELEASE-NOTE.txt
120120
File README.txt
121-
File library.zip
122-
File python27.dll
123-
File w9xpopen.exe
124-
File *.pyd
125-
File /r Microsoft.VC90.CRT
121+
;File library.zip
122+
;File python27.dll
123+
;File w9xpopen.exe
124+
;File *.pyd
125+
;File /r Microsoft.VC90.CRT
126126

127127
IfErrors 0 +2
128128

@@ -149,13 +149,13 @@ Delete $INSTDIR\library.zip
149149
Delete $INSTDIR\*.ico
150150
Delete $INSTDIR\*.bat
151151
Delete $INSTDIR\*.txt
152-
Delete $INSTDIR\python27.dll
153-
Delete $INSTDIR\w9xpopen.exe
154-
Delete $INSTDIR\*.pyd
155-
Delete $INSTDIR\Microsoft.VC90.CRT\*.dll
156-
Delete $INSTDIR\Microsoft.VC90.CRT\*.manifest
152+
;Delete $INSTDIR\python27.dll
153+
;Delete $INSTDIR\w9xpopen.exe
154+
;Delete $INSTDIR\*.pyd
155+
;Delete $INSTDIR\Microsoft.VC90.CRT\*.dll
156+
;Delete $INSTDIR\Microsoft.VC90.CRT\*.manifest
157157
Delete $INSTDIR\${UNINSTALLER_NAME}
158-
rmDir /r $INSTDIR\Microsoft.VC90.CRT
158+
;rmDir /r $INSTDIR\Microsoft.VC90.CRT
159159
;rmDir /r $INSTDIR
160160
rmDir $INSTDIR
161161

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,5 @@ def find_version(path):
6767
package_data={'': ['release-note.txt']},
6868
include_package_data=True,
6969
#install_requires=['argparse', 'Logbook==0.4.1', 'IMAPClient==0.9.2','gdata==2.0.17']
70-
install_requires=['argparse', 'Logbook==0.9.0', 'IMAPClient==0.12', 'chardet==2.3.0']
70+
install_requires=['argparse', 'Logbook==0.10.1', 'IMAPClient==0.13', 'chardet==2.3.0']
7171
)

src/gmv/credential_utils.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import webbrowser
2424
import json
2525
import base64
26-
import urllib
26+
import urllib #for urlencode
2727
import urllib2
2828

2929
import os
@@ -69,7 +69,7 @@ def get_secret_key(cls, a_filepath):
6969
Get secret key if it is in the file otherwise generate it and save it
7070
"""
7171
if os.path.exists(a_filepath):
72-
with open(a_filepath).read() as f:
72+
with open(a_filepath) as f:
7373
secret = f.read()
7474
else:
7575
secret = gmvault_utils.make_password()
@@ -114,7 +114,14 @@ def store_oauth2_credentials(cls, email, access_token, refresh_token, validity,
114114

115115
# Open a file
116116
fdesc = os.open(oauth_file, os.O_RDWR|os.O_CREAT )
117-
fobj = os.fdopen(fdesc, "w+")
117+
118+
#write new content
119+
fobj = os.fdopen(fdesc, "w")
120+
121+
#empty file
122+
fobj.truncate()
123+
fobj.seek(0, os.SEEK_SET)
124+
118125

119126
the_obj = { "access_token" : access_token,
120127
"refresh_token" : refresh_token,
@@ -293,7 +300,7 @@ def _get_authorization_tokens(cls, authorization_code):
293300
request_url = '%s/%s' % (account_base_url, 'o/oauth2/token')
294301

295302
try:
296-
response = urllib.urlopen(request_url, urllib.urlencode(params)).read()
303+
response = urllib2.urlopen(request_url, urllib.urlencode(params)).read()
297304
except Exception, err: #pylint: disable-msg=W0703
298305
LOG.critical("Error: Problems when trying to connect to Google oauth2 endpoint: %s." % (request_url))
299306
raise err

src/gmv/gmv_cmd.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class GMVaultLauncher(object):
149149
def __init__(self):
150150
""" constructor """
151151
super(GMVaultLauncher, self).__init__()
152-
152+
153153
@gmvault_utils.memoized
154154
def _create_parser(self): #pylint: disable=R0915
155155
"""
@@ -201,6 +201,10 @@ def _create_parser(self): #pylint: disable=R0915
201201
help="use interactive password authentication, encrypt and store the password. (not recommended)",
202202
action= 'store_const' , dest="passwd", const='store')
203203

204+
#sync_parser.add_argument("-r", "--imap-req", type = get_unicode_commandline_arg, metavar = "REQ", \
205+
# help="Imap request to restrict sync.",\
206+
# dest="imap_request", default=None)
207+
204208
sync_parser.add_argument("-r", "--imap-req", metavar = "REQ", \
205209
help="Imap request to restrict sync.",\
206210
dest="imap_request", default=None)
@@ -273,7 +277,7 @@ def _create_parser(self): #pylint: disable=R0915
273277
default='full', help='type of restoration: full|quick. (default: full)')
274278

275279
# add a label
276-
rest_parser.add_argument('-a', '--apply-label', \
280+
rest_parser.add_argument('-a', '--apply-label' , \
277281
action='store', dest='apply_label', \
278282
default=None, help='Apply a label to restored emails')
279283

@@ -694,7 +698,8 @@ def _sync(cls, args, credential):
694698
elif args.get('type', '') == 'custom':
695699

696700
#convert args to unicode
697-
args['request']['req'] = gmvault_utils.convert_to_unicode(args['request']['req'])
701+
u_str = gmvault_utils.convert_argv_to_unicode(args['request']['req'])
702+
args['request']['req'] = u_str
698703
args['request']['charset'] = 'utf-8' #for the moment always utf-8
699704
args['request']['mode'] = 'custom'
700705

@@ -836,7 +841,7 @@ def bootstrap_run():
836841
""" temporary bootstrap """
837842

838843
init_logging()
839-
844+
840845
#force argv[0] to gmvault
841846
sys.argv[0] = "gmvault"
842847

@@ -845,7 +850,7 @@ def bootstrap_run():
845850
gmvlt = GMVaultLauncher()
846851

847852
args = gmvlt.parse_args()
848-
853+
849854
#activate debug if enabled
850855
if args['debug']:
851856
LOG.critical("Activate debugging information.")

src/gmv/gmvault.py

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def handle_sync_imap_error(the_exception, the_id, error_report, src):
102102
except Exception, _: #pylint:disable-msg=W0703
103103
curr = None
104104
LOG.critical("Error when trying to get gmail id for message with imap id %s." % (the_id))
105-
LOG.critical("Disconnect, wait for 20 sec then reconnect.")
105+
LOG.critical("Disconnect, wait for 10 sec then reconnect.")
106106
src.disconnect()
107107
#could not fetch the gm_id so disconnect and sleep
108108
#sleep 10 sec
@@ -265,7 +265,8 @@ def __init__(self, db_root_dir, host, port, login, \
265265
self.error_report = { 'empty' : [] ,
266266
'cannot_be_fetched' : [],
267267
'emails_in_quarantine' : [],
268-
'reconnections' : 0}
268+
'reconnections' : 0,
269+
'key_error' : []}
269270

270271
#instantiate gstorer
271272
self.gstorer = gmvault_db.GmailStorer(self.db_root_dir, self.use_encryption)
@@ -290,14 +291,16 @@ def get_operation_report(self):
290291
"%s operation performed in %s.\n" \
291292
"Number of reconnections: %d.\nNumber of emails quarantined: %d.\n" \
292293
"Number of emails that could not be fetched: %d.\n" \
293-
"Number of emails that were returned empty by gmail: %d\n"\
294+
"Number of emails that were returned empty by gmail: %d.\n"\
295+
"Number of emails without label information returned by gmail: %d.\n"\
294296
"================================================================" \
295297
% (self.error_report['operation'], \
296298
self.error_report['operation_time'], \
297299
self.error_report['reconnections'], \
298300
len(self.error_report['emails_in_quarantine']), \
299301
len(self.error_report['cannot_be_fetched']), \
300-
len(self.error_report['empty'])
302+
len(self.error_report['empty']), \
303+
len(self.error_report['key_error'])
301304
)
302305

303306
LOG.debug("error_report complete structure = %s" % (self.error_report))
@@ -430,8 +433,9 @@ def _common_sync(self, a_timer, a_type, imap_req, compress, restart):
430433
"""
431434
# get all imap ids in All Mail
432435
imap_ids = self.src.search(imap_req)
433-
434-
last_id_file = self.OP_EMAIL_SYNC if a_type == "email" else self.OP_CHAT_SYNC
436+
437+
last_id_file = self.OP_EMAIL_SYNC if a_type == "email" else self.OP_CHAT_SYNC
438+
435439
# check if there is a restart
436440
if restart:
437441
LOG.critical("Restart mode activated for emails. Need to find information in Gmail, be patient ...")
@@ -484,8 +488,23 @@ def _common_sync(self, a_timer, a_type, imap_req, compress, restart):
484488
LOG.critical("Process %s num %d (imap_id:%s) from %s." % (a_type, nb_msgs_processed, the_id, the_dir))
485489

486490
#decode the labels that are received as utf7 => unicode
487-
new_data[the_id][imap_utils.GIMAPFetcher.GMAIL_LABELS] = \
488-
imap_utils.decode_labels(new_data[the_id][imap_utils.GIMAPFetcher.GMAIL_LABELS])
491+
try:
492+
new_data[the_id][imap_utils.GIMAPFetcher.GMAIL_LABELS] = \
493+
imap_utils.decode_labels(new_data[the_id][imap_utils.GIMAPFetcher.GMAIL_LABELS])
494+
except KeyError, ke:
495+
LOG.info("KeyError, reason: %s. new_data[%s]=%s" % (str(ke), the_id, new_data.get(the_id)))
496+
# try to fetch it individually and replace current info if it fails then raise error.
497+
id_info = None
498+
try:
499+
id_info = batch_fetcher.individual_fetch(the_id)
500+
new_data[the_id][imap_utils.GIMAPFetcher.GMAIL_LABELS] = \
501+
imap_utils.decode_labels(id_info[imap_utils.GIMAPFetcher.GMAIL_LABELS])
502+
except Exception, err:
503+
LOG.debug("Error when trying to fetch again information for email id %s. id_info = %s. exception:(%s)" \
504+
% (the_id, id_info, str(err)))
505+
LOG.info("Missing labels information for email id %s. Ignore it\n" % (the_id))
506+
self.error_report['key_error'].append((the_id, new_data.get(the_id)))
507+
continue
489508

490509
LOG.debug("metadata info collected: %s\n" % (new_data[the_id]))
491510

@@ -998,7 +1017,11 @@ def restore_chats(self, extra_labels = [], restart = False): #pylint:disable=W01
9981017
self.src.apply_labels_to(labels_to_apply[label], [label])
9991018
except Exception, err:
10001019
LOG.error("Problem when applying labels %s to the following ids: %s" %(label, labels_to_apply[label]), err)
1001-
if isinstance(err, imaplib.IMAP4.abort) and str(err).find("=> Gmvault ssl socket error: EOF") >= 0:
1020+
if isinstance(err, imap_utils.LabelError) and err.ignore() == True:
1021+
LOG.critical("Ignore labelling: %s" % (err))
1022+
LOG.critical("Disconnecting and reconnecting to restart cleanly.")
1023+
self.src.reconnect() #reconnect
1024+
elif isinstance(err, imaplib.IMAP4.abort) and str(err).find("=> Gmvault ssl socket error: EOF") >= 0:
10021025
# if this is a Gmvault SSL Socket error ignore labelling and continue the restore
10031026
LOG.critical("Ignore labelling")
10041027
LOG.critical("Disconnecting and reconnecting to restart cleanly.")
@@ -1082,6 +1105,9 @@ def restore_emails(self, pivot_dir = None, extra_labels = [], restart = False):
10821105
# unbury the metadata for all these emails
10831106
for gm_id in group_imap_ids:
10841107
try:
1108+
1109+
LOG.debug("Unbury email with gm_id %s." % (gm_id))
1110+
10851111
email_meta, email_data = self.gstorer.unbury_email(gm_id)
10861112

10871113
LOG.critical("Pushing email body with id %s." % (gm_id))
@@ -1125,7 +1151,6 @@ def restore_emails(self, pivot_dir = None, extra_labels = [], restart = False):
11251151

11261152
# associate labels with emails
11271153
LOG.critical("Applying labels to the current batch of emails.")
1128-
11291154
try:
11301155
LOG.debug("Changing directory. Going into ALLMAIL")
11311156
the_timer = gmvault_utils.Timer()
@@ -1136,8 +1161,11 @@ def restore_emails(self, pivot_dir = None, extra_labels = [], restart = False):
11361161
self.src.apply_labels_to(labels_to_apply[label], [label])
11371162
except Exception, err:
11381163
LOG.error("Problem when applying labels %s to the following ids: %s" %(label, labels_to_apply[label]), err)
1139-
LOG.error("Problem when applying labels.", err)
1140-
if isinstance(err, imaplib.IMAP4.abort) and str(err).find("=> Gmvault ssl socket error: EOF") >= 0:
1164+
if isinstance(err, imap_utils.LabelError) and err.ignore() == True:
1165+
LOG.critical("Ignore labelling: %s" % (err))
1166+
LOG.critical("Disconnecting and reconnecting to restart cleanly.")
1167+
self.src.reconnect() #reconnect
1168+
elif isinstance(err, imaplib.IMAP4.abort) and str(err).find("=> Gmvault ssl socket error: EOF") >= 0:
11411169
# if this is a Gmvault SSL Socket error ignore labelling and continue the restore
11421170
LOG.critical("Ignore labelling")
11431171
LOG.critical("Disconnecting and reconnecting to restart cleanly.")

0 commit comments

Comments
 (0)