MailDrop 是一款以 Tauri 2 + Vue 3 開發的桌面 Email 測試工具,定位接近 MailHog / Mailpit。它會在本機啟動 SMTP server,接收開發環境送出的 email,並提供桌面 UI 檢視信件內容、原始 MIME、HTML/Text 版本與基本收件紀錄。
目前專案以 Windows 桌面使用情境為主,適合後端或整合測試時取代真實 SMTP 服務,避免測試信件外送到正式信箱。
- 本機 SMTP server,預設監聽
127.0.0.1:1025 - 收件清單與信件詳情檢視
- HTML / Text / Raw MIME 分頁預覽
- 搜尋、刪除單封信、清空全部信件
- SQLite 本機保存收件資料
- 可設定 SMTP port、主題模式與最大保存信件數
- 收到新信時透過 Tauri event 即時更新 UI
- System tray 與 close-to-tray 行為
- Single instance,重複啟動時聚焦既有視窗
| Layer | Tech |
|---|---|
| Desktop shell | Tauri 2 |
| Frontend | Vue 3, TypeScript, Vite |
| State | Pinia |
| UI | Tailwind CSS v4, scoped CSS, Lucide icons |
| Backend | Rust, Tokio |
| SMTP / MIME | Custom SMTP session handling, mail-parser |
| Database | SQLite via rusqlite + r2d2_sqlite |
- Node.js / npm
- Rust toolchain
- Tauri 2 系統依賴
- Windows 開發時需安裝 WebView2 Runtime
- 啟動 MailDrop:
npm install
npm run start- 確認 SMTP server 使用預設設定:
host: 127.0.0.1
port: 1025
secure: false
auth: none
- 在要測試的應用程式中,將 SMTP 設定指向 MailDrop。寄出測試信後,信件會出現在 MailDrop inbox。
若專案使用 spring-boot-starter-mail,開發環境可在 application-dev.yml 設定:
spring:
mail:
host: 127.0.0.1
port: 1025
username:
password:
properties:
mail:
smtp:
auth: false
starttls:
enable: false使用 .properties 格式則可寫成:
spring.mail.host=127.0.0.1
spring.mail.port=1025
spring.mail.username=
spring.mail.password=
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.starttls.enable=false簡單寄信範例:
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@Service
public class MailTestService {
private final JavaMailSender mailSender;
public MailTestService(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendTestMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("dev@example.com");
message.setTo("test@example.com");
message.setSubject("MailDrop test");
message.setText("Hello from Spring Boot");
mailSender.send(message);
}
}HTML email 可使用 MimeMessageHelper:
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
@Service
public class HtmlMailTestService {
private final JavaMailSender mailSender;
public HtmlMailTestService(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendHtmlMail() throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, "UTF-8");
helper.setFrom("dev@example.com");
helper.setTo("test@example.com");
helper.setSubject("MailDrop HTML test");
helper.setText("<strong>Hello from Spring Boot</strong>", true);
mailSender.send(message);
}
}若 Spring Boot 版本仍使用 javax.mail,請將 import 改為 javax.mail.* 對應套件。
npm install
npm run startnpm run start 會執行 tauri dev,並依照 src-tauri/tauri.conf.json 先啟動 Vite dev server。
若只需要啟動前端開發伺服器:
npm run dev建立前端 production bundle:
npm run build打包桌面應用(不含簽署,僅用於一般功能測試):
npm run pack打包並簽署(含 updater .sig 檔,自動更新功能需要此版本):
npm run pack:signedMailDrop 的版本號需要同時出現在三個位置:
package.jsonsrc-tauri/Cargo.tomlsrc-tauri/tauri.conf.json
請使用下列指令同步更新版本:
npm run version:set -- 0.1.1建立 GitHub Release 的建議流程:
npm run version:set -- 0.1.1
git add package.json src-tauri/Cargo.toml src-tauri/tauri.conf.json
git commit -m "chore(release): bump version to 0.1.1"
git tag v0.1.1
git push origin main --tags推送 v* tag 後,GitHub Actions 會執行 .github/workflows/release.yml,打包 Tauri 應用程式並更新 GitHub Releases。
自動更新需要 Tauri updater 簽章。公鑰已寫入 src-tauri/tauri.conf.json,私鑰請放到 GitHub repository secrets:
| Secret | 說明 |
|---|---|
TAURI_SIGNING_PRIVATE_KEY |
src-tauri/updater-keys/maildrop.key 的檔案內容(私鑰已 gitignore,請妥善保管) |
TAURI_SIGNING_PRIVATE_KEY_PASSWORD |
簽章密碼;目前 key 未設定密碼,可留空 |
應用程式會檢查:
https://github.com/Racious/MailDrop/releases/latest/download/latest.json
Settings 裡可切換啟動時檢查更新、自動安裝更新,也可手動檢查更新或開啟 Releases 頁面。
啟動 MailDrop 後,讓測試程式將 SMTP host 指向:
host: 127.0.0.1
port: 1025
例如使用 Nodemailer:
import nodemailer from 'nodemailer'
const transporter = nodemailer.createTransport({
host: '127.0.0.1',
port: 1025,
secure: false,
})
await transporter.sendMail({
from: 'dev@example.com',
to: 'test@example.com',
subject: 'MailDrop test',
text: 'Hello from MailDrop',
html: '<strong>Hello from MailDrop</strong>',
})或使用 swaks:
swaks --server 127.0.0.1:1025 --from dev@example.com --to test@example.com --data "Subject: MailDrop test\n\nHello from MailDrop"MailDrop/
├─ src/ # Vue frontend
│ ├─ components/
│ │ ├─ inbox/ # Mail list, toolbar, list item
│ │ ├─ layout/ # App shell and sidebar
│ │ ├─ preview/ # HTML/Text/Raw preview
│ │ └─ ui/ # Shared UI components
│ ├─ composables/ # Tauri event and theme hooks
│ ├─ lib/tauri.ts # Frontend invoke wrappers
│ ├─ stores/ # Pinia stores
│ ├─ types/ # TypeScript models
│ └─ views/SettingsView.vue # Settings page
├─ src-tauri/ # Rust backend and Tauri config
│ ├─ src/
│ │ ├─ commands/ # Tauri commands
│ │ ├─ db/ # SQLite pool, migrations, repository
│ │ ├─ models/ # Rust models serialized to frontend
│ │ ├─ smtp/ # SMTP server, session parser, MIME handling
│ │ ├─ tray/ # System tray setup
│ │ └─ lib.rs # Tauri setup and AppState
│ └─ tauri.conf.json
├─ scripts/ # 工具腳本(版本管理、簽署包版)
├─ docs/ # Planning / design notes
├─ public/
└─ package.json
MailDrop 會在 Tauri app data directory 建立 SQLite database:
<app-data-dir>/maildrop.db
啟動時會自動建立下列表:
mails:保存收件內容、寄件者、收件者、主旨、HTML/Text body、Raw MIME、大小與接收時間app_config:保存應用程式設定
預設設定:
| Key | Default |
|---|---|
smtp_port |
1025 |
theme |
system |
max_mails |
500 |
check_updates_on_startup |
true |
auto_install_updates |
false |
Frontend 透過 @tauri-apps/api/core 的 invoke() 呼叫 Rust commands。主要命令如下:
| Command | Purpose |
|---|---|
list_mails |
分頁取得信件摘要 |
get_mail |
取得單封信件詳情 |
delete_mail |
刪除單封信件 |
clear_mails |
清空全部信件 |
get_mail_count |
取得信件總數 |
get_config |
讀取設定 |
save_config |
保存設定 |
get_smtp_status |
取得 SMTP server 狀態 |
restart_app |
重新啟動應用程式 |
收到新信時,Rust backend 會 emit mail:received event,前端由 useMailEvents() 監聽並更新 Pinia store。
目前 SMTP session 支援開發測試所需的基本命令:
EHLO/HELOMAIL FROMRCPT TODATARSETNOOPQUITAUTHSTARTTLS
注意:AUTH 目前會直接視為成功,方便本機開發測試工具相容有送出帳密的 client。STARTTLS 會明確回覆 454 TLS not available,因為 MailDrop 目前不提供真正 TLS upgrade。開發環境請關閉 TLS / STARTTLS;本工具不應視為正式 SMTP server 安全實作。
New Features
- 新增 Windows 系統通知,收到新信時自動跳出 toast(可於 Settings → Notifications 關閉)
- 新增信件未讀狀態:未讀信件顯示藍點 + 加粗主旨,點開後自動標記已讀
- Sidebar Inbox badge 改為顯示未讀數量
Bug Fixes
- 修正 HTML 信件內連結點擊後在 MailDrop 內部顯示白頁的問題,現在會正確開啟系統瀏覽器
初始發布
- 本機 SMTP server(tokio 非同步,預設 port 1025)
- 收件匣虛擬捲動列表
- HTML / Text / Raw 三種郵件預覽模式
- HTML 預覽信件內連結自動開啟系統瀏覽器
- SQLite 本機保存,可設定最大保存信件數
- 可設定 SMTP port、主題模式(亮色 / 暗色 / 系統跟隨)
- SMTP 監聽失敗時顯示錯誤橫幅並引導至設定頁
- 變更 SMTP port 後提示重啟,支援一鍵自動重啟
- System tray 常駐,右鍵選單支援顯示視窗與結束程式
- Single instance,重複啟動時聚焦既有視窗
- 自動更新功能(Settings 可設定啟動時檢查、自動安裝)
- GitHub Actions 自動 build 並發布 Release
- SMTP port 變更後需要重新啟動應用程式才會生效。
- App 關閉視窗時預設隱藏到 system tray;請從 tray menu 或應用流程結束程式。
- HTML 預覽以 sandbox iframe 呈現;信件內的連結點擊後會自動開啟系統瀏覽器,不會在 MailDrop 內部導覽。
docs/vue-concurrent-scroll.md是早期企畫文件,目前存在編碼顯示問題;實作狀態請以程式碼與本 README 為準。