Created
March 5, 2017 11:11
-
-
Save DaffyDuke/dd5afc6271ae67bbbfce6783c2b009ac to your computer and use it in GitHub Desktop.
imapsave - From http://stackp.online.fr/?p=25
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: iso-8859-1 -*- | |
# Licensed under the Python License (see http://www.python.org/psf/license/) | |
# Copyright (C) 2008 Pierre Duquesne <stackp@online.fr> | |
# | |
# Changelog: | |
# 20080722 * disable spinning when output is redirected to a file | |
# 20080718 * Use BODY.PEEK[] in the fetch command as specified in RFC 3501 | |
# (fix by Stefan) | |
# 20080313 * Initial release | |
import getpass | |
import imaplib | |
import email | |
import email.Parser | |
import re | |
import sys | |
import getopt | |
from os.path import basename | |
USAGE = """\ | |
usage: %s [--ssl] [--port num] [--password pass] [server] [user] | |
server | |
The hostname of your imap server | |
user | |
Your login | |
--ssl | |
Use an encrypted connection | |
-p num | |
--port num | |
Use port number num instead of default port | |
(Defaults are 143 for unencrypted connection and 993 for ssl) | |
-P pass | |
--password pass | |
Password for the server | |
""" % basename(sys.argv[0]) | |
class Spinner: | |
"""A class to show some activity on a character terminal.""" | |
def __init__(self, message=''): | |
self.message = message | |
self.symbols = list('-\|/') | |
self.nsym = len(self.symbols) | |
self.n = 0 | |
def spin(self): | |
print '\r', self.message + self.symbols[self.n], | |
sys.stdout.flush() | |
self.n = (self.n + 1) % self.nsym | |
def stop(self, stop_message=''): | |
print '\r', self.message + stop_message | |
def set_message(self, message): | |
self.message = message | |
class DummySpinner: | |
"""A class that mock Spinner and do not spin. | |
Used when output is not a character terminal (e.g. a log file). | |
""" | |
def __init__(self, message=''): | |
self.message = message | |
def spin(self): | |
pass | |
def stop(self, stop_message=''): | |
print self.message + stop_message | |
def set_message(self, message): | |
self.message = message | |
def foldname_to_filename(folder): | |
"""Deal with weird characters in folder names.""" | |
filename = re.sub('"(.*)"', ur'\1', folder) | |
filename = filename.replace('/', '.') | |
return filename | |
try: | |
# Parse command line arguments | |
try: | |
opts, args = getopt.gnu_getopt(sys.argv[1:], 'pP:h', | |
['port=', 'password=', 'ssl', 'help']) | |
except getopt.GetoptError, e: | |
print 'Error:', e | |
sys.exit(1) | |
ssl = False | |
port = None | |
password = None | |
for o, a in opts: | |
if o == '--ssl': | |
ssl = True | |
if o == '-p' or o == '--port': | |
port = int(a) | |
if o == '-P' or o == '--password': | |
password = a | |
elif o in ['-h', '--help']: | |
print USAGE | |
sys.exit(0) | |
try: | |
servername = args[0] | |
except IndexError: | |
servername = raw_input("Enter the server hostname: ") | |
try: | |
username = args[1] | |
except IndexError: | |
username = raw_input("Enter your username: ") | |
# Connect | |
print 'Connecting to %s as user %s ...' % (servername, username) | |
if ssl: | |
IMAP = imaplib.IMAP4_SSL | |
else: | |
IMAP = imaplib.IMAP4 | |
try: | |
if port: | |
server = IMAP(servername, port) | |
else: | |
server = IMAP(servername) | |
if not password: | |
password = getpass.getpass() | |
server.login(username, password) | |
except Exception, e: | |
print 'Error:', e | |
sys.exit(1) | |
# Retrieve folder list | |
folders = [] | |
foldptn = re.compile('\([^\)]*\) "[^"]*" ([^"]*)') | |
for fold_desc in server.list()[1]: | |
folder = foldptn.sub(ur'\1', fold_desc) | |
folders.append(folder) | |
# Save messages in a separate file for each folder | |
if sys.stdout.isatty(): | |
spinner = Spinner() | |
else: | |
spinner = DummySpinner() | |
parser = email.Parser.Parser() | |
succeed = [] | |
failed = [] | |
for folder in folders: | |
msg = '%s ... ' % folder | |
spinner.set_message(msg) | |
try: | |
resp, info = server.select(folder) | |
if resp != 'OK': | |
raise imaplib.IMAP4.error(' - '.join(info)) | |
filename = foldname_to_filename(folder) | |
fp = open(filename, 'w') | |
resp, items = server.search(None, "ALL") | |
numbers = items[0].split() | |
for num in numbers: | |
resp, data = server.fetch(num, "(BODY.PEEK[])") | |
text = data[0][1] | |
mess = parser.parsestr(text) | |
fp.write(mess.as_string(unixfrom=True)) | |
spinner.spin() | |
succeed.append(folder) | |
spinner.stop('Done.') | |
fp.close() | |
except imaplib.IMAP4.error, e: | |
failed.append(folder) | |
spinner.stop('Error! (' + str(e) + ')') | |
server.logout() | |
# Print the folders which failed, if any | |
if failed != []: | |
import textwrap | |
wrapper = textwrap.TextWrapper(initial_indent=' ', | |
subsequent_indent=' ') | |
print 'WARNING - The following folders could not be saved:' | |
print wrapper.fill(', '.join(failed)) | |
sys.exit(1) | |
except KeyboardInterrupt: | |
print '' | |
print '^C received, stopping.' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment