Mailu/MSMTP: split token mgmt, idempotent reload, safer guards

• Rename: 02_create-user.yml → 02_manage_user.yml; 03_create-token.yml → 03a_manage_user_token.yml + 03b_create_user_token.yml
• Only (re)run sys-svc-msmtp when no-reply token exists; set run_once_sys_svc_msmtp=true in 01_core
• Reset by setting run_once_sys_svc_msmtp=false after creating no-reply token; then include sys-svc-msmtp
• Harden when-guards (no '{{ }}' in when, safe .get lookups)
• Minor formatting and failed_when readability

Conversation: https://chatgpt.com/share/68ebd196-a264-800f-a215-3a89d0f96c79
This commit is contained in:
2025-10-12 18:05:00 +02:00
parent a996e2190f
commit 3da645f3b8
7 changed files with 62 additions and 47 deletions

View File

@@ -41,7 +41,7 @@
meta: flush_handlers
- name: "Create Mailu accounts"
include_tasks: 02_create-user.yml
include_tasks: 02_manage_user.yml
vars:
MAILU_DOCKER_DIR: "{{ docker_compose.directories.instance }}"
mailu_api_base_url: "http://127.0.0.1:8080/api/v1"

View File

@@ -25,5 +25,5 @@
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Create Mailu API Token for {{ mailu_user_name }}"
include_tasks: 03_create-token.yml
when: "{{ 'mail-bot' in item.value.roles }}"
include_tasks: 03a_manage_user_token.yml
when: "'mail-bot' in item.value.roles"

View File

@@ -0,0 +1,26 @@
- name: "Fetch existing API tokens via curl inside admin container"
command: >-
{{ docker_compose_command_exec }} -T admin \
curl -s -X GET {{ mailu_api_base_url }}/token \
-H "Authorization: Bearer {{ MAILU_API_TOKEN }}"
args:
chdir: "{{ MAILU_DOCKER_DIR }}"
register: mailu_tokens_cli
changed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Extract existing token info for '{{ mailu_user_key }};{{ mailu_user_name }}'"
set_fact:
mailu_user_existing_token: >-
{{ (
mailu_tokens_cli.stdout
| default('[]')
| from_json
| selectattr('comment','equalto', SOFTWARE_NAME)
| list
).0 | default(None) }}
- name: "Start Mailu token procedures for undefined tokens"
when: users[mailu_user_key].mailu_token is not defined
include_tasks: 03b_create_user_token.yml

View File

@@ -1,26 +1,3 @@
- name: "Fetch existing API tokens via curl inside admin container"
command: >-
{{ docker_compose_command_exec }} -T admin \
curl -s -X GET {{ mailu_api_base_url }}/token \
-H "Authorization: Bearer {{ MAILU_API_TOKEN }}"
args:
chdir: "{{ MAILU_DOCKER_DIR }}"
register: mailu_tokens_cli
changed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Extract existing token info for '{{ mailu_user_key }};{{ mailu_user_name }}'"
set_fact:
mailu_user_existing_token: >-
{{ (
mailu_tokens_cli.stdout
| default('[]')
| from_json
| selectattr('comment','equalto', SOFTWARE_NAME)
| list
).0 | default(None) }}
- name: "Delete existing API token for '{{ mailu_user_key }};{{ mailu_user_name }}' if local token missing but remote exists"
command: >-
{{ docker_compose_command_exec }} -T admin \
@@ -29,7 +6,6 @@
args:
chdir: "{{ MAILU_DOCKER_DIR }}"
when:
- users[mailu_user_key].mailu_token is not defined
- mailu_user_existing_token is not none
- mailu_user_existing_token.id is defined
register: mailu_token_delete
@@ -49,7 +25,6 @@
} | to_json }}'
args:
chdir: "{{ MAILU_DOCKER_DIR }}"
when: users[mailu_user_key].mailu_token is not defined
register: mailu_token_creation
# If curl sees 4xx/5xx it returns non-zero due to -f → fail the task.
failed_when:
@@ -57,7 +32,7 @@
# Fallback: if some gateway returns 200 but embeds an error JSON.
- mailu_token_creation.rc == 0 and
(mailu_token_creation.stdout is search('"code"\\s*:\\s*4\\d\\d') or
mailu_token_creation.stdout is search('cannot be found'))
mailu_token_creation.stdout is search('cannot be found'))
# Only mark changed when a token is actually present in the JSON.
changed_when: mailu_token_creation.stdout is search('"token"\\s*:')
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
@@ -66,14 +41,25 @@
set_fact:
users: >-
{{ users
| combine({
mailu_user_key: (
users[mailu_user_key]
| combine({
'mailu_token': (mailu_token_creation.stdout | from_json).token
})
)
}, recursive=True)
| combine({
mailu_user_key: (
users[mailu_user_key]
| combine({
'mailu_token': (mailu_token_creation.stdout | from_json).token
})
)
}, recursive=True)
}}
when: users[mailu_user_key].mailu_token is not defined
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "Reset MSMTP Configuration if No-Reply User Token changed"
when: users['no-reply'].username == mailu_user_name
block:
- name: "Set MSMTP run-once fact false"
set_fact:
run_once_sys_svc_msmtp: false
changed_when: false
- name: Reload MSMTP role
include_role:
name: "sys-svc-msmtp"