#!/usr/bin/python3

'''sgfilter - sagator's filer daemon client

(c) 2005-2018 Jan ONDREJ (SAL) <ondrejj(at)salstar.sk>

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
'''

from __future__ import print_function

import sys, socket, getopt, shutil
from version import *

SERVER = ('127.0.0.1', 27)
mail_from = 'vscan@'+socket.gethostname()
rcpt_to = 'vscan@'+socket.gethostname()
JUST_EXIT_CODE = False
SAFE = True

try:
  opts, files = getopt.gnu_getopt(sys.argv[1:], 'h:p:cx',
    ['help', 'host=', 'port=', 'codes', 'non-safe'])
except getopt.GetoptError as err:
  (msg, opt) = err.args
  print("Error:", msg)
  sys.exit(1)

for key, value in opts:
  if key=='--help':
    print("SgFilter for SAGATOR %s-%s" % (VERSION, RELEASE))
    print("")
    print("Usage: sgfilter [options...] [filename]")
    print("")
    print("Params: --help           this help")
    print("        --host hostname  sagator's filterd() hostname")
    print("        --port X         sagator's filterd() port number")
    print("        --codes -c       exit code=1 for spam, 0 for clean or error")
    print("        --non-safe -x    disable safe fallback")
    print("        filename         filename to scan (stdin is used, when")
    print("                         no filename is defined)")
    sys.exit(0)
  elif key in ('--host', '-h'):
    SERVER = (value, SERVER[1])
  elif key in ('--port', '-p'):
    SERVER = (SERVER[0], int(value))
  elif key in ('--codes', '-c'):
    JUST_EXIT_CODE = True
  elif key in ('--non-safe', '-x'):
    SAFE = False

if files:
  f = open(files[0], 'r')
else:
  f = sys.stdin

if __name__ == '__main__':
  try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(SERVER)
    s.sendall('MAIL FROM: %s\r\n' % mail_from)
    s.sendall('RCPT TO: %s\r\n' % rcpt_to)
    # skip bad mailbox firstline
    firstline = f.readline()
    if firstline[:5]=='From ':
      data = f.read()
    else:
      data = firstline+f.read()
      firstline = ''
    s.sendall('DATA %d\r\n' % len(data))
    s.sendall(data)
    f = s.makefile('rw', 0)
    status = f.readline()
    if status[:3]=='551': # drop
      sys.exit(0) # return silently
    elif status[:3]=='550': # reject
      if JUST_EXIT_CODE:
        print(status.rstrip())
        sys.exit(1)
    elif status[0]!='2': # non clean, temp_fail or unknown
      if not SAFE:
        print(status.rstrip())
        sys.exit(64)
    # clean or SAFE or without exit code forcing
    sys.stdout.write(firstline)
    shutil.copyfileobj(f, sys.stdout, 1024*1024)
  except socket.error as err:
    print("ERROR:", err)
    sys.exit(65)
