aboutsummaryrefslogtreecommitdiff
path: root/services/docker/mail-server
diff options
context:
space:
mode:
Diffstat (limited to 'services/docker/mail-server')
-rw-r--r--services/docker/mail-server/Dockerfile11
-rwxr-xr-xservices/docker/mail-server/app/main.bash11
-rw-r--r--services/docker/mail-server/aws-lambda.js23
-rw-r--r--services/docker/mail-server/dovecot.conf197
4 files changed, 242 insertions, 0 deletions
diff --git a/services/docker/mail-server/Dockerfile b/services/docker/mail-server/Dockerfile
new file mode 100644
index 0000000..7a3be9a
--- /dev/null
+++ b/services/docker/mail-server/Dockerfile
@@ -0,0 +1,11 @@
+FROM denoland/deno AS deno-build
+COPY --from=deno . /workdir/
+WORKDIR /workdir
+RUN deno install
+RUN deno task compile:mail-relay
+
+FROM dovecot/dovecot:latest-root
+COPY --from=deno-build /workdir/mail-relay/out/crupest-relay /app/
+ADD dovecot.conf /etc/dovecot/dovecot.conf
+ADD app/* /app/
+CMD ["/app/main.bash"]
diff --git a/services/docker/mail-server/app/main.bash b/services/docker/mail-server/app/main.bash
new file mode 100755
index 0000000..70c9b75
--- /dev/null
+++ b/services/docker/mail-server/app/main.bash
@@ -0,0 +1,11 @@
+#!/usr/bin/bash
+
+set -e -o pipefail
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+/app/crupest-relay serve --real &
+/dovecot/sbin/dovecot -F
diff --git a/services/docker/mail-server/aws-lambda.js b/services/docker/mail-server/aws-lambda.js
new file mode 100644
index 0000000..d240c1a
--- /dev/null
+++ b/services/docker/mail-server/aws-lambda.js
@@ -0,0 +1,23 @@
+export const handler = async (event, context, callback) => {
+ const sesNotification = event.Records[0].ses;
+ console.log("SES Notification:\n", JSON.stringify(sesNotification, null, 2));
+
+ const res = await fetch(
+ `https://mail.crupest.life/${process.env.CRUPEST_MAIL_SERVER_AWS_INBOUND_PATH}`,
+ {
+ method: "POST",
+ headers: {
+ "content-type": "application/json",
+ "Authorization": process.env.CRUPEST_MAIL_SERVER_AWS_INBOUND_KEY,
+ },
+ body: JSON.stringify({
+ key: sesNotification.mail.messageId,
+ recipients: sesNotification.receipt.recipients,
+ }),
+ },
+ );
+ console.log(res);
+ console.log(res.text());
+
+ callback(null, { "disposition": "CONTINUE" });
+};
diff --git a/services/docker/mail-server/dovecot.conf b/services/docker/mail-server/dovecot.conf
new file mode 100644
index 0000000..5d2eaf4
--- /dev/null
+++ b/services/docker/mail-server/dovecot.conf
@@ -0,0 +1,197 @@
+dovecot_config_version = 2.4.1
+dovecot_storage_version = 2.4.0
+
+base_dir = /run/dovecot
+state_dir = /run/dovecot
+log_path = /dev/stdout
+
+protocols = imap submission lmtp sieve
+sendmail_path = /app/out/crupest-relay sendmail
+submission_relay_host = 127.0.0.1
+submission_relay_port = 2346
+submission_relay_trusted = yes
+
+mail_driver = maildir
+mail_home = /data/vmail/%{user | domain}/%{user | username}
+mail_path = ~/mail
+mail_log_events = delete undelete expunge save copy mailbox_create mailbox_delete mailbox_rename flag_change
+
+# Setup default mailboxes for inbox namespace
+@mailbox_defaults = english
+
+namespace inbox {
+ mailbox Archive {
+ special_use = "\\Archive"
+ }
+}
+
+mail_plugins {
+ fts = yes
+ fts_flatcurve = yes
+ mail_log = yes
+ notify = yes
+}
+
+fts_autoindex = yes
+fts_autoindex_max_recent_msgs = 999
+fts_search_add_missing = yes
+language_filters = normalizer-icu snowball stopwords
+
+language_tokenizers = generic email-address
+language_tokenizer_generic_algorithm = simple
+
+language en {
+ default = yes
+ filters = lowercase snowball english-possessive stopwords
+}
+
+fts flatcurve {
+ substring_search = yes
+}
+
+auth_mechanisms = plain login
+
+passdb passwd-file {
+ passwd_file_path = /data/userdb
+ default_password_scheme = SHA512-CRYPT
+}
+
+userdb passwd-file {
+ passwd_file_path = /data/userdb
+ fields {
+ uid:default = vmail
+ gid:default = vmail
+ home:default = /data/vmail/%{user | domain}/%{user | username}
+ }
+}
+
+ssl = yes
+ssl_server {
+ cert_file = /etc/dovecot/ssl/tls.crt
+ key_file = /etc/dovecot/ssl/tls.key
+}
+
+protocol imap {
+ mail_plugins {
+ imap_sieve = yes
+ imap_filter_sieve = yes
+ }
+}
+
+protocol lmtp {
+ mail_plugins {
+ sieve = yes
+ }
+}
+
+protocol lda {
+ mail_plugins {
+ sieve = yes
+ }
+}
+
+service imap-login {
+ process_min_avail = 1
+ client_limit = 100
+}
+
+service pop3-login {
+ process_min_avail = 1
+ client_limit = 100
+}
+
+service submission-login {
+ process_min_avail = 1
+ client_limit = 100
+
+ inet_listener submissions {
+ port = 465
+ ssl = yes
+ }
+}
+
+service managesieve-login {
+ process_min_avail = 1
+ client_limit = 100
+}
+
+sieve_plugins = sieve_imapsieve sieve_extprograms
+
+event_exporter log {
+ format = json
+ time_format = rfc3339
+}
+
+# Add default backend metrics
+@metric_defaults = backend
+
+# Log auth failures
+metric auth_failures {
+ filter = event=auth_request_finished AND NOT success=yes
+ exporter = log
+}
+
+metric imap_command {
+ filter = event=imap_command_finished
+ group_by cmd_name {
+ method discrete {
+ }
+ }
+ group_by tagged_reply_state {
+ method discrete {
+ }
+ }
+}
+
+metric smtp_command {
+ filter = event=smtp_server_command_finished and protocol=submission
+ group_by cmd_name {
+ method discrete {
+ }
+ }
+ group_by status_code {
+ method discrete {
+ }
+ }
+ group_by duration {
+ method exponential {
+ base = 10
+ min_magnitude = 1
+ max_magnitude = 5
+ }
+ }
+}
+
+metric lmtp_command {
+ filter = event=smtp_server_command_finished and protocol=lmtp
+ group_by cmd_name {
+ method discrete {
+ }
+ }
+ group_by status_code {
+ method discrete {
+ }
+ }
+ group_by duration {
+ method exponential {
+ base = 10
+ min_magnitude = 1
+ max_magnitude = 5
+ }
+ }
+}
+
+# Add duration metrics for deliveries
+metric mail_deliveries {
+ filter = event=mail_delivery_finished
+ group_by duration {
+ method exponential {
+ base = 10
+ min_magnitude = 1
+ max_magnitude = 5
+ }
+ }
+}
+
+!include_try vendor.d/*.conf
+!include_try conf.d/*.conf