mailout - a https://caddyserver.com/ V1 SMTP client email middleware with PGP encryption
Post form data from a website to this route and receive the data as nicely
formatted email.
Supports Caddy, the web server: >= v0.9 < 2
Read more: https://cyrillschumacher.com/projects/2016-02-26-mailout-caddyserver-email-smtp/
mailout [endpoint] {
maillog [path/to/logdir|stdout|stderr]
errorlog [path/to/logdir|stdout|stderr]
to email@address1.tld
[cc "email@address2.tld, email@addressN.tld"]
[bcc "email@addressN.tld, email@addressN.tld"]
subject "Email from {{.firstname}} {{.lastname}}"
body path/to/tpl.[txt|html]
[from_email optional.senders@email.address]
[from_name "Optional Senders Name"]
[email@address1.tld path/to/pgp1.pub|ENV:MY_PGP_KEY_PATH_1|https://keybase.io/cyrill1/key.asc]
[email@address2.tld path/to/pgp2.pub|ENV:MY_PGP_KEY_PATH_2|https://keybase.io/cyrill2/key.asc]
[email@addressN.tld path/to/pgpN.pub|ENV:MY_PGP_KEY_PATH_N|https://keybase.io/cyrillN/key.asc]
username "ENV:MY_SMTP_USERNAME|gopher"
password "ENV:MY_SMTP_PASSWORD|g0ph3r"
host "ENV:MY_SMTP_HOST|smtp.gmail.com"
port ENV:MY_SMTP_PORT|25|465|587
[ratelimit_interval 24h]
[ratelimit_capacity 1000]
[skip_tls_verify]
[redirect_field "optional name of form field used for redirection url"]
[captcha]
[recaptcha]
recaptcha_secret [reCAPTCHA Secret key of your site]
}
Configuration values in brackets are optional.
endpoint
: Can be any path but your POST request must match it. Default path:/mailout
maillog
: Specify a directory, which gets created recursively, and emails willerrorlog
: Specify a directory, which gets created recursively, and errors getsto
, cc
, bcc
: Multiple email addresses must be separated by a colon and withinsubject
: Has the same functionality as the body template, but text only.body
: Text or HTML template stored on the hard disk of your server. Morefrom_email
: Email address of the sender, otherwise the email address of thefrom_name
: Name of the sender. If empty the email address in the fieldfrom_email
gets used.username
, password
, host
: Self explanatory, access credentials to the SMTPport
: Plain text on port 25, SSL uses port 465, for TLS use port 587.ratelimit_interval
: the duration in which the capacity can be consumed. Aratelimit_capacity
: the overall capacity within the interval. Default: 1000skip_tls_verify
if added skips the TLS verification process otherwiseredirect_field
: Form field name to use to configure redirection URL.The default filename for an encrypted message attached to an email is:
encrypted.gpg.
The extension .gpg
has been chosen to allow easy handling with
https://www.gnupg.org/
If you don’t like this file name you can overwrite it with the keypublickeyAttachmentFileName
.
To implement a fully working This is an OpenPGP/MIME encrypted message (RFC
4880 and 3156) PGP attachment, I need some help. It’s possible that the gomail
package needs to be refactored.
Note on sensitive information leakage when using PGP with multiple email message
receivers: For each email address in the to, cc and bcc field you must add a
public PGP key, if not, emails to recipients without a public key won’t be
encrypted. For all email addresses with a PGP key, the mailout middleware will
send a separated email encrypted with the key of the receiver.
Rate limit: Does not require external storage since it uses an algorithm called
Token Bucket (Go library:
juju/ratelimit).
Note: Current architecture of the mailout pluging allows to set only one
endpoint and its configuration per virtual host. If you need more endpoints,
for different email receivers, you must create additional virtual hosts in
*Caddy.
Server response on success (Status 200 OK):
{"code":200}
Server response on error (Status 422 Unprocessable Entity):
{"code":422,"error":"Invalid email address: \"doe.john40nonexistantServer.email\""}
Server response on non-POST requests (Status 405 Method Not Allowed):
{"code":405,"error":"Method Not Allowed"}
Server response on form parse error (Status 400 Bad Request):
{"code":400,"error":"Bad request"}
Server response on reaching the rate limit (Status 429 Too Many Requests):
{"code":429,"error":"Too Many Requests"}
Server response on internal errors:
500 Internal Server Error
Example:
add to config: captcha
<div class="form-group text-center">
<img id="captcha" src="/mailout/captcha">
<input type="text" id="captcha_text" name="captcha_text" class="form-control" placeholder="Captcha text" required>
</div>
After sending the request:
var d = new Date();
$("#captcha").attr("src", "/mailout/captcha?" + d.getTime());
https://github.com/steambap/captcha
https://github.com/quasoft/memstore
Example:
add to config: recaptcha and recaptcha_secret
recaptcha
recaptcha_secret 6LdnR1QUAAAAAIdxxxxxxxxxxxxx
The rendering engine for the email templates depends on the suffix of the
template file name.
.txt
: Plain text template language.html
: HTML template languageCreate a simple HTML form with some JavaScript and AJAX functions.
Mandatory input field is email
. Optional recommended field: name
. Those two
fields will be later joined to create the From:
header of an email.
The following snipped has been extracted from a Hugo
template.
```html