mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/tglx/remail.git
synced 2024-11-09 14:02:38 +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
|
:maxdepth: 3
|
||||||
|
|
||||||
man1/remail_daemon.rst
|
man1/remail_daemon.rst
|
||||||
|
man1/remail_pipe.rst
|
||||||
man1/remail_chkcfg.rst
|
man1/remail_chkcfg.rst
|
||||||
man5/remail.config.rst
|
man5/remail.config.rst
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
:program:`remail_daemon`, The daemon for running an encrypted mailing
|
: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
|
Options
|
||||||
|
@ -36,8 +36,8 @@ Options
|
||||||
Configuration file
|
Configuration file
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
remail_daemon reads the configuration file which was handed in on the
|
remail_daemon reads the configuration file which was handed in as command
|
||||||
command line. The configuration file is a simple yaml file. Non-mandatory
|
line argument. The configuration file is a simple yaml file. Non-mandatory
|
||||||
configuration options which are not in the configuration file are set to
|
configuration options which are not in the configuration file are set to
|
||||||
the default values.
|
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::
|
The configuration directory structure is fixed and looks like this::
|
||||||
|
|
||||||
├── .certs
|
├── .certs
|
||||||
│ ├── cacert.pem
|
│ ├── cacert.pem
|
||||||
│ ├── list1@your.domain.key
|
│ ├── list1@your.domain.key
|
||||||
│ ├── list2@your.domain.key
|
│ ├── list2@your.domain.key
|
||||||
|
@ -427,4 +427,5 @@ See also
|
||||||
--------
|
--------
|
||||||
:manpage:`remail_daemon(1)`
|
:manpage:`remail_daemon(1)`
|
||||||
:manpage:`remail_chkcfg(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.config import main_config
|
||||||
from remail.maillist import maillist
|
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 email.policy import EmailPolicy
|
||||||
from ruamel.yaml import YAML
|
from ruamel.yaml import YAML
|
||||||
import pyinotify
|
import pyinotify
|
||||||
|
@ -15,6 +15,7 @@ import mailbox
|
||||||
import pathlib
|
import pathlib
|
||||||
import signal
|
import signal
|
||||||
import fcntl
|
import fcntl
|
||||||
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class EventHandler(pyinotify.ProcessEvent):
|
class EventHandler(pyinotify.ProcessEvent):
|
||||||
|
@ -173,6 +174,25 @@ class remaild(object):
|
||||||
except:
|
except:
|
||||||
pass
|
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
|
# The actual mail processing
|
||||||
def process_mail(self, queue):
|
def process_mail(self, queue):
|
||||||
'''
|
'''
|
||||||
|
@ -193,24 +213,9 @@ class remaild(object):
|
||||||
self.logger.log_exception(txt, ex)
|
self.logger.log_exception(txt, ex)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check whether one of the lists will take it
|
res = self.process_msg(msg)
|
||||||
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
|
|
||||||
|
|
||||||
if processed:
|
if res == 0:
|
||||||
os.unlink(mailfile)
|
os.unlink(mailfile)
|
||||||
else:
|
else:
|
||||||
self.move_frozen(mailfile)
|
self.move_frozen(mailfile)
|
||||||
|
@ -360,6 +365,17 @@ class remaild(object):
|
||||||
|
|
||||||
return self.should_stop()
|
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
|
# The runner
|
||||||
def run(self):
|
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