Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. The format
- **DMS v14 mistakenly** relocated the _getmail state directory_ to the _DMS Config Volume_ as a `getmail/` subdirectory.
- This has been corrected to `/var/lib/getmail` (_if you have mounted a DMS State Volume to `/var/mail-state`, `/var/lib/getmail` will be symlinked to `/var/mail-state/lib-getmail`_).
- To preserve this state when upgrading to DMS v15, **you must manually migrate `getmail/` from the _DMS Config Volume_ to `lib-getmail/` in the _DMS State Volume_.**
- `setup email delete <EMAIL ADDRESS>` now requires explicit confirmation if the mailbox data should be deleted ([#4365](https://github.com/docker-mailserver/docker-mailserver/pull/4365)).

### Added

Expand Down
26 changes: 14 additions & 12 deletions target/bin/delmailuser
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ function _main() {
for MAIL_ACCOUNT in "${@}"; do
_account_should_already_exist

[[ ${MAILDEL} -eq 1 ]] && _remove_maildir "${MAIL_ACCOUNT}"
if [[ ${MAILDEL} -eq 1 ]]; then
_remove_maildir "${MAIL_ACCOUNT}"
else
_log 'info' "The mailbox data will not be deleted."
fi

_manage_virtual_aliases_delete '_' "${MAIL_ACCOUNT}" \
|| _exit_with_error "Aliases for '${MAIL_ACCOUNT}' could not be deleted"
Expand All @@ -31,7 +35,7 @@ function _main() {
_manage_accounts_delete "${MAIL_ACCOUNT}" \
|| _exit_with_error "'${MAIL_ACCOUNT}' could not be deleted"

_log 'info' "'${MAIL_ACCOUNT}' and associated data deleted"
_log 'info' "'${MAIL_ACCOUNT}' and associated data (aliases, quotas) deleted"
done
}

Expand All @@ -43,14 +47,14 @@ ${ORANGE}USAGE${RESET}

${ORANGE}OPTIONS${RESET}
-y
Skip prompt by approving to ${LWHITE}delete all mail storage${RESET} for the account(s).
Skip prompt by approving to ${LWHITE}delete all mail data${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.
optionally the mailbox data for that account.

${ORANGE}EXAMPLES${RESET}
${LWHITE}./setup.sh email del [email protected]${RESET}
Expand Down Expand Up @@ -87,12 +91,10 @@ function _parse_options() {
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
read -r -p "Do you want to delete the mailbox data 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
# Delete mailbox data only if the user provides explicit confirmation.
[[ ${MAILDEL_CHOSEN,,} == "y" ]] && MAILDEL=1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the ,, portion meant to do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes the var value lowercase.

Copy link
Member

@polarathene polarathene Feb 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun πŸ˜’

While a bit more verbose, this is the equivalent with Nu:

if ($MAILDEL_CHOSEN | str downcase) == 'y' { $MAILDEL = true }

Container example:

$ docker run --rm ghcr.io/nushell/nushell -c 'mut MAILDEL_CHOSEN = "Y" ; print ($MAILDEL_CHOSEN | str downcase)'

y

More fleshed out example

Similar to a previous example I shared in the past to compare to Bash, here's what some more NuShell looks like (I'm still not really sold on it, has some good/bad aspects πŸ˜…)

#!/usr/bin/env nu

# Implicit default method run:
def main [] {
    print "this is setup CLI"
}

# Subcommand (see usage example below),
# also implicitly has `--help` generated `email del --help` (can be improved)
# Args are between the [], a bool flag with long and short forms,
# and spread syntax to indicate the rest of the CLI args will be collected as a list variable
def "main email del" [--yes (-y), ...accounts] {
  # `let` is immutable (read-only) after assignment
  let force_skip = $yes

  # `mut` allow updating the variable after assignment
  mut should_delete = false
  if not $force_skip {
    print 'Do you want to delete the mailbox data as well (removing all mails)? [y/N]'
    # Read the next input from the user, lowercase it and compare to get true/false:
    # `--numchar 1` is like `read -n 1` stopping after the first char input from the user.
    # `--suppress-output` so regardless of char when input is not `y`, we later print `no`.
    $should_delete = (input --numchar 1 --suppress-output | str downcase) == 'y'

    # Alternative that provides an interactive prompt and converts selection to boolean:
    # https://github.com/nushell/nushell/issues/15124
    #$should_delete = try { (['no', 'yes'] | input list --index | into bool) } catch { false }

    # Formats the bool result as yes/no for optionally logging to stdout:
    print (if $should_delete { 'yes' } else { 'no' })
  }

  # Iterate through the array of 1 or more accounts:
  for account in $accounts {
    if $should_delete { delete_mailbox $account }
  }
}

# Pretend this has full functionality of `_remove_maildir()` :)
def delete_mailbox [account: string] {
  # This variable will split the email address at `@` into subfields `.local` + `.domain`:
  let mail_parts = ($account | split column --number 2 '@' local domain | first)

  let mailbox_path = $"/var/mail/($mail_parts.domain)/($mail_parts.local)"
  print $"Deleting Mailbox: '($mailbox_path)'"
}
$ ./setup.nu email del [email protected]

Do you want to delete the mailbox data as well (removing all mails)? [y/N]
yes
Deleting Mailbox: '/var/mail/example.test/john.doe'
Some relevant NuShell doc links if you're interested

fi
}

Expand All @@ -103,10 +105,10 @@ function _remove_maildir() {
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"
[[ ! -d ${MAIL_ACCOUNT_STORAGE_DIR} ]] && _exit_with_error "Mailbox data 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'
_log 'info' "Deleting mailbox data: '${MAIL_ACCOUNT_STORAGE_DIR}'"
rm -R "${MAIL_ACCOUNT_STORAGE_DIR}" || _exit_with_error 'Mailbox data could not be deleted'
# Remove parent directory too if it's empty:
rmdir "/var/mail/${DOMAIN_PART}" &>/dev/null
}
Expand Down
Loading