mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
initial commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
import { AccessToken } from "@/features/access-tokens/data/schema";
|
||||
|
||||
export const login = async (password: string) => {
|
||||
const response = await axiosInstance.post(`/api/login`, password, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const reset_root_token = async () => {
|
||||
const response = await axiosInstance.post("/api/v1/reset-root-token");
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const reset_root_password = async (password: string) => {
|
||||
const response = await axiosInstance.post("/api/v1/reset-root-password", password, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const list_access_tokens = async () => {
|
||||
const response = await axiosInstance.get<AccessToken[]>("/api/v1/access-token-list");
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const create_access_token = async (data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post("/api/v1/access-token", data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const update_access_token = async (token: string, data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post(`/api/v1/access-token/${token}`, data);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const delete_access_token = async (token: string) => {
|
||||
const response = await axiosInstance.delete(`/api/v1/access-token/${token}`);
|
||||
return response.data;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
import { AccountModel } from "@/features/accounts/data/schema";
|
||||
import { PaginatedResponse } from "..";
|
||||
|
||||
export interface MinimalAccount {
|
||||
id: number;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export const minimal_account_list = async () => {
|
||||
const response = await axiosInstance.get<MinimalAccount[]>("/api/v1/minimal-account-list");
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
export interface ErrorMessage {
|
||||
error: string;
|
||||
at: number; // milliseconds timestamp
|
||||
}
|
||||
|
||||
export type ProgressMap = Record<string, MailboxBatchProgress>;
|
||||
|
||||
export interface AccountRunningState {
|
||||
account_id: number;
|
||||
last_incremental_sync_start: number;
|
||||
last_incremental_sync_end?: number,
|
||||
errors: ErrorMessage[];
|
||||
is_initial_sync_completed: boolean;
|
||||
progress?: ProgressMap;
|
||||
initial_sync_start_time?: number;
|
||||
initial_sync_end_time?: number;
|
||||
}
|
||||
|
||||
|
||||
export interface MailboxBatchProgress {
|
||||
total_batches: number;
|
||||
current_batch: number;
|
||||
}
|
||||
|
||||
export const account_state = async (account_id: number) => {
|
||||
const response = await axiosInstance.get<AccountRunningState>(`/api/v1/account-state/${account_id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const create_account = async (data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post("/api/v1/account", data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const list_accounts = async () => {
|
||||
const response = await axiosInstance.get<PaginatedResponse<AccountModel>>("/api/v1/accounts?desc=true");
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const update_account = async (account_id: number, data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post(`/api/v1/account/${account_id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const remove_account = async (account_id: number) => {
|
||||
const response = await axiosInstance.delete(`/api/v1/account/${account_id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export interface AutoConfigResult {
|
||||
imap: ServerConfig;
|
||||
oauth2?: OAuth2Config;
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
encryption: 'None' | 'Ssl' | 'StartTls';
|
||||
}
|
||||
|
||||
export interface OAuth2Config {
|
||||
issuer: string;
|
||||
scope: string;
|
||||
auth_url: string;
|
||||
token_url: string;
|
||||
}
|
||||
|
||||
export const autoconfig = async (email: string) => {
|
||||
const response = await axiosInstance.get<AutoConfigResult>(`/api/v1/autoconfig/${email}`);
|
||||
return response.data;
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import { getAccessToken } from "@/stores/authStore";
|
||||
import axios from "axios";
|
||||
|
||||
// Create an Axios instance
|
||||
const baseURL = process.env.NODE_ENV === "production"
|
||||
? "/" // Production: relative to the current domain
|
||||
: "http://localhost:15630"; // Development: Poem's backend server
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL,
|
||||
timeout: 30000, // Timeout in milliseconds
|
||||
headers: {
|
||||
"Content-Type": "application/json", // Explicitly setting Content-Type to application/json
|
||||
},
|
||||
});
|
||||
|
||||
// Add a request interceptor to include the access token in headers
|
||||
axiosInstance.interceptors.request.use(
|
||||
(config) => {
|
||||
const accessToken = getAccessToken(); // Retrieve access token from localStorage
|
||||
if (accessToken) {
|
||||
config.headers.Authorization = `Bearer ${accessToken}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
// Handle request errors
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Add a response interceptor (optional)
|
||||
axiosInstance.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
// Handle response errors
|
||||
//console.error("API error:", error.response?.data || error.message);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default axiosInstance;
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
export interface PaginatedResponse<S> {
|
||||
current_page: number | null;
|
||||
page_size: number | null;
|
||||
total_items: number;
|
||||
items: S[];
|
||||
total_pages: number | null;
|
||||
}
|
||||
|
||||
|
||||
export interface EmailEnvelope {
|
||||
id: number;
|
||||
message_id: string;
|
||||
account_id: number;
|
||||
uid: number;
|
||||
subject: string;
|
||||
text: string;
|
||||
from: string;
|
||||
to: string[];
|
||||
cc: string[];
|
||||
bcc: string[];
|
||||
date: number;
|
||||
internal_date: number;
|
||||
size: number;
|
||||
thread_id: number,
|
||||
attachments: string[];
|
||||
tags: string[];
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
|
||||
|
||||
export interface MailboxData {
|
||||
attributes: { attr: string; extension: string | null }[];
|
||||
delimiter: string | null;
|
||||
exists: number;
|
||||
id: number;
|
||||
name: string;
|
||||
uid_next: number | null;
|
||||
uid_validity: number | null;
|
||||
unseen: number | null;
|
||||
}
|
||||
|
||||
export const list_mailboxes = async (accountId: number, remote: boolean) => {
|
||||
const response = await axiosInstance.get<MailboxData[]>(`/api/v1/list-mailboxes/${accountId}?remote=${remote}`);
|
||||
return response.data;
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import { EmailEnvelope, PaginatedResponse } from "@/api";
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
export const list_messages = async (accountId: number, mailbox_id: number, page: number, page_size: number) => {
|
||||
const params = new URLSearchParams({
|
||||
mailbox_id: String(mailbox_id),
|
||||
page: String(page),
|
||||
page_size: String(page_size),
|
||||
});
|
||||
|
||||
const response = await axiosInstance.get<PaginatedResponse<EmailEnvelope>>(
|
||||
`/api/v1/list-messages/${accountId}?${params.toString()}`
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const get_thread_messages = async (accountId: number, thread_id: number, page: number, page_size: number) => {
|
||||
const params = new URLSearchParams({
|
||||
thread_id: String(thread_id),
|
||||
page: String(page),
|
||||
page_size: String(page_size),
|
||||
});
|
||||
|
||||
const response = await axiosInstance.get<PaginatedResponse<EmailEnvelope>>(
|
||||
`/api/v1/get-thread-messages/${accountId}?${params.toString()}`
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const download_attachment = async (accountId: number, id: number, attachmentFileName: string) => {
|
||||
const response = await axiosInstance.get(`/api/v1/download-attachment/${accountId}?id=${id}&name=${attachmentFileName}`, { responseType: 'blob' });
|
||||
const blob = new Blob([response.data]);
|
||||
saveAs(blob, attachmentFileName);
|
||||
};
|
||||
|
||||
|
||||
export interface AttachmentInfo {
|
||||
/** MIME content type of the attachment (e.g., `image/png`, `application/pdf`). */
|
||||
file_type: string;
|
||||
/** Content-ID, used for inline attachments (referenced in HTML by `cid:` URLs). */
|
||||
content_id?: string;
|
||||
/** Whether the attachment is marked as inline (true) or a regular file (false). */
|
||||
inline: boolean;
|
||||
/** Original filename of the attachment, if provided. */
|
||||
filename: string;
|
||||
/** Size of the attachment in bytes. */
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface MessageContentResponse {
|
||||
text?: string;
|
||||
html?: string;
|
||||
attachments?: AttachmentInfo[]
|
||||
}
|
||||
|
||||
export const getContent = (messageContent: MessageContentResponse): string | null => {
|
||||
if (messageContent.html) {
|
||||
return messageContent.html;
|
||||
} else if (messageContent.text) {
|
||||
return messageContent.text;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const load_message = async (accountId: number, id: number) => {
|
||||
const response = await axiosInstance.get<MessageContentResponse>(`/api/v1/message-content/${accountId}?id=${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const delete_messages = async (payload: Record<string, number[]>) => {
|
||||
const response = await axiosInstance.post("/api/v1/delete-messages", payload);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const download_message = async (accountId: number, id: number) => {
|
||||
const response = await axiosInstance.get(`/api/v1/download-message/${accountId}?id=${id}`, { responseType: 'blob' });
|
||||
const blob = new Blob([response.data]);
|
||||
saveAs(blob, `${id}.eml`);
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import { OAuth2Entity } from "@/features/oauth2/data/schema";
|
||||
import axiosInstance from "../axiosInstance";
|
||||
|
||||
export const get_oauth2_list = async () => {
|
||||
const response = await axiosInstance.get<{ items: OAuth2Entity[] }>("/api/v1/oauth2-list");
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const delete_oauth2 = async (id: number) => {
|
||||
const response = await axiosInstance.delete(`/api/v1/oauth2/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const create_oauth2 = async (data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post<OAuth2Entity>("/api/v1/oauth2", data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const update_oauth2 = async (id: number, data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post<OAuth2Entity>(`/api/v1/oauth2/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
export const get_authorize_url = async (data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post('/api/v1/oauth2-authorize-url', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
export interface OAuth2Tokens {
|
||||
access_token: string;
|
||||
account_id: string;
|
||||
created_at: number;
|
||||
oauth2_name: string;
|
||||
refresh_token: string;
|
||||
updated_at: number;
|
||||
}
|
||||
|
||||
export const get_oauth2_tokens = async (accountId: number) => {
|
||||
const response = await axiosInstance.get<OAuth2Tokens>(`/api/v1/oauth2-tokens/${accountId}`);
|
||||
return response.data;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
import { EmailEnvelope, PaginatedResponse } from "..";
|
||||
|
||||
export const search_messages = async (payload: Record<string, any>) => {
|
||||
const response = await axiosInstance.post<PaginatedResponse<EmailEnvelope>>("/api/v1/search-messages", payload);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export interface TagCount {
|
||||
tag: string;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export const get_top_tags = async () => {
|
||||
const response = await axiosInstance.get<TagCount[]>("/api/v1/all-tags");
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const update_tags = async (data: Record<string, any>) => {
|
||||
const response = await axiosInstance.post("/api/v1/update-tags", data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// Copyright (c) 2025 rustmailer.com (https://rustmailer.com)
|
||||
//
|
||||
// This file is part of the Bichon Email Archiving Project
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import axiosInstance from "@/api/axiosInstance";
|
||||
import { Proxy } from "@/features/settings/proxy/data/schema";
|
||||
|
||||
export interface Release {
|
||||
tag_name: string;
|
||||
published_at: string;
|
||||
body: string;
|
||||
html_url: string;
|
||||
}
|
||||
|
||||
export interface ReleaseNotification {
|
||||
latest: Release | null; // `latest` can be null if the release information is not available
|
||||
is_newer: boolean;
|
||||
error_message: string | null; // New field to store error message when the request fails
|
||||
}
|
||||
|
||||
interface Notifications {
|
||||
release: ReleaseNotification;
|
||||
}
|
||||
|
||||
export const get_notifications = async () => {
|
||||
const response = await axiosInstance.get<Notifications>(`/api/v1/notifications`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export interface DashboardStats {
|
||||
account_count: number; // Number of accounts
|
||||
email_count: number; // Total number of emails
|
||||
total_size_bytes: number; // Total size of all emails (in bytes)
|
||||
storage_usage_bytes: number; // Actual storage used (in bytes)
|
||||
index_usage_bytes: number; // Index storage size (in bytes)
|
||||
recent_activity: TimeBucket[]; // Email activity over recent days
|
||||
top_senders: Group[]; // Top 10 senders
|
||||
top_accounts: Group[]; // Top 10 senders
|
||||
with_attachment_count: number; // Emails with attachments
|
||||
without_attachment_count: number; // Emails without attachments
|
||||
top_largest_emails: LargestEmail[]; // Top 10 largest emails
|
||||
}
|
||||
|
||||
export interface TimeBucket {
|
||||
timestamp_ms: number; // Timestamp in milliseconds
|
||||
count: number; // Number of emails in this time bucket
|
||||
}
|
||||
|
||||
export interface Group {
|
||||
key: string; // Sender email or name
|
||||
count: number; // Number of emails from this sender
|
||||
}
|
||||
|
||||
export interface LargestEmail {
|
||||
subject: string; // Email subject
|
||||
size_bytes: number; // Email size in bytes
|
||||
}
|
||||
|
||||
export const get_dashboard_stats = async () => {
|
||||
const response = await axiosInstance.get<DashboardStats>(`/api/v1/dashboard-stats`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const list_proxy = async () => {
|
||||
const response = await axiosInstance.get<Proxy[]>(`/api/v1/list-proxy`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const delete_proxy = async (id: number) => {
|
||||
const response = await axiosInstance.delete(`/api/v1/proxy/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const update_proxy = async (id: number, url: string) => {
|
||||
const response = await axiosInstance.post(`/api/v1/proxy/${id}`, url, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const add_proxy = async (url: string) => {
|
||||
const response = await axiosInstance.post(`/api/v1/proxy`, url, {
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
Reference in New Issue
Block a user