Mini Shell
#!/opt/imh-python/bin/python3
import subprocess
import os.path
import getpass
import argparse
import yaml
import json
import sys
import crontab
import random
from rads.shared import is_cpanel_user
#DEFAULTS: creates monthly archives for messages more than 30 days old in the format of "Archive.YYYY.MM-Jan"
#these are the settings pretty much everyone will be using
#most invocations will just be 'archive-email -a' with -c if its setting up a weekly cron
archive_name='Archive'
archive_period='2' #1=yearly 2=monthly
age=30 #dont touch mail until its this many days old
user=None #cpanel user
email=None #user's email account
dry_run=False #pretend we're archiving but dont move anything
trial_run=None #pretend we're archiving but dont move anything
add_cron=False #create user cron to run weekly
is_cron=False #is this a cron?
quiet=False #suppress output (for cron)
def do_archive(email, user, dry_run, quiet):
path = os.path.join('/home', user, 'mail', email.split('@')[1], email.split('@')[0])
cmd_opts = [
'/usr/local/bin/cleanup-maildir',
'--archive-folder={}'.format(archive_name),
'--archive-hierarchy-depth={}'.format(archive_period),
'--age={}'.format(age),
'--maildir-root={}'.format(path)
]
if dry_run:
cmd_opts.append('--trial-run')
if quiet:
cmd_opts.append('--quiet')
cmd_opts.extend(['archive', ''])
if os.path.exists(os.path.join(path, 'cur')):
subprocess.Popen(cmd_opts).wait()
def parse_args():
#argparsing here
parser = argparse.ArgumentParser(description='Archive large email accounts')
parser.add_argument('-a', '--all', action='store_true', dest='user',
help='archive all accounts for a cpanel user')
parser.add_argument('-e', '--email', action='store', dest='email', metavar="",
help='archive a single email account')
parser.add_argument('-c', '--add-cron', action='store_true', dest='add_cron',
help='add a weekly cron to continually archive configured users')
parser.add_argument('-n', '--dry-run', action='store_true', dest='dry_run',
help='run archive script without moving any files')
parser.add_argument('-q', '--quiet', action='store_true', dest='quiet', default=False,
help='quiet output')
parser.add_argument('-p', action='store_true',dest='is_cron',
help='archives users from config silently (for cron jobs)')
args = parser.parse_args()
if not args.user and not args.email and not args.is_cron and not args.add_cron:
sys.exit("imap-archiver.py : no option selected")
return args
def read_config(reader, path):
try:
with open(path) as handle:
return reader(handle)
except (ValueError, IOError):
return
def setup_cron(user):
ctab = crontab.CronTab(user=user)
cmd = '/usr/local/bin/imap-archiver -p -q'
if len([x for x in ctab.find_command(cmd) if x.is_enabled()]) > 0:
print('Cron already enabled: {}'.format(cmd))
return
job = ctab.new(command=cmd)
job.dow.on('SUN')
job.hour.on(random.randint(0,9))
job.minute.on(random.randint(0, 59))
print("Adding weekly cron to the crontab for {}".format(user))
ctab.write()
def main():
args = parse_args()
user = getpass.getuser()
#has to be run as the user just like the old one, so the folders it creates arent goofy.
if not is_cpanel_user(user):
print("This script must be run as the cpanel user to ensure proper file ownership")
sys.exit()
#since we're sure we're running as a user, set user to me
#if run with -e just archive the one email and exit
if args.email is not None:
print("archiving {0.email}".format(args))
# single email so get value from args
do_archive(args.email, user, args.dry_run, args.quiet)
sys.exit()
#read a list of accounts to load ours > cpanel new > cpanel old
try_confs = [
(json.load, os.path.join('/home', user, '.archived-accounts.json')),
(json.load, os.path.join('/home', user, '.cpanel/email_accounts.json')),
(yaml.load, os.path.join('/home', user, '.cpanel/email_accounts.yaml'))
]
data = None
for reader, path in try_confs:
data = read_config(reader, path)
if data is not None:
break # stop at the first config which could be loaded
if data is None: # still none
sys.exit('no valid config')
if args.is_cron: #imap-archiver -p
quiet = True #ensure we're running silently
#generate list of emails to archive
addrs = []
if isinstance(data, dict):
# then we read this from cpanel's config
data.pop('__version', None) # trim __version key off the end since it jacks up our loops
for domain in data.keys():
for email_user in data[domain]['accounts'].keys():
addrs.append("{}@{}".format(email_user,domain))
else:
# then we read this from our own config
addrs = data
try:
with open (os.path.join('/home', user, '.archived-accounts.json'), 'w') as f:
json.dump(addrs, f, indent=4)
except (ValueError, IOError):
print("Unable to write to config file")
#archive the things
for email in addrs:
#forcing quiet to True here because output gets horrible with multiple accts
do_archive(email, user, args.dry_run, True)
if args.add_cron:
setup_cron(user)
if __name__ == "__main__":
main()
Zerion Mini Shell 1.0