rp

simple email tools
git clone https://git.parazyd.org/rp
Log | Files | Refs | README | LICENSE

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))