mailer.py 3.15 KB
import os
import sys
import json
from time import sleep
from logging import getLogger
from argparse import ArgumentParser
from configparser import ConfigParser
import smtplib
from base64 import b64decode
from opensipkd.string import exception_message
from .tools import (
    make_pid_file,
    clean_log,
    create_doc,
    file2dict,
    )
from .logger import setup_logging


registry = dict()


def dict2doc(d):
    cf = registry['conf']
    files = []
    for fname, content in d.get('files', []):
        data = base64.b64decode(content)
        files.append([fname, data])
    return create_doc(
            cf['username'], d['penerima'], d.get('subject'), d['pesan'],
            cf['name'], d.get('name'), files)


def save_result(d, filename):
    log = getLogger('save_result')
    result_dir = registry['conf']['result_dir']
    fullpath = os.path.join(result_dir, filename)
    with open(fullpath, 'w') as f:
        f.write(json.dumps(d))
    log.info(f'Save {fullpath}: {d}')


def save_status(status=0, jawaban='OK'):
    conf = registry['conf']
    d = dict(id=conf['username'], status=status, jawaban=jawaban)
    save_result(d, 'status.json')


def send(server):
    conf = registry['conf']
    job_dir = conf['job_dir']
    job_files = os.listdir(job_dir)
    if not job_files:
        return
    log = getLogger('send')
    job_files.sort()
    job_file = os.path.join(job_dir, job_files[0])
    result_file = os.path.split(job_file)[-1]
    d = file2dict(job_file)
    os.remove(job_file)
    result = 'id' in d and dict(id=d['id']) or dict()
    try:
        doc = dict2doc(d)
        log.info(f'Send {clean_log(d)}')
        server.sendmail(
            conf['username'], d['penerima'], doc.as_string())
        result['status'] = 0
        result['jawaban'] = 'OK'
    except Exception as e:
        result['status'] = -3
        result['jawaban'] = exception_message()
        log.error(f'Result {result}')
    save_result(result, result_file)


def get_option(argv):
    pars = ArgumentParser()
    pars.add_argument('conf')
    return pars.parse_args(argv)


def main(argv=sys.argv[1:]):
    option = get_option(argv)
    conf = ConfigParser()
    conf.read(option.conf)
    registry['conf'] = cf = dict(conf.items('main'))
    if not make_pid_file(cf['pid_file']):
        return
    setup_logging(option.conf)
    log = getLogger('main')
    cf['tls'] = cf['tls'] == 'true'
    cf['port'] = int(cf['port'])
    log.debug(f'Connect to {cf["host"]}:{cf["port"]}')
    try:
        with smtplib.SMTP(cf['host'], cf['port']) as server:
            if cf['tls']:
                server.starttls()
            log.debug(f'Login sebagai {cf["username"]}')
            server.login(cf['username'], cf['password'])
            save_status()
            while True:
                send(server)
                sleep(1)
    except ConnectionRefusedError as err:
        msg = str(err)
    except OSError as err:
        msg = str(err)
    except smtplib.SMTPAuthenticationError as err:
        msg = str(err)
    except KeyboardInterrupt:
        msg = 'Keyboard Interrupt'
    except Exception:
        msg = exception_message()
    log.error(msg)
    save_status(-2, msg)
    os.remove(cf['pid_file'])