-
+
+
@@ -649,7 +649,7 @@ onBeforeUnmount(() => {
diff --git a/frontend/src/components/MailContentRenderer.vue b/frontend/src/components/MailContentRenderer.vue
index b1d2cdf..5922a58 100644
--- a/frontend/src/components/MailContentRenderer.vue
+++ b/frontend/src/components/MailContentRenderer.vue
@@ -34,7 +34,7 @@ const props = defineProps({
type: Boolean,
default: false
},
- enableMailFlags: {
+ enableReadStatus: {
type: Boolean,
default: false
},
@@ -154,8 +154,8 @@ const handleSaveToS3 = async (filename, blob) => {
{{ t('downloadMail') }}
-
- {{ mail.mail_flags?.unread ? t('markRead') : t('markUnread') }}
+
+ {{ mail.unread ? t('markRead') : t('markUnread') }}
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
index 0825782..95e4b22 100644
--- a/frontend/src/store/index.js
+++ b/frontend/src/store/index.js
@@ -24,7 +24,7 @@ export const useGlobalState = createGlobalState(
disableAnonymousUserCreateEmail: false,
disableCustomAddressName: false,
enableUserDeleteEmail: false,
- enableMailFlags: false,
+ enableReadStatus: false,
enableAutoReply: false,
enableIndexAbout: false,
/** @type {string[]} */
diff --git a/frontend/src/views/Index.vue b/frontend/src/views/Index.vue
index 8c73242..2dcf866 100644
--- a/frontend/src/views/Index.vue
+++ b/frontend/src/views/Index.vue
@@ -32,13 +32,13 @@ const SendMail = defineAsyncComponent(() => {
const { t } = useScopedI18n('views.Index')
-const fetchMailData = async (limit, offset, mailFlagFilter = 'all') => {
+const fetchMailData = async (limit, offset, readStatus = 'all') => {
if (mailIdQuery.value > 0) {
const singleMail = await api.fetch(`/api/mail/${mailIdQuery.value}`);
if (singleMail) return { results: [singleMail], count: 1 };
return { results: [], count: 0 };
}
- const readStatusQuery = mailFlagFilter === 'all' ? '' : `&read_status=${mailFlagFilter}`
+ const readStatusQuery = readStatus === 'all' ? '' : `&read_status=${readStatus}`
return await api.fetch(
`/api/mails?limit=${limit}&offset=${offset}${readStatusQuery}`
);
@@ -48,10 +48,10 @@ const deleteMail = async (curMailId) => {
await api.fetch(`/api/mails/${curMailId}`, { method: 'DELETE' });
};
-const updateMailFlags = async (ids, flag, action) => {
- return await api.fetch(`/api/mails/flags`, {
+const updateMailReadStatus = async (ids, action) => {
+ return await api.fetch(`/api/mails/read-status`, {
method: 'PATCH',
- body: JSON.stringify({ ids, flag, action })
+ body: JSON.stringify({ ids, action })
});
};
@@ -138,7 +138,7 @@ onMounted(() => {
+ :enableReadStatus="openSettings.enableReadStatus" :updateMailReadStatus="updateMailReadStatus" />
{
totalCount.value = count > 0 ? count : totalCount.value;
const rawMail = results && results.length > 0 ? results[0] : null
currentMail.value = rawMail ? await processItem(rawMail) : null
- if (openSettings.value.enableMailFlags && rawMail) {
- const response = await api.fetch(`/api/mails/flags`, {
+ if (openSettings.value.enableReadStatus && rawMail) {
+ const response = await api.fetch(`/api/mails/read-status`, {
method: 'PATCH',
- body: JSON.stringify({ ids: [rawMail.id], flag: 'unread', action: 'clear' })
+ body: JSON.stringify({ ids: [rawMail.id], action: 'read' })
})
const updatedMail = response.results?.[0]
- if (updatedMail) currentMail.value.mail_flags = updatedMail.mail_flags
+ if (updatedMail) currentMail.value.unread = updatedMail.unread
}
} catch (error) {
console.error('Failed to fetch mails:', error)
@@ -65,18 +65,17 @@ const fetchMails = async () => {
}
const toggleCurrentMailUnread = async () => {
- if (!currentMail.value || !openSettings.value.enableMailFlags) return
+ if (!currentMail.value || !openSettings.value.enableReadStatus) return
try {
- const response = await api.fetch(`/api/mails/flags`, {
+ const response = await api.fetch(`/api/mails/read-status`, {
method: 'PATCH',
body: JSON.stringify({
ids: [currentMail.value.id],
- flag: 'unread',
action: 'toggle',
})
})
const updatedMail = response.results?.[0]
- if (updatedMail) currentMail.value.mail_flags = updatedMail.mail_flags
+ if (updatedMail) currentMail.value.unread = updatedMail.unread
} catch (error) {
message.error(error.message || 'error')
}
@@ -246,7 +245,7 @@ onBeforeUnmount(() => {
diff --git a/frontend/src/views/user/UserMailBox.vue b/frontend/src/views/user/UserMailBox.vue
index c070ae0..645cabd 100644
--- a/frontend/src/views/user/UserMailBox.vue
+++ b/frontend/src/views/user/UserMailBox.vue
@@ -20,12 +20,12 @@ const queryMail = () => {
mailBoxKey.value = Date.now();
}
-const fetchMailData = async (limit, offset, mailFlagFilter = 'all') => {
+const fetchMailData = async (limit, offset, readStatus = 'all') => {
return await api.fetch(
`/user_api/mails`
+ `?limit=${limit}`
+ `&offset=${offset}`
- + (mailFlagFilter === 'all' ? '' : `&read_status=${mailFlagFilter}`)
+ + (readStatus === 'all' ? '' : `&read_status=${readStatus}`)
+ (addressFilter.value ? `&address=${addressFilter.value}` : '')
);
}
@@ -51,10 +51,10 @@ const deleteMail = async (curMailId) => {
await api.fetch(`/user_api/mails/${curMailId}`, { method: 'DELETE' });
};
-const updateMailFlags = async (ids, flag, action) => {
- return await api.fetch(`/user_api/mails/flags`, {
+const updateMailReadStatus = async (ids, action) => {
+ return await api.fetch(`/user_api/mails/read-status`, {
method: 'PATCH',
- body: JSON.stringify({ ids, flag, action })
+ body: JSON.stringify({ ids, action })
});
};
@@ -78,7 +78,7 @@ onMounted(() => {
+ :deleteMail="deleteMail" :showFilterInput="true" :enableReadStatus="openSettings.enableReadStatus"
+ :updateMailReadStatus="updateMailReadStatus" />
diff --git a/vitepress-docs/docs/en/guide/feature/mail-api.md b/vitepress-docs/docs/en/guide/feature/mail-api.md
index b552a16..3341e4d 100644
--- a/vitepress-docs/docs/en/guide/feature/mail-api.md
+++ b/vitepress-docs/docs/en/guide/feature/mail-api.md
@@ -19,21 +19,21 @@ res = requests.get(
**Note**: `/api/mails` returns raw RFC822 data by design (for example `source`/`raw`), and it does not guarantee parsed fields such as `subject`, `text`, or `html`. Parse the raw source on the client side (for example with `mail-parser-wasm` or `postal-mime`) if you need readable message content.
-## Mail Flags API
+## Mail Read Status API
-After enabling `ENABLE_MAIL_FLAGS` and running the database migration, each mail response includes `mail_flags`, for example `{"unread": true}`. The backend owns bitmask mapping, historical `NULL` compatibility, and state calculation; clients do not need to know bit positions.
+After enabling `ENABLE_MAIL_FLAGS` and running the database migration, each mail response includes the boolean field `unread`. The backend owns storage, historical `NULL` compatibility, and state calculation.
-With an Address JWT, use `PATCH /api/mails/flags` to update up to 100 mail IDs. The supported flag is currently `unread`, and its action can be `set`, `clear`, or `toggle`.
+With an Address JWT, use `PATCH /api/mails/read-status` to update up to 100 mail IDs. The `action` can be `read`, `unread`, or `toggle`.
```python
requests.patch(
- "https://