rpsync (2936B)
1 #!/usr/bin/env python3 2 # 3 # Copy me if you can 4 # by parazyd 5 # 6 """ rp module for syncing from a remote IMAP server. """ 7 8 from argparse import ArgumentParser 9 from os import getenv 10 from os.path import join 11 from imaplib import IMAP4, IMAP4_SSL 12 from subprocess import Popen, PIPE 13 from time import time 14 from sys import exit as die 15 16 17 PROFILE = getenv('RPPROFILE') 18 if not PROFILE: 19 PROFILE = join(getenv('HOME'), '.rp/default') 20 21 22 def parsecfg(): 23 """ Function for parsing the config file """ 24 cfgmap = {} 25 rawtxt = open(join(PROFILE, 'config')).read() 26 contents = rawtxt.split('\n')[:-1] 27 for i in contents: 28 key = i.split(': ', 1)[0] 29 val = i.split(': ', 1)[1] 30 cfgmap[key] = val 31 return cfgmap 32 33 34 def imapconnect(host, port): 35 """ Abstraction layer for an IMAP connection """ 36 if port in ('imap', 143): 37 return IMAP4(host=host, port=port) 38 if port in ('imaps', 993): 39 return IMAP4_SSL(host=host, port=port) 40 41 print('Invalid host and port: %s:%s' % (host, port)) 42 return None 43 44 45 def fetchmail(imapctx, mailbox): 46 """ Fetch all emails from a given mailbox """ 47 data = imapctx.select(mailbox) 48 data = imapctx.fetch('1:*', '(FLAGS)') 49 50 for i in data[1]: 51 email = imapctx.fetch(i.split()[0], 'body[]') 52 emailtopipe = email[1][0][1] 53 mbx = mailbox.replace(b'.', b'/') 54 55 proc = Popen(['/usr/libexec/dovecot/deliver', '-m', mbx], 56 stdin=PIPE) 57 proc.stdin.write(emailtopipe) 58 proc.communicate() 59 proc.stdin.close() 60 imapctx.store(i.split()[0], '+FLAGS', '\\Deleted') 61 imapctx.expunge() 62 63 64 def main(): 65 """ Main routine """ 66 parser = ArgumentParser(description='rpsync') 67 parser.add_argument('mbox', type=str, nargs='+', help='Mailbox to sync') 68 parser.add_argument('-n', action='store_true', help='Dry run') 69 70 args = parser.parse_args() 71 72 dryrun = args.n 73 config = parsecfg() 74 rhost = config['rnet'].split('!')[1] 75 rport = config['rnet'].split('!')[2] 76 77 imap = imapconnect(rhost, rport) 78 if not imap: 79 die(1) 80 81 imap.login(config['ruser'], config['rpass']) 82 83 boxes = [] 84 if args.mbox[0] == 'all': 85 for i in imap.list()[1]: 86 boxes.append(i.split()[2]) 87 else: 88 for i in args.mbox: 89 boxes.append(i.encode()) 90 91 hasmail = [] 92 for i in boxes: 93 status = imap.status(i, '(MESSAGES)')[1][0].split(b' ', 1) 94 if status[1] != b'(MESSAGES 0)': 95 nmails = status[1].decode('utf-8').split(' ', 1)[1] 96 print('* New mail in %s (%s' % (i.decode('utf-8'), nmails)) 97 hasmail.append(i) 98 99 if hasmail: 100 if not dryrun: 101 for i in hasmail: 102 fetchmail(imap, i) 103 else: 104 print('* No new mail') 105 106 imap.logout() 107 108 109 if __name__ == '__main__': 110 T1 = time() 111 main() 112 T2 = time() 113 print('* Total time: %.2f seconds' % (T2 - T1))