mailer.py 3.62 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, job_files):
    conf = registry['conf']
    job_dir = conf['job_dir']
    log = getLogger('send')
    job_files.sort()
    for job_file in job_files:
        result_file = job_file
        job_file = os.path.join(conf['job_dir'], job_file)
        d = file2dict(job_file)
        os.remove(job_file)
        result = 'id' in d and dict(id=d['id']) or dict()
        err = None
        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 smtplib.SMTPSenderRefused as err:
            msg = str(err)
        except smtplib.SMTPServerDisconnected as err:
            msg = str(err)
        except Exception as err:
            msg = exception_message()
        if err:
            result['status'] = -3
            result['jawaban'] = msg
            log.error(f'Result {result}')
        save_result(result, result_file)
        if err:
            return


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'])
    first = True
    try:
        while True:
            job_files = os.listdir(cf['job_dir'])
            if first or job_files:
                log.debug(f'Connect to {cf["host"]}:{cf["port"]}')
                with smtplib.SMTP_SSL(cf['host'], cf['port']) as server:
                    if cf['tls']:
                        server.starttls()
                    log.debug(f'Login sebagai {cf["username"]}')
                    server.login(cf['username'], cf['password'])
                    first and save_status()
                    send(server, job_files)
                first = False
            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'])