Hầu hết các công cụ email AI chỉ là wrapper đơn giản. Tutorial này hướng dẫn bạn xây từ đầu — một assistant đọc email, soạn reply theo giọng văn của bạn, tóm tắt thread và gửi qua email API thực.
Cuối bài bạn sẽ có ứng dụng Node.js tích hợp OpenAI cho tác vụ ngôn ngữ và Resend để gửi email.
Bạn Sẽ Xây Gì
CLI email assistant có thể:
- Tóm tắt email thread dài thành các điểm chính
- Soạn reply phù hợp ngữ cảnh theo đúng giọng văn
- Phân loại email đến theo mức độ ưu tiên
- Gửi email bằng lập trình qua Resend API
Yêu Cầu
- Node.js 18 trở lên
- OpenAI API key
- Tài khoản Resend (gói miễn phí được)
- Domain đã xác minh trong Resend
Bước 1: Cài Đặt Project
mkdir ai-email-assistant && cd ai-email-assistant
npm init -y
npm install openai resend dotenv zodTạo file .env:
OPENAI_API_KEY=your-openai-key
RESEND_API_KEY=your-resend-key
FROM_EMAIL=ban@domain.comBước 2: Email Summarizer
Tóm tắt thread email dài thành các điểm hành động:
import OpenAI from 'openai'
const client = new OpenAI()
export async function summarizeEmail(emailContent: string): Promise<string> {
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: `Bạn là chuyên gia tóm tắt email. Trích xuất:
1. Chủ đề chính trong một câu
2. Quyết định hoặc yêu cầu quan trọng (bullet points)
3. Hành động cần thực hiện và deadline
4. Những người quan trọng được đề cập
Ngắn gọn, tập trung vào thông tin có thể hành động.`
},
{
role: 'user',
content: `Tóm tắt email thread này:\n\n${emailContent}`
}
],
max_tokens: 500
})
return response.choices[0].message.content ?? ''
}Bước 3: Reply Drafter
Soạn reply phù hợp ngữ cảnh theo tone được chỉ định:
interface DraftReplyOptions {
emailThread: string
tone: 'professional' | 'friendly' | 'concise'
keyPoints: string[]
senderName: string
}
export async function draftReply(options: DraftReplyOptions): Promise<string> {
const { emailThread, tone, keyPoints, senderName } = options
const toneGuide = {
professional: 'trang trọng, lịch sự, phù hợp môi trường công sở',
friendly: 'thân thiện, gần gũi, vẫn chuyên nghiệp',
concise: 'ngắn gọn, trực tiếp, không dài dòng — đi thẳng vào vấn đề'
}
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: `Bạn soạn thảo email reply. Tone: ${toneGuide[tone]}.
Luôn gọi tên người nhận.
Cấu trúc: lời chào → nội dung chính → bước tiếp theo rõ ràng → kết thúc.
Không dùng placeholder text.`
},
{
role: 'user',
content: `Soạn reply cho email thread từ ${senderName}.
Các điểm cần đề cập:
${keyPoints.map(p => `- ${p}`).join('\n')}
Thread gốc:
${emailThread}`
}
],
max_tokens: 800
})
return response.choices[0].message.content ?? ''
}Bước 4: Priority Classifier
Tự động phân loại email theo mức độ khẩn cấp:
import { z } from 'zod'
const ClassificationSchema = z.object({
priority: z.enum(['urgent', 'normal', 'low']),
category: z.enum(['action-required', 'fyi', 'newsletter', 'spam', 'meeting']),
reasoning: z.string()
})
export async function classifyEmail(emailContent: string) {
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'Phân loại email theo priority và category. Chỉ trả về JSON.'
},
{
role: 'user',
content: `Phân loại email này và trả JSON theo schema:
{ priority: "urgent"|"normal"|"low", category: "action-required"|"fyi"|"newsletter"|"spam"|"meeting", reasoning: string }
Email: ${emailContent}`
}
],
response_format: { type: 'json_object' }
})
const parsed = JSON.parse(response.choices[0].message.content ?? '{}')
return ClassificationSchema.parse(parsed)
}Bước 5: Gửi Email Với Resend
Kết nối Resend API để gửi email bằng lập trình:
import { Resend } from 'resend'
const resend = new Resend(process.env.RESEND_API_KEY)
export async function sendEmail(options: {
to: string
subject: string
body: string
replyTo?: string
}) {
const { to, subject, body, replyTo } = options
const { data, error } = await resend.emails.send({
from: process.env.FROM_EMAIL!,
to,
subject,
text: body,
replyTo
})
if (error) throw new Error(`Gửi email thất bại: ${error.message}`)
return data
}Bước 6: CLI Interface
Kết hợp tất cả thành CLI có thể dùng được:
import * as readline from 'readline'
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
const question = (prompt: string): Promise<string> =>
new Promise(resolve => rl.question(prompt, resolve))
async function main() {
console.log('AI Email Assistant\n')
const action = await question('Chọn hành động (summarize/draft/classify): ')
const emailContent = await question('Dán nội dung email:\n')
if (action === 'summarize') {
const summary = await summarizeEmail(emailContent)
console.log('\nTóm tắt:\n', summary)
} else if (action === 'draft') {
const tone = await question('Tone (professional/friendly/concise): ') as any
const points = await question('Các điểm cần đề cập (cách nhau bằng dấu phẩy): ')
const sender = await question('Tên người gửi: ')
const draft = await draftReply({
emailThread: emailContent,
tone,
keyPoints: points.split(',').map(p => p.trim()),
senderName: sender
})
console.log('\nBản nháp:\n', draft)
} else if (action === 'classify') {
const result = await classifyEmail(emailContent)
console.log('\nPhân loại:', JSON.stringify(result, null, 2))
}
rl.close()
}
main().catch(console.error)Mở Rộng Thêm
Kết nối hộp thư thực. Dùng Gmail API hoặc IMAP để đọc email tự động thay vì paste thủ công.
Thêm web UI. Bọc các functions trong Next.js API route và xây dashboard đơn giản để quản lý drafts.
Tinh chỉnh giọng văn. Cung cấp ví dụ email cũ của bạn cho system prompt để AI bắt chước phong cách viết chính xác hơn.
Giới hạn rate cẩn thận. Mỗi email xử lý tốn API calls. Với volume cao, batch emails và cache classifications.