Merge pull request #212 from ttionya/feature/mail-thread

Add email threading control (close #210)
This commit is contained in:
ttionya
2025-08-02 14:22:56 +08:00
committed by GitHub
6 changed files with 92 additions and 17 deletions
+1
View File
@@ -23,4 +23,5 @@
# MAIL_TO=""
# MAIL_WHEN_SUCCESS="TRUE"
# MAIL_WHEN_FAILURE="TRUE"
# MAIL_FORCE_THREAD="FALSE"
# TIMEZONE="UTC"
+16 -7
View File
@@ -444,13 +444,14 @@ Starting from v1.19.0, we will be using [`s-nail`](https://www.sdaoden.eu/code-n
Please note that `heirloom-mailx` is a stub for `s-nail`, and most of its functionality is compatible. Therefore, you may not need to modify any environment variables for this change.
| Environment Variable | Default Value | Description |
| --- | --- |-------------------------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | Enable sending mail. |
| MAIL_SMTP_VARIABLES | | Mail sending options. |
| MAIL_TO | | The recipient of the notification email. |
| MAIL_WHEN_SUCCESS | `TRUE` | Send an email when the backup completes successfully. |
| MAIL_WHEN_FAILURE | `TRUE` | Send an email if the backup fails. |
| Environment Variable | Default Value | Description |
| --- | --- |-----------------------------------------------------------------------------------------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | Enable sending mail. |
| MAIL_SMTP_VARIABLES | | Mail sending options. |
| MAIL_TO | | The recipient of the notification email. |
| MAIL_WHEN_SUCCESS | `TRUE` | Send an email when the backup completes successfully. |
| MAIL_WHEN_FAILURE | `TRUE` | Send an email if the backup fails. |
| MAIL_FORCE_THREAD | `FALSE` | Particularly useful when mail clients fail to group related messages in conversation view despite identical subjects. |
For `MAIL_SMTP_VARIABLES`, you need to configure the mail sending options yourself. **We will set the email subject based on the usage scenario, so you should not use the `-s` flag.**
@@ -468,6 +469,14 @@ For `MAIL_SMTP_VARIABLES`, you need to configure the mail sending options yourse
Console showing warnings? Check [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) for more details.
For `MAIL_FORCE_THREAD`, particularly useful when receiving systems fail to properly aggregate messages into conversation threads. It supports three modes of operation:
1. `FALSE`: Default email sending behavior.
2. `TRUE`: Auto-generates RFC-compliant Message-ID to force thread creation.
3. `Valid Message-ID string`: Uses specified Message-ID to associate with existing thread. Find it in the original email's Message-ID field.
When enabled, the system automatically adds required headers (`Message-ID`, `References`, `In-Reply-To`) to enforce proper thread association on the receiving end.
<br>
+16 -7
View File
@@ -441,13 +441,14 @@ docker run --rm -it \
请注意,`heirloom-mailx``s-nail` 的存根,它们大部分功能是兼容的。因此你可能不需要为这个改变修改任何环境变量。
| 环境变量 | 默认值 | 描述 |
| --- |--------|-----------|
| MAIL_SMTP_ENABLE | `FALSE` | 启用邮件发送功能 |
| MAIL_SMTP_VARIABLES | | 邮件发送参数 |
| MAIL_TO | | 接收邮件的地址 |
| MAIL_WHEN_SUCCESS | `TRUE` | 备份成功后发送邮件 |
| MAIL_WHEN_FAILURE | `TRUE` | 备份失败后发送邮件 |
| 环境变量 | 默认值 | 描述 |
| --- |--------|----------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | 启用邮件发送功能 |
| MAIL_SMTP_VARIABLES | | 邮件发送参数 |
| MAIL_TO | | 接收邮件的地址 |
| MAIL_WHEN_SUCCESS | `TRUE` | 备份成功后发送邮件 |
| MAIL_WHEN_FAILURE | `TRUE` | 备份失败后发送邮件 |
| MAIL_FORCE_THREAD | `FALSE` | 尤其适用于邮件客户端在主题相同的情况下仍无法在对话视图中将相关邮件分组的情况 |
对于 `MAIL_SMTP_VARIABLES`,你需要自行配置邮件发送参数。**我们会根据使用场景设置邮件主题,所以你不应该使用 `-s` 标志。**
@@ -465,6 +466,14 @@ docker run --rm -it \
控制台有警告?查看 [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) 了解更多。
对于 `MAIL_FORCE_THREAD`,在邮件客户端无法正确将邮件聚合到同一会话中时特别有用。它支持三种操作模式:
1. `FALSE`:默认电子邮件发送行为
2. `TRUE`:自动生成符合 RFC 的 Message-ID 以强制会话关联
3. `有效 Message-ID 字符串`:使用指定的 Message-ID 与现有会话关联。你可以在原始邮件内容的 Message-ID 字段中找到它
启用后,系统会自动添加所需的标头(`Message-ID``References``In-Reply-To`),以便邮件客户端适当地关联会话。
<br>
+1
View File
@@ -39,6 +39,7 @@ services:
# MAIL_TO: ''
# MAIL_WHEN_SUCCESS: 'TRUE'
# MAIL_WHEN_FAILURE: 'TRUE'
# MAIL_FORCE_THREAD: 'FALSE'
# TIMEZONE: 'UTC'
volumes:
- vaultwarden-data:/bitwarden/data/
+57 -2
View File
@@ -2,6 +2,8 @@
ENV_FILE="/.env"
CRON_CONFIG_FILE="${HOME}/crontabs"
MAIL_CONFIG_DIR="/config/mail"
MAIL_PARENT_MESSAGE_ID_FILE="${MAIL_CONFIG_DIR}/parent_message_id"
BACKUP_DIR="/bitwarden/backup"
RESTORE_DIR="/bitwarden/restore"
RESTORE_EXTRACT_DIR="/bitwarden/extract"
@@ -105,15 +107,40 @@ function check_dir_exist() {
# send mail result
########################################
function send_mail() {
local MAIL_VERBOSE_FLAG=""
local MAIL_TEMPLATE_FLAG=""
local MAIL_TEMPLATE=""
local MAIL_USED_MESSAGE_ID=""
# verbose
if [[ "${MAIL_DEBUG}" == "TRUE" ]]; then
local MAIL_VERBOSE="-v"
MAIL_VERBOSE_FLAG="-v"
fi
echo "$2" | eval "mail ${MAIL_VERBOSE} -s \"$1\" ${MAIL_SMTP_VARIABLES} \"${MAIL_TO}\""
# template
if [[ "${MAIL_FORCE_THREAD}" == "TRUE" ]]; then
if [[ -n "${MAIL_PARENT_MESSAGE_ID}" ]]; then
MAIL_USED_MESSAGE_ID="${MAIL_PARENT_MESSAGE_ID}"
MAIL_TEMPLATE="References: ${MAIL_USED_MESSAGE_ID}\nIn-Reply-To: ${MAIL_USED_MESSAGE_ID}\n\n"
else
MAIL_USED_MESSAGE_ID="<$(date +%s%N).$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16).$(hostname)@vaultwarden.backup>"
MAIL_TEMPLATE="Message-ID: ${MAIL_USED_MESSAGE_ID}\n\n"
fi
fi
if [[ -n "${MAIL_TEMPLATE}" ]]; then
MAIL_TEMPLATE_FLAG="-t"
fi
echo -e "${MAIL_TEMPLATE}$2" | eval "mail ${MAIL_VERBOSE_FLAG} ${MAIL_TEMPLATE_FLAG} -s \"$1\" ${MAIL_SMTP_VARIABLES} \"${MAIL_TO}\""
if [[ $? != 0 ]]; then
color red "mail sending has failed"
else
color blue "mail has been sent successfully"
if [[ "${MAIL_FORCE_THREAD}" == "TRUE" && -z "${MAIL_PARENT_MESSAGE_ID}" ]]; then
mkdir -p "$(dirname "${MAIL_PARENT_MESSAGE_ID_FILE}")"
echo -n "${MAIL_USED_MESSAGE_ID}" > "${MAIL_PARENT_MESSAGE_ID_FILE}"
fi
fi
}
@@ -417,6 +444,13 @@ function init_env() {
color yellow "MAIL_TO: ${MAIL_TO}"
color yellow "MAIL_WHEN_SUCCESS: ${MAIL_WHEN_SUCCESS}"
color yellow "MAIL_WHEN_FAILURE: ${MAIL_WHEN_FAILURE}"
if [[ "${MAIL_FORCE_THREAD}" == "TRUE" ]]; then
if [[ -n "${MAIL_PARENT_MESSAGE_ID}" ]]; then
color yellow "MAIL_PARENT_MESSAGE_ID: ${MAIL_PARENT_MESSAGE_ID}"
else
color yellow "MAIL_MESSAGE_ID: auto generate"
fi
fi
fi
color yellow "TIMEZONE: ${TIMEZONE}"
color yellow "DISPLAY_NAME: ${DISPLAY_NAME}"
@@ -589,4 +623,25 @@ function init_env_mail() {
else
MAIL_WHEN_FAILURE="TRUE"
fi
# MAIL_FORCE_THREAD
get_env MAIL_FORCE_THREAD
# 1. As long as MAIL_PARENT_MESSAGE_ID is valid (either specified or read from a file), MAIL_FORCE_THREAD must be set to TRUE.
# 2. As long as MAIL_FORCE_THREAD is set to TRUE, even if an invalid Message-ID is read from the file, it will be regenerated subsequently.
# 3. When MAIL_FORCE_THREAD is not set to TRUE, promptly clear the persistent files.
if [[ "${MAIL_FORCE_THREAD^^}" == "TRUE" ]]; then
MAIL_FORCE_THREAD="TRUE"
if [[ -f "${MAIL_PARENT_MESSAGE_ID_FILE}" && -s "${MAIL_PARENT_MESSAGE_ID_FILE}" ]]; then
MAIL_PARENT_MESSAGE_ID="$(cat "${MAIL_PARENT_MESSAGE_ID_FILE}")"
fi
else
MAIL_PARENT_MESSAGE_ID="${MAIL_FORCE_THREAD}"
MAIL_FORCE_THREAD="FALSE"
rm -rf "${MAIL_CONFIG_DIR}"
fi
if [[ "${MAIL_PARENT_MESSAGE_ID}" =~ ^\<.*\@.+\>$ ]]; then
MAIL_FORCE_THREAD="TRUE"
else
MAIL_PARENT_MESSAGE_ID=""
fi
}
+1 -1
View File
@@ -1 +1 @@
v1.24.4
v1.25.0-beta.1