Add responses
config option which allows customizing the response message templates
This commit is contained in:
parent
adc699aeed
commit
f9ddba422c
6 changed files with 138 additions and 86 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,5 +1,18 @@
|
|||
# EasyWKS Changelog
|
||||
|
||||
<!-- BEGIN RELEASE v0.1.5 -->
|
||||
## Version 0.1.5
|
||||
|
||||
The messages sent by EasyWKS can now be customized.
|
||||
|
||||
### Changes
|
||||
|
||||
<!-- BEGIN CHANGES 0.1.5 -->
|
||||
- Add `responses` config option.
|
||||
<!-- END CHANGES 0.1.5 -->
|
||||
|
||||
<!-- END RELEASE v0.1.5 -->
|
||||
|
||||
<!-- BEGIN RELEASE v0.1.4 -->
|
||||
## Version 0.1.4
|
||||
|
||||
|
|
26
README.md
26
README.md
|
@ -112,10 +112,34 @@ smtp:
|
|||
# Omit username/password if authentication is not needed.
|
||||
username: webkey
|
||||
password: SuperS3curePassword123
|
||||
|
||||
# Configure the LMTP server
|
||||
lmtpds:
|
||||
lmtpd:
|
||||
host: "::1"
|
||||
port: 8024
|
||||
|
||||
# You can override the mail response templates with your own text.
|
||||
# The following templates can be overridden:
|
||||
# - "header": Placed in front of every message.
|
||||
# - "footer": Appended to every message.
|
||||
# - "confirm": Sent with the confirmation request.
|
||||
# - "done": Sent after a key was published.
|
||||
# - "error": Sent when an error occurs.
|
||||
# The following placeholders can be used (enclosed in curly braces):
|
||||
# - {domain}: The email domain for with the request is processed.
|
||||
# - {sender}: The submitter's mail address.
|
||||
# - {submission}: The submission address.
|
||||
# When overriding the "error" template, theres an additional
|
||||
# placeholder you can use:
|
||||
# - {error}: The error message.
|
||||
#responses:
|
||||
# error: |
|
||||
# An error has occurred while processing your request:
|
||||
#
|
||||
# {error}
|
||||
#
|
||||
# If this error persists, please contact admin@example.org for help.
|
||||
|
||||
# Every domain served by EasyWKS must be listed here
|
||||
domains:
|
||||
example.org:
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
|
||||
__version__ = '0.1.4'
|
||||
__version__ = '0.1.5'
|
||||
|
|
|
@ -79,6 +79,58 @@ def _validate_policy_flags(value):
|
|||
return f'has invalid key {flag}'
|
||||
|
||||
|
||||
def _validate_responses(value):
|
||||
if not isinstance(value, dict):
|
||||
return f'must be a map, got {type(value)}'
|
||||
if 'header' not in value:
|
||||
value['header'] = '''Hi there!
|
||||
|
||||
This is the EasyWKS system at {domain}.
|
||||
'''
|
||||
if 'footer' not in value:
|
||||
value['footer'] = '''For more information on WKD and WKS see:
|
||||
|
||||
https://gnupg.org/faq/wkd.html
|
||||
https://gnupg.org/faq/wks.html
|
||||
|
||||
|
||||
Regards
|
||||
EasyWKS
|
||||
|
||||
--
|
||||
Dance like nobody is watching.
|
||||
Encrypt live everybody is.
|
||||
'''
|
||||
if 'confirm' not in value:
|
||||
value['confirm'] = '''You appear to have submitted your key for publication in the Web Key
|
||||
Directory. There's one more step you need to complete. If you did not
|
||||
request this, you can simply ignore this message.
|
||||
|
||||
If your email client doesn't automatically complete this challenge, you
|
||||
can perform this step manually: Please verify that you can decrypt the
|
||||
second part of this message and that the fingerprint listed in the
|
||||
encrypted part matches your key. If everything looks ok, please reply
|
||||
to this message with an **encrypted and signed PGP/MIME message** with
|
||||
the following content (without the <> brackets)
|
||||
|
||||
type: confirmation-response
|
||||
sender: <your email address>
|
||||
nonce: <copy the nonce from the encrypted part of this message>
|
||||
'''
|
||||
if 'done' not in value:
|
||||
value['done'] = '''Your key has been published to the Web Key Directory.
|
||||
You can test WKD key retrieval e.g. with:
|
||||
|
||||
gpg --auto-key-locate=wkd,nodefault --locate-key {sender}
|
||||
'''
|
||||
if 'error' not in value:
|
||||
value['error'] = '''An error has occurred while processing your request:
|
||||
|
||||
{error}
|
||||
|
||||
If this error persists, please contact your administrator for help.'''
|
||||
|
||||
|
||||
class _ConfigOption:
|
||||
|
||||
def __init__(self, key, typ, default, validator=None):
|
||||
|
@ -165,4 +217,12 @@ Config = _GlobalConfig(
|
|||
'host': 'localhost',
|
||||
'port': 25,
|
||||
}, validator=_validate_lmtpd_config),
|
||||
responses=_ConfigOption('responses', dict, {}, validator=_validate_responses),
|
||||
)
|
||||
|
||||
|
||||
def render_message(key, **kwargs):
|
||||
header = Config.responses['header'].format(**kwargs)
|
||||
content = Config.responses[key].format(**kwargs)
|
||||
footer = Config.responses['footer'].format(**kwargs)
|
||||
return f'{header}\n{content}\n{footer}'
|
||||
|
|
101
easywks/types.py
101
easywks/types.py
|
@ -10,7 +10,7 @@ from pgpy import PGPKey, PGPMessage, PGPUID
|
|||
from pgpy.types import SignatureVerification
|
||||
|
||||
from .crypto import pgp_sign
|
||||
from .config import Config
|
||||
from .config import Config, render_message
|
||||
from .util import create_nonce, fingerprint
|
||||
|
||||
|
||||
|
@ -42,39 +42,6 @@ class SubmissionRequest:
|
|||
|
||||
class ConfirmationRequest:
|
||||
|
||||
MAIL_TEXT = '''Hi there!
|
||||
|
||||
This is the EasyWKS system at {domain}.
|
||||
|
||||
You appear to have submitted your key for publication in the Web Key
|
||||
Directory. There's one more step you need to complete. If you did not
|
||||
request this, you can simply ignore this message.
|
||||
|
||||
If your email client doesn't automatically complete this challenge, you
|
||||
can perform this step manually: Please verify that you can decrypt the
|
||||
second part of this message and that the fingerprint listed in the
|
||||
encrypted part matches your key. If everything looks ok, please reply
|
||||
to this message with an **encrypted and signed PGP/MIME message** with
|
||||
the following content (without the <> brackets)
|
||||
|
||||
type: confirmation-response
|
||||
sender: <your email address>
|
||||
nonce: <copy the nonce from the encrypted part of this message>
|
||||
|
||||
For more information on WKD and WKS see:
|
||||
|
||||
https://gnupg.org/faq/wkd.html
|
||||
https://gnupg.org/faq/wks.html
|
||||
|
||||
|
||||
Regards
|
||||
EasyWKS
|
||||
|
||||
--
|
||||
Dance like nobody is watching.
|
||||
Encrypt live everybody is.
|
||||
'''
|
||||
|
||||
def __init__(self, submitter_addr: str, submission_addr: str, key: PGPKey, nonce: str = None):
|
||||
self._domain = submitter_addr.split('@')[1]
|
||||
self._submitter_addr = submitter_addr
|
||||
|
@ -103,7 +70,11 @@ Encrypt live everybody is.
|
|||
return self._nonce
|
||||
|
||||
def create_signed_message(self):
|
||||
mpplain = MIMEText(ConfirmationRequest.MAIL_TEXT.format(domain=self.domain), _subtype='plain')
|
||||
mail_text = render_message('confirm',
|
||||
domain=self.domain,
|
||||
sender=self.submitter_address,
|
||||
submission=self.submission_address)
|
||||
mpplain = MIMEText(mail_text, _subtype='plain')
|
||||
ps = '\r\n'.join([
|
||||
'type: confirmation-request',
|
||||
f'sender: {self._submission_addr}',
|
||||
|
@ -181,27 +152,6 @@ class ConfirmationResponse:
|
|||
|
||||
|
||||
class PublishResponse:
|
||||
MAIL_TEXT = '''Hi there!
|
||||
|
||||
This is the EasyWKS system at {domain}.
|
||||
|
||||
Your key has been published to the Web Key Directory.
|
||||
You can test WKD key retrieval e.g. with:
|
||||
|
||||
gpg --auto-key-locate=wkd,nodefault --locate-key {uid}
|
||||
|
||||
For more information on WKD and WKS see:
|
||||
|
||||
https://gnupg.org/faq/wkd.html
|
||||
https://gnupg.org/faq/wks.html
|
||||
|
||||
Regards
|
||||
EasyWKS
|
||||
|
||||
--
|
||||
Dance like nobody is watching.
|
||||
Encrypt live everybody is.
|
||||
'''
|
||||
|
||||
def __init__(self, submitter_addr: str, submission_addr: str, key: PGPKey):
|
||||
self._domain = submitter_addr.split('@')[1]
|
||||
|
@ -226,8 +176,11 @@ Encrypt live everybody is.
|
|||
return self._domain
|
||||
|
||||
def create_signed_message(self):
|
||||
mpplain = MIMEText(PublishResponse.MAIL_TEXT.format(domain=self.domain, uid=self.submitter_address),
|
||||
_subtype='plain')
|
||||
mail_text = render_message('done',
|
||||
domain=self.domain,
|
||||
sender=self.submitter_address,
|
||||
submission=self.submission_address)
|
||||
mpplain = MIMEText(mail_text, _subtype='plain')
|
||||
to_encrypt = PGPMessage.new(mpplain.as_string(policy=default))
|
||||
encrypted: PGPMessage = self.key.encrypt(to_encrypt)
|
||||
encrypted |= pgp_sign(self.domain, encrypted)
|
||||
|
@ -248,30 +201,6 @@ Encrypt live everybody is.
|
|||
|
||||
class EasyWksError(BaseException):
|
||||
|
||||
MAIL_TEXT = '''Hi there!
|
||||
|
||||
This is the EasyWKS system at {domain}.
|
||||
|
||||
An error has occurred while processing your request.
|
||||
|
||||
{message}
|
||||
|
||||
If this error persists, please contact your administrator for help.
|
||||
|
||||
For more information on WKD and WKS see:
|
||||
|
||||
https://gnupg.org/faq/wkd.html
|
||||
https://gnupg.org/faq/wks.html
|
||||
|
||||
|
||||
Regards
|
||||
EasyWKS
|
||||
|
||||
--
|
||||
Dance like nobody is watching.
|
||||
Encrypt live everybody is.
|
||||
'''
|
||||
|
||||
def __init__(self, msg: str, ):
|
||||
super().__init__()
|
||||
self._msg = msg
|
||||
|
@ -281,8 +210,12 @@ Encrypt live everybody is.
|
|||
|
||||
def create_message(self, submitter_addr: str, submission_addr: str) -> MIMEText:
|
||||
domain = submission_addr.split('@', 1)[1]
|
||||
payload = EasyWksError.MAIL_TEXT.format(domain=domain, message=self._msg)
|
||||
email = MIMEText(payload)
|
||||
mail_text = render_message('error',
|
||||
domain=domain,
|
||||
sender=submitter_addr,
|
||||
submission=submission_addr,
|
||||
error=self._msg)
|
||||
email = MIMEText(mail_text)
|
||||
email['Subject'] = 'An error has occurred while processing your request'
|
||||
email['From'] = submission_addr
|
||||
email['To'] = submitter_addr
|
||||
|
|
|
@ -42,6 +42,28 @@ lmtpd:
|
|||
host: "::1"
|
||||
port: 8024
|
||||
|
||||
# You can override the mail response templates with your own text.
|
||||
# The following templates can be overridden:
|
||||
# - "header": Placed in front of every message.
|
||||
# - "footer": Appended to every message.
|
||||
# - "confirm": Sent with the confirmation request.
|
||||
# - "done": Sent after a key was published.
|
||||
# - "error": Sent when an error occurs.
|
||||
# The following placeholders can be used (enclosed in curly braces):
|
||||
# - {domain}: The email domain for with the request is processed.
|
||||
# - {sender}: The submitter's mail address.
|
||||
# - {submission}: The submission address.
|
||||
# When overriding the "error" template, theres an additional
|
||||
# placeholder you can use:
|
||||
# - {error}: The error message.
|
||||
#responses:
|
||||
# error: |
|
||||
# An error has occurred while processing your request:
|
||||
#
|
||||
# {error}
|
||||
#
|
||||
# If this error persists, please contact admin@example.org for help.
|
||||
|
||||
# Every domain served by EasyWKS must be listed here
|
||||
domains:
|
||||
# Defaults are gpgwks@<domain> and no password protection.
|
||||
|
|
Loading…
Reference in a new issue