mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/tglx/remail.git
synced 2024-12-26 04:20:55 +01:00
remail: Add remail_pipe script
Add a handle pipe function to the remailer and a pipe script for handling mail in a MTA delivery path. Requested-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
266221e151
commit
323b8cda64
6 changed files with 171 additions and 22 deletions
|
@ -70,6 +70,7 @@ Usage guidelines (man pages)
|
|||
:maxdepth: 3
|
||||
|
||||
man1/remail_daemon.rst
|
||||
man1/remail_pipe.rst
|
||||
man1/remail_chkcfg.rst
|
||||
man5/remail.config.rst
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ Description
|
|||
-----------
|
||||
|
||||
:program:`remail_daemon`, The daemon for running an encrypted mailing
|
||||
list. It reads the configuration file from the command line.
|
||||
list. The configuration file name is handed in as command line argument.
|
||||
|
||||
|
||||
Options
|
||||
|
@ -36,8 +36,8 @@ Options
|
|||
Configuration file
|
||||
------------------
|
||||
|
||||
remail_daemon reads the configuration file which was handed in on the
|
||||
command line. The configuration file is a simple yaml file. Non-mandatory
|
||||
remail_daemon reads the configuration file which was handed in as command
|
||||
line argument. The configuration file is a simple yaml file. Non-mandatory
|
||||
configuration options which are not in the configuration file are set to
|
||||
the default values.
|
||||
|
||||
|
|
74
Documentation/man1/remail_pipe.rst
Normal file
74
Documentation/man1/remail_pipe.rst
Normal file
|
@ -0,0 +1,74 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. _remail_pipe_man:
|
||||
|
||||
remail_pipe manual page
|
||||
=========================
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**remail_pipe** [*options*] config_file
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
:program:`remail_pipe`, The pipe script for decrypting incoming mail and
|
||||
sending it re-encrypted to the subscribers of an encrypted mailing
|
||||
list. The incoming mail is read from stdin.
|
||||
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
-h, --help
|
||||
Show this help message and exit
|
||||
|
||||
-s syslog, --syslog
|
||||
Use syslog for logging. Default is stderr
|
||||
|
||||
-v, --verbose
|
||||
Enable verbose logging.
|
||||
|
||||
-V, --version
|
||||
Display version information
|
||||
|
||||
|
||||
Configuration file
|
||||
------------------
|
||||
|
||||
remail_pipe reads the configuration file which was handed in as command
|
||||
line argument. The configuration file is a simple yaml file. Non-mandatory
|
||||
configuration options which are not in the configuration file are set to
|
||||
the default values.
|
||||
|
||||
See the configuration file man page for detailed information.
|
||||
|
||||
|
||||
Work directory
|
||||
--------------
|
||||
|
||||
remail pipe assumes that the configuration file is in the work directory
|
||||
which has a defined layout and content. The directory structure is
|
||||
documented in the full remail documentation along with hints how to manage
|
||||
encrypted mailing lists.
|
||||
|
||||
Exit codes
|
||||
----------
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - 0
|
||||
- Mail was successfully delivered
|
||||
* - 1
|
||||
- No enabled mailinglist found for delivery
|
||||
* - 2
|
||||
- Mail processing incomplete. See log output
|
||||
* - 11
|
||||
- Configuration error
|
||||
* - 12
|
||||
- Fatal exception
|
||||
|
||||
See also
|
||||
--------
|
||||
:manpage:`remail.config(5)`
|
|
@ -38,7 +38,7 @@ Configuration directory structure
|
|||
|
||||
The configuration directory structure is fixed and looks like this::
|
||||
|
||||
├── .certs
|
||||
├── .certs
|
||||
│ ├── cacert.pem
|
||||
│ ├── list1@your.domain.key
|
||||
│ ├── list2@your.domain.key
|
||||
|
@ -427,4 +427,5 @@ See also
|
|||
--------
|
||||
:manpage:`remail_daemon(1)`
|
||||
:manpage:`remail_chkcfg(1)`
|
||||
:manpage:`remail_pipe(1)`
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from remail.config import RemailConfigException
|
|||
from remail.config import main_config
|
||||
from remail.maillist import maillist
|
||||
|
||||
from email import message_from_binary_file
|
||||
from email import message_from_binary_file, message_from_file
|
||||
from email.policy import EmailPolicy
|
||||
from ruamel.yaml import YAML
|
||||
import pyinotify
|
||||
|
@ -15,6 +15,7 @@ import mailbox
|
|||
import pathlib
|
||||
import signal
|
||||
import fcntl
|
||||
import sys
|
||||
import os
|
||||
|
||||
class EventHandler(pyinotify.ProcessEvent):
|
||||
|
@ -173,6 +174,25 @@ class remaild(object):
|
|||
except:
|
||||
pass
|
||||
|
||||
|
||||
def process_msg(self, msg):
|
||||
# Check whether one of the lists will take it
|
||||
for ml in self.mailinglists:
|
||||
if not ml.enabled:
|
||||
continue
|
||||
dest = ml.get_destination(msg)
|
||||
if not dest:
|
||||
continue
|
||||
try:
|
||||
if ml.process_mail(msg, dest):
|
||||
return 0
|
||||
return 2
|
||||
except Exception as ex:
|
||||
txt = 'Failed to process mail file %s\n' %(mailfile)
|
||||
self.logger.log_exception(txt, ex)
|
||||
break
|
||||
return 1
|
||||
|
||||
# The actual mail processing
|
||||
def process_mail(self, queue):
|
||||
'''
|
||||
|
@ -193,24 +213,9 @@ class remaild(object):
|
|||
self.logger.log_exception(txt, ex)
|
||||
continue
|
||||
|
||||
# Check whether one of the lists will take it
|
||||
processed = False
|
||||
for ml in self.mailinglists:
|
||||
if not ml.enabled:
|
||||
continue
|
||||
dest = ml.get_destination(msg)
|
||||
if not dest:
|
||||
continue
|
||||
try:
|
||||
processed = ml.process_mail(msg, dest)
|
||||
break
|
||||
except Exception as ex:
|
||||
self.failedmails.append(mailfile)
|
||||
txt = 'Failed to process mail file %s\n' %(mailfile)
|
||||
self.logger.log_exception(txt, ex)
|
||||
break
|
||||
res = self.process_msg(msg)
|
||||
|
||||
if processed:
|
||||
if res == 0:
|
||||
os.unlink(mailfile)
|
||||
else:
|
||||
self.move_frozen(mailfile)
|
||||
|
@ -360,6 +365,17 @@ class remaild(object):
|
|||
|
||||
return self.should_stop()
|
||||
|
||||
# The pipe handling interface
|
||||
def handle_pipe(self):
|
||||
self._should_reload = True
|
||||
self.reconfigure()
|
||||
|
||||
if not self.enabled:
|
||||
return 1
|
||||
|
||||
msg = message_from_file(sys.stdin)
|
||||
return self.process_msg(msg)
|
||||
|
||||
# The runner
|
||||
def run(self):
|
||||
|
||||
|
|
57
remail_pipe
Executable file
57
remail_pipe
Executable file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright Thomas Gleixner <tglx@linutronix.de>
|
||||
#
|
||||
|
||||
from remail.utils import logger
|
||||
from remail.version import __version__
|
||||
from remail.remaild import remaild
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
def exit_daemon(logger, res):
|
||||
logger.log('Stopped\n')
|
||||
sys.exit(res)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = ArgumentParser(description='remail pipe')
|
||||
parser.add_argument('config', help='Config file')
|
||||
parser.add_argument('--syslog', '-s', dest='syslog', action='store_true',
|
||||
help='Use syslog for logging. Default is stderr')
|
||||
parser.add_argument('--verbose', '-v', dest='verbose', action='store_true',
|
||||
help='Verbose logging')
|
||||
parser.add_argument('--version', '-V', action='version',
|
||||
version='%(prog)s {version}'.format(version=__version__))
|
||||
args = parser.parse_args()
|
||||
|
||||
logger = logger(use_syslog=args.syslog, verbose=args.verbose)
|
||||
logger.log("Started\n")
|
||||
|
||||
# Change into the directory in which the config file resides
|
||||
wdir = os.path.dirname(args.config)
|
||||
if len(wdir):
|
||||
os.chdir(wdir)
|
||||
args.config = os.path.basename(args.config)
|
||||
|
||||
try:
|
||||
rd = remaild(args.config, logger)
|
||||
except Exception as ex:
|
||||
'''
|
||||
Exceptions which reach here are fatal
|
||||
'''
|
||||
logger.log_exception('', ex, verbose=True)
|
||||
exit_daemon(logger, 11)
|
||||
|
||||
try:
|
||||
res = rd.handle_pipe()
|
||||
except Exception as ex:
|
||||
'''
|
||||
Exceptions which reach here are fatal
|
||||
'''
|
||||
logger.log_exception('', ex, verbose=True)
|
||||
res = 12
|
||||
|
||||
exit_daemon(logger, res)
|
Loading…
Reference in a new issue