1
1
Fork 0
mirror of https://github.com/docker-mailserver/docker-mailserver synced 2024-05-28 09:06:04 +02:00
docker-mailserver/target/bin/delmailuser
Brennan Kinney 57aeb6db2a
refactor: CLI commands for database management (#2654)
See the associated PR for more detailed commentary on specific changes.

### Commands refactored:
- User (**All:** add / list / update / del + _dovecot-master variants_)
- Quota (**All:** set / del)
- Virtual Alias (**All:** add / list /del)
- Relay (**All:** add-relayhost / add-sasl / exclude-domain)

### Overall changes involve:
- **Fairly common structure:**
  - `_main` method at the top provides an overview of logical steps:
    - After all methods are declared beneath it (_and imported from the new `helpers/database/db.sh`_), the `_main` is called at the bottom of the file.
    - `delmailuser` additionally processes option support for `-y` prior to calling `_main`.
  - `__usage` is now consistent with each of these commands, along with the `help` command.
  - Most logic delegated to new helper scripts. Some duplicate content remains on the basis that it's low-risk to maintenance and avoids less hassle to jump between files to check a single line, usually this is arg validation.
  - Error handling should be more consistent, along with var names (_no more `USER`/`EMAIL`/`FULL_EMAIL` to refer to the same expected value_).
- **Three new management scripts** (in `helpers/database/manage/`) using a common structure for managing changes to their respective "Database" config file.
  - `postfix-accounts.sh` unified not only add and update commands, but also all the dovecot-master versions, a single password call for all 4 of them, with a 5th consumer of the password prompt from the relay command `addsaslpassword`.
  - These scripts delegate actual writes to `helpers/database/db.sh` which provides a common API to support the changes made.
     - This is more verbose/complex vs the current inline operations each command currently has, as it provides generic support instead of slightly different variations being maintained, along with handling some edge cases that existed and would lead to bugs (notably substring matches).
     - Centralizing changes here seems wiser than scattered about. I've tried to make it easy to grok, hopefully it's not worse than the current situation.
     - List operations were kept in their respective commands, `db.sh` is only really managing writes. I didn't see a nice way for removing the code duplication for list commands as the duplication was fairly minimal, especially for `listalias` and `listdovecotmasteruser` which were quite simple in their differences in the loop body.
     - `listmailuser` and `delmailuser` also retain methods exclusive to respective commands, I wasn't sure if there was any benefit to move those, but they were refactored.
2022-07-29 12:10:23 +12:00

131 lines
3.8 KiB
Bash
Executable File

#! /bin/bash
# shellcheck source=../scripts/helpers/index.sh
source /usr/local/bin/helpers/index.sh
function _main
{
[[ ${1:-} == 'help' ]] && { __usage ; exit 0 ; }
# Tests expect early exit without error if no DB exists:
[[ -s ${DATABASE_ACCOUNTS} ]] || return 0
# Validate Parameters:
[[ -z ${*} ]] && { __usage ; _exit_with_error 'No account specified' ; }
_maildel_request_if_missing
# TODO: May want to lock all database files prior to loop? (DATABASE_ACCOUNTS DATABASE_QUOTA DATABASE_VIRTUAL)
# NOTE: Present lock method locks the original sourcing script itself.
_create_lock
# Actual command to perform:
for MAIL_ACCOUNT in "${@}"
do
_account_should_already_exist
[[ ${MAILDEL} -eq 1 ]] && _remove_maildir "${MAIL_ACCOUNT}"
_manage_virtual_aliases_delete '_' "${MAIL_ACCOUNT}" \
|| _exit_with_error "Aliases for '${MAIL_ACCOUNT}' could not be deleted"
_manage_dovecot_quota_delete "${MAIL_ACCOUNT}" \
|| _exit_with_error "Quota for '${MAIL_ACCOUNT}' could not be deleted"
# Performed last, avoids breaking command if a prior failure occurred
_manage_accounts_delete "${MAIL_ACCOUNT}" \
|| _exit_with_error "'${MAIL_ACCOUNT}' could not be deleted"
_log 'info' "'${MAIL_ACCOUNT}' and associated data deleted"
done
}
function __usage
{
printf '%s' "${PURPLE}delmailuser${RED}(${YELLOW}8${RED})
${ORANGE}USAGE${RESET}
./setup.sh email del [ OPTIONS ] <MAIL ACCOUNT> [<EXTRA MAIL ACCOUNTS> ${RED}...${RESET} ]
${ORANGE}OPTIONS${RESET}
-y
Skip prompt by approving to ${LWHITE}delete all mail storage${RESET} for the account(s).
${BLUE}Generic Program Information${RESET}
help Print the usage information.
${ORANGE}DESCRIPTION${RESET}
Delete a mail account, including associated data (aliases, quotas) and
optionally the mailbox storage for that account.
${ORANGE}EXAMPLES${RESET}
${LWHITE}./setup.sh email del user@example.com${RESET}
Delete the mail account 'user@example.com' and associated data,
but ask if mailbox data should also be deleted.
${LWHITE}./setup.sh email del -y user@example.com extra-user@example.com${RESET}
Delete the two mail accounts requested, their associated data and
delete the mailbox data for both accounts without asking.
${ORANGE}EXIT STATUS${RESET}
Exit status is 0 if command was successful. If wrong arguments are provided
or arguments contain errors, the script will exit early with exit status 1.
"
}
function _parse_options
{
while getopts ":yY" OPT
do
case "${OPT}" in
( 'y' | 'Y' )
MAILDEL=1
;;
( * )
__usage
_exit_with_error "The option '${OPT}' is unknown"
;;
esac
done
}
function _maildel_request_if_missing
{
if [[ ${MAILDEL} -eq 0 ]]
then
local MAILDEL_CHOSEN
read -r -p "Do you want to delete the mailbox as well (removing all mails)? [Y/n] " MAILDEL_CHOSEN
# TODO: Why would MAILDEL be set to true if MAILDEL_CHOSEN is empty?
if [[ ${MAILDEL_CHOSEN} =~ (y|Y|yes|Yes) ]] || [[ -z ${MAILDEL_CHOSEN} ]]
then
MAILDEL=1
fi
fi
}
function _remove_maildir
{
local MAIL_ACCOUNT=${1}
local LOCAL_PART="${MAIL_ACCOUNT%@*}"
local DOMAIN_PART="${MAIL_ACCOUNT#*@}"
local MAIL_ACCOUNT_STORAGE_DIR="/var/mail/${DOMAIN_PART}/${LOCAL_PART}"
[[ ! -d ${MAIL_ACCOUNT_STORAGE_DIR} ]] && _exit_with_error "Mailbox directory '${MAIL_ACCOUNT_STORAGE_DIR}' does not exist"
_log 'info' "Deleting Mailbox: '${MAIL_ACCOUNT_STORAGE_DIR}'"
rm -R "${MAIL_ACCOUNT_STORAGE_DIR}" || _exit_with_error 'Mailbox could not be deleted'
# Remove parent directory too if it's empty:
rmdir "/var/mail/${DOMAIN_PART}" &>/dev/null
}
# Support for optional maildir removal:
MAILDEL=0
_parse_options "${@}"
# Remove options before passing over parameters to _main:
shift $((OPTIND-1))
_main "${@}"