simplify helpers for sending massively
This commit is contained in:
parent
730f5249bd
commit
c78b6d1847
|
@ -7,103 +7,19 @@
|
||||||
# ! ATTENTION: This file is loaded by `common.sh` - do not load it yourself!
|
# ! ATTENTION: This file is loaded by `common.sh` - do not load it yourself!
|
||||||
# ! ATTENTION: This file requires helper functions from `common.sh`!
|
# ! ATTENTION: This file requires helper functions from `common.sh`!
|
||||||
|
|
||||||
# Parse the arguments given to `_send_email` and `_send_email_unchecked`.
|
# Sends an e-mail from the container named by the environment variable `CONTAINER_NAME`
|
||||||
# Outputs the `swaks` command to later be executed by the calling function.
|
|
||||||
#
|
|
||||||
# ## Note
|
|
||||||
#
|
|
||||||
# This is an internal support function, it should not be used directly by tests.
|
|
||||||
function __parse_swaks_arguments() {
|
|
||||||
[[ -v CONTAINER_NAME ]] || return 1
|
|
||||||
|
|
||||||
# Parameter defaults common to our testing needs:
|
|
||||||
local EHLO='mail.external.tld'
|
|
||||||
local FROM='user@external.tld'
|
|
||||||
local TO='user1@localhost.localdomain'
|
|
||||||
local SERVER='0.0.0.0'
|
|
||||||
local PORT=25
|
|
||||||
# Extra options for `swaks` that aren't covered by the default options above:
|
|
||||||
local ADDITIONAL_SWAKS_OPTIONS=()
|
|
||||||
local DATA_WAS_SUPPLIED=0
|
|
||||||
|
|
||||||
while [[ ${#} -gt 0 ]]; do
|
|
||||||
case "${1}" in
|
|
||||||
( '--ehlo' ) EHLO=${2:?--ehlo given but no argument} ; shift 2 ;;
|
|
||||||
( '--from' ) FROM=${2:?--from given but no argument} ; shift 2 ;;
|
|
||||||
( '--to' ) TO=${2:?--to given but no argument} ; shift 2 ;;
|
|
||||||
( '--server' ) SERVER=${2:?--server given but no argument} ; shift 2 ;;
|
|
||||||
( '--port' ) PORT=${2:?--port given but no argument} ; shift 2 ;;
|
|
||||||
( '--data' )
|
|
||||||
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
|
||||||
local FILE_PATH="/tmp/docker-mailserver-test/emails/${2:?--data given but no argument provided}"
|
|
||||||
if _exec_in_container_bash "[[ -e ${FILE_PATH} ]]"; then
|
|
||||||
ADDITIONAL_SWAKS_OPTIONS+=("@${FILE_PATH}")
|
|
||||||
else
|
|
||||||
ADDITIONAL_SWAKS_OPTIONS+=("'${2}'")
|
|
||||||
fi
|
|
||||||
shift 2
|
|
||||||
DATA_WAS_SUPPLIED=1
|
|
||||||
;;
|
|
||||||
( * ) ADDITIONAL_SWAKS_OPTIONS+=("'${1}'") ; shift 1 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ${DATA_WAS_SUPPLIED} -eq 0 ]]; then
|
|
||||||
# Fallback template (without the implicit `Message-Id` + `X-Mailer` headers from swaks):
|
|
||||||
# NOTE: It is better to let Postfix generate and append the `Message-Id` header itself,
|
|
||||||
# as it will contain the Queue ID for tracking in logs (which is also returned in swaks output).
|
|
||||||
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
|
||||||
ADDITIONAL_SWAKS_OPTIONS+=("'Date: %DATE%\nTo: %TO_ADDRESS%\nFrom: %FROM_ADDRESS%\nSubject: test %DATE%\n%NEW_HEADERS%\n%BODY%\n'")
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "swaks --server '${SERVER}' --port '${PORT}' --ehlo '${EHLO}' --from '${FROM}' --to '${TO}' ${ADDITIONAL_SWAKS_OPTIONS[*]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sends a mail from the container named by the environment variable `CONTAINER_NAME`
|
|
||||||
# to the same or another container.
|
# to the same or another container.
|
||||||
#
|
#
|
||||||
# To send a custom email:
|
# To send a custom email, you can
|
||||||
# 1. Create a file at `test/files/<TEST FILE>`
|
|
||||||
# 2. Provide `<TEST FILE>` as an argument to this function.
|
|
||||||
#
|
#
|
||||||
# Parameters include all options that one can supply to `swaks` itself.
|
# 1. create a file at `test/files/<TEST FILE>` and provide `<TEST FILE>` via `--data` as an argument to this function;
|
||||||
# The `--data` parameter expects a value of either:
|
# 2. use this function without the `--data` argument, in which case we provide a default;
|
||||||
# - A relative path from `test/files/emails/`
|
# 3. provide data inline (`--data <INLINE DATA>`).
|
||||||
# - An "inline" data string (e.g., `Date: 1 Jan 2024\nSubject: This is a test`)
|
|
||||||
#
|
#
|
||||||
# ## Output
|
# The very first parameter **may** be `--expect-rejection` - use it of you expect the mail transaction to not finish
|
||||||
|
# successfully. All other (following) parameters include all options that one can supply to `swaks` itself.
|
||||||
|
# As mentioned before, the `--data` parameter expects a value of either:
|
||||||
#
|
#
|
||||||
# This functions prints the output of the transaction that `swaks` prints.
|
|
||||||
#
|
|
||||||
# ## Attention
|
|
||||||
#
|
|
||||||
# This function assumes `CONTAINER_NAME` to be properly set (to the container
|
|
||||||
# name the command should be executed in)!
|
|
||||||
#
|
|
||||||
# This function will send the email in an "asynchronous" fashion,
|
|
||||||
# it will return without waiting for the Postfix mail queue to be emptied.
|
|
||||||
#
|
|
||||||
# This functions performs **no** implicit `assert_success` to check whether the
|
|
||||||
# e-mail transaction was successful. If this is not desirable, use `_send_email`.
|
|
||||||
# If you anticipate the sending to succeed, use `_send_email` instead.
|
|
||||||
function _send_email_unchecked() {
|
|
||||||
local COMMAND_STRING=$(__parse_swaks_arguments "${@}")
|
|
||||||
_run_in_container_bash "${COMMAND_STRING}"
|
|
||||||
local RETURN_VALUE=${?}
|
|
||||||
# shellcheck disable=SC2154
|
|
||||||
echo "${output}"
|
|
||||||
return "${RETURN_VALUE}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sends a mail from the container named by the environment variable `CONTAINER_NAME`
|
|
||||||
# to the same or another container.
|
|
||||||
#
|
|
||||||
# To send a custom email:
|
|
||||||
# 1. Create a file at `test/files/<TEST FILE>`
|
|
||||||
# 2. Provide `<TEST FILE>` as an argument to this function.
|
|
||||||
#
|
|
||||||
# Parameters include all options that one can supply to `swaks` itself.
|
|
||||||
# The `--data` parameter expects a value of either:
|
|
||||||
# - A relative path from `test/files/emails/`
|
# - A relative path from `test/files/emails/`
|
||||||
# - An "inline" data string (e.g., `Date: 1 Jan 2024\nSubject: This is a test`)
|
# - An "inline" data string (e.g., `Date: 1 Jan 2024\nSubject: This is a test`)
|
||||||
#
|
#
|
||||||
|
@ -119,11 +35,69 @@ function _send_email_unchecked() {
|
||||||
# This function will send the email in an "asynchronous" fashion,
|
# This function will send the email in an "asynchronous" fashion,
|
||||||
# it will return without waiting for the Postfix mail queue to be emptied.
|
# it will return without waiting for the Postfix mail queue to be emptied.
|
||||||
function _send_email() {
|
function _send_email() {
|
||||||
local COMMAND_STRING=$(__parse_swaks_arguments "${@}")
|
local RETURN_VALUE=0
|
||||||
_run_in_container_bash "${COMMAND_STRING}"
|
local COMMAND_STRING
|
||||||
assert_success
|
|
||||||
|
function __parse_arguments() {
|
||||||
|
[[ -v CONTAINER_NAME ]] || return 1
|
||||||
|
|
||||||
|
# Parameter defaults common to our testing needs:
|
||||||
|
local EHLO='mail.external.tld'
|
||||||
|
local FROM='user@external.tld'
|
||||||
|
local TO='user1@localhost.localdomain'
|
||||||
|
local SERVER='0.0.0.0'
|
||||||
|
local PORT=25
|
||||||
|
# Extra options for `swaks` that aren't covered by the default options above:
|
||||||
|
local ADDITIONAL_SWAKS_OPTIONS=()
|
||||||
|
local DATA_WAS_SUPPLIED=0
|
||||||
|
|
||||||
|
while [[ ${#} -gt 0 ]]; do
|
||||||
|
case "${1}" in
|
||||||
|
( '--ehlo' ) EHLO=${2:?--ehlo given but no argument} ; shift 2 ;;
|
||||||
|
( '--from' ) FROM=${2:?--from given but no argument} ; shift 2 ;;
|
||||||
|
( '--to' ) TO=${2:?--to given but no argument} ; shift 2 ;;
|
||||||
|
( '--server' ) SERVER=${2:?--server given but no argument} ; shift 2 ;;
|
||||||
|
( '--port' ) PORT=${2:?--port given but no argument} ; shift 2 ;;
|
||||||
|
( '--data' )
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
||||||
|
local FILE_PATH="/tmp/docker-mailserver-test/emails/${2:?--data given but no argument provided}"
|
||||||
|
if _exec_in_container_bash "[[ -e ${FILE_PATH} ]]"; then
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("@${FILE_PATH}")
|
||||||
|
else
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("'${2}'")
|
||||||
|
fi
|
||||||
|
shift 2
|
||||||
|
DATA_WAS_SUPPLIED=1
|
||||||
|
;;
|
||||||
|
( * ) ADDITIONAL_SWAKS_OPTIONS+=("'${1}'") ; shift 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${DATA_WAS_SUPPLIED} -eq 0 ]]; then
|
||||||
|
# Fallback template (without the implicit `Message-Id` + `X-Mailer` headers from swaks):
|
||||||
|
# NOTE: It is better to let Postfix generate and append the `Message-Id` header itself,
|
||||||
|
# as it will contain the Queue ID for tracking in logs (which is also returned in swaks output).
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=('--data')
|
||||||
|
ADDITIONAL_SWAKS_OPTIONS+=("'Date: %DATE%\nTo: %TO_ADDRESS%\nFrom: %FROM_ADDRESS%\nSubject: test %DATE%\n%NEW_HEADERS%\n%BODY%\n'")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "swaks --server '${SERVER}' --port '${PORT}' --ehlo '${EHLO}' --from '${FROM}' --to '${TO}' ${ADDITIONAL_SWAKS_OPTIONS[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${1:-} == --expect-rejection ]]; then
|
||||||
|
shift 1
|
||||||
|
COMMAND_STRING=$(__parse_arguments "${@}")
|
||||||
|
_run_in_container_bash "${COMMAND_STRING}"
|
||||||
|
assert_success
|
||||||
|
else
|
||||||
|
COMMAND_STRING=$(__parse_arguments "${@}")
|
||||||
|
_run_in_container_bash "${COMMAND_STRING}"
|
||||||
|
RETURN_VALUE=${?}
|
||||||
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2154
|
# shellcheck disable=SC2154
|
||||||
echo "${output}"
|
echo "${output}"
|
||||||
|
return "${RETURN_VALUE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Like `_send_email` with two major differences:
|
# Like `_send_email` with two major differences:
|
||||||
|
@ -172,9 +146,9 @@ function _send_email_and_get_id() {
|
||||||
local MESSAGE_ID_REGEX="[0-9]{14}\\.${QUEUE_ID_REGEX}"
|
local MESSAGE_ID_REGEX="[0-9]{14}\\.${QUEUE_ID_REGEX}"
|
||||||
|
|
||||||
_wait_for_empty_mail_queue_in_container
|
_wait_for_empty_mail_queue_in_container
|
||||||
if [[ ${1} == --expect-rejection ]]; then
|
local OUTPUT=$(_send_email "${@}")
|
||||||
shift 1
|
|
||||||
local OUTPUT=$(_send_email_unchecked "${@}")
|
if [[ ${1:-} == --expect-rejection ]]; then
|
||||||
# Because we expect the mail to be rejected, we have to query the mail log
|
# Because we expect the mail to be rejected, we have to query the mail log
|
||||||
# instead of `swaks`, because `swaks` cannot provide us with a queue ID when
|
# instead of `swaks`, because `swaks` cannot provide us with a queue ID when
|
||||||
# mail is rejected (we see something like this instead: `<** 554 5.7.1 Gtube pattern`).
|
# mail is rejected (we see something like this instead: `<** 554 5.7.1 Gtube pattern`).
|
||||||
|
@ -182,7 +156,6 @@ function _send_email_and_get_id() {
|
||||||
| grep -E "postfix/smtpd.*: ${QUEUE_ID_REGEX}: client=" \
|
| grep -E "postfix/smtpd.*: ${QUEUE_ID_REGEX}: client=" \
|
||||||
| grep -E -m 1 -o '[A-Z0-9]{9,12}' || :)
|
| grep -E -m 1 -o '[A-Z0-9]{9,12}' || :)
|
||||||
else
|
else
|
||||||
local OUTPUT=$(_send_email "${@}")
|
|
||||||
# When mail is expected to be delivered, we can use the output of `swaks`
|
# When mail is expected to be delivered, we can use the output of `swaks`
|
||||||
# to easily query the queue ID.
|
# to easily query the queue ID.
|
||||||
QUEUE_ID=$(grep -F 'queued as' <<< "${OUTPUT}" | grep -E -o "${QUEUE_ID_REGEX}$")
|
QUEUE_ID=$(grep -F 'queued as' <<< "${OUTPUT}" | grep -E -o "${QUEUE_ID_REGEX}$")
|
||||||
|
|
|
@ -74,7 +74,7 @@ function teardown_file() {
|
||||||
CONTAINER1_IP=$(_get_container_ip "${CONTAINER1_NAME}")
|
CONTAINER1_IP=$(_get_container_ip "${CONTAINER1_NAME}")
|
||||||
# Trigger a ban by failing to login twice:
|
# Trigger a ban by failing to login twice:
|
||||||
for _ in {1..2}; do
|
for _ in {1..2}; do
|
||||||
CONTAINER_NAME=${CONTAINER2_NAME} _send_email_unchecked \
|
CONTAINER_NAME=${CONTAINER2_NAME} _send_email --expect-rejection \
|
||||||
--server "${CONTAINER1_IP}" \
|
--server "${CONTAINER1_IP}" \
|
||||||
--port 465 \
|
--port 465 \
|
||||||
--auth PLAIN \
|
--auth PLAIN \
|
||||||
|
|
|
@ -51,7 +51,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
_reload_postfix
|
_reload_postfix
|
||||||
|
|
||||||
# Send test mail (it should fail to deliver):
|
# Send test mail (it should fail to deliver):
|
||||||
_send_email_unchecked --from 'user@external.tld' --port 25 --data 'postgrey.txt'
|
_send_email --expect-rejection --from 'user@external.tld' --port 25 --data 'postgrey.txt'
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'Recipient address rejected: Delayed by Postgrey'
|
assert_output --partial 'Recipient address rejected: Delayed by Postgrey'
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ function teardown_file() {
|
||||||
# Configure `send_email()` to send from the mail client container (CONTAINER2_NAME) via ENV override,
|
# Configure `send_email()` to send from the mail client container (CONTAINER2_NAME) via ENV override,
|
||||||
# mail is sent to the DMS server container (CONTAINER1_NAME) via `--server` parameter:
|
# mail is sent to the DMS server container (CONTAINER1_NAME) via `--server` parameter:
|
||||||
# TODO: Use _send_email_and_get_id when proper resolution of domain names is possible:
|
# TODO: Use _send_email_and_get_id when proper resolution of domain names is possible:
|
||||||
CONTAINER_NAME=${CONTAINER2_NAME} _send_email_unchecked --server "${CONTAINER1_IP}" --port 25 --data 'postscreen.txt'
|
CONTAINER_NAME=${CONTAINER2_NAME} _send_email --expect-rejection --server "${CONTAINER1_IP}" --port 25 --data 'postscreen.txt'
|
||||||
# CONTAINER_NAME=${CONTAINER2_NAME} _send_email_and_get_id MAIL_ID_POSTSCREEN --server "${CONTAINER1_IP}" --data 'postscreen.txt'
|
# CONTAINER_NAME=${CONTAINER2_NAME} _send_email_and_get_id MAIL_ID_POSTSCREEN --server "${CONTAINER1_IP}" --data 'postscreen.txt'
|
||||||
# _print_mail_log_for_id "${MAIL_ID_POSTSCREEN}"
|
# _print_mail_log_for_id "${MAIL_ID_POSTSCREEN}"
|
||||||
# assert_output --partial "stored mail into mailbox 'INBOX'"
|
# assert_output --partial "stored mail into mailbox 'INBOX'"
|
||||||
|
|
|
@ -75,7 +75,7 @@ function setup_file() {
|
||||||
_send_email --to test123@localhost.localdomain --header 'Subject: Test Message existing-regexp-alias-local'
|
_send_email --to test123@localhost.localdomain --header 'Subject: Test Message existing-regexp-alias-local'
|
||||||
|
|
||||||
# Required for 'rejects mail to unknown user':
|
# Required for 'rejects mail to unknown user':
|
||||||
_send_email_unchecked --to nouser@localhost.localdomain
|
_send_email --expect-rejection --to nouser@localhost.localdomain
|
||||||
assert_failure
|
assert_failure
|
||||||
# Required for 'redirects mail to external aliases':
|
# Required for 'redirects mail to external aliases':
|
||||||
_send_email --to bounce-always@localhost.localdomain
|
_send_email --to bounce-always@localhost.localdomain
|
||||||
|
@ -99,7 +99,7 @@ function setup_file() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _unsuccessful() {
|
function _unsuccessful() {
|
||||||
_send_email_unchecked --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword --quit-after AUTH
|
_send_email --expect-rejection --port 465 --auth "${1}" --auth-user "${2}" --auth-password wrongpassword --quit-after AUTH
|
||||||
assert_failure
|
assert_failure
|
||||||
assert_output --partial 'authentication failed'
|
assert_output --partial 'authentication failed'
|
||||||
assert_output --partial 'No authentication type succeeded'
|
assert_output --partial 'No authentication type succeeded'
|
||||||
|
|
|
@ -31,7 +31,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@test '(SASLauthd) RIMAP SMTP authentication works' {
|
@test '(SASLauthd) RIMAP SMTP authentication works' {
|
||||||
_send_email_unchecked \
|
_send_email --expect-rejection \
|
||||||
--auth PLAIN \
|
--auth PLAIN \
|
||||||
--auth-user user1@localhost.localdomain \
|
--auth-user user1@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
|
|
|
@ -326,7 +326,7 @@ function teardown() {
|
||||||
@test "spoofing (with LDAP): rejects sender forging" {
|
@test "spoofing (with LDAP): rejects sender forging" {
|
||||||
_wait_for_smtp_port_in_container_to_respond dms-test_ldap
|
_wait_for_smtp_port_in_container_to_respond dms-test_ldap
|
||||||
|
|
||||||
_send_email_unchecked \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth PLAIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
|
@ -354,7 +354,7 @@ function teardown() {
|
||||||
# Template used has invalid AUTH: https://github.com/docker-mailserver/docker-mailserver/pull/3006#discussion_r1073321432
|
# Template used has invalid AUTH: https://github.com/docker-mailserver/docker-mailserver/pull/3006#discussion_r1073321432
|
||||||
skip 'TODO: This test seems to have been broken from the start (?)'
|
skip 'TODO: This test seems to have been broken from the start (?)'
|
||||||
|
|
||||||
_send_email_unchecked \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth PLAIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user some.user.email@localhost.localdomain \
|
--auth-user some.user.email@localhost.localdomain \
|
||||||
--auth-password secret \
|
--auth-password secret \
|
||||||
|
@ -367,7 +367,7 @@ function teardown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "saslauthd: ldap smtp authentication" {
|
@test "saslauthd: ldap smtp authentication" {
|
||||||
_send_email_unchecked \
|
_send_email --expect-rejection \
|
||||||
--auth PLAIN \
|
--auth PLAIN \
|
||||||
--auth-user some.user@localhost.localdomain \
|
--auth-user some.user@localhost.localdomain \
|
||||||
--auth-password wrongpassword \
|
--auth-password wrongpassword \
|
||||||
|
|
|
@ -293,7 +293,7 @@ EOF
|
||||||
|
|
||||||
# An authenticated user cannot use an envelope sender (MAIL FROM)
|
# An authenticated user cannot use an envelope sender (MAIL FROM)
|
||||||
# address they do not own according to `main.cf:smtpd_sender_login_maps` lookup
|
# address they do not own according to `main.cf:smtpd_sender_login_maps` lookup
|
||||||
_send_email_unchecked \
|
_send_email --expect-rejection \
|
||||||
--port 465 -tlsc --auth PLAIN \
|
--port 465 -tlsc --auth PLAIN \
|
||||||
--auth-user added@localhost.localdomain \
|
--auth-user added@localhost.localdomain \
|
||||||
--auth-password mypassword \
|
--auth-password mypassword \
|
||||||
|
|
Loading…
Reference in New Issue