chore: initial import 萌邮 MengPost (React+Vite + Go+Gin)
Made-with: Cursor
This commit is contained in:
61
mengpost-backend/handlers/account.go
Normal file
61
mengpost-backend/handlers/account.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"mengpost-backend/models"
|
||||
)
|
||||
|
||||
func ListAccounts(c *gin.Context) {
|
||||
list, err := models.ListAccounts()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, list)
|
||||
}
|
||||
|
||||
func CreateAccount(c *gin.Context) {
|
||||
var a models.Account
|
||||
if err := c.ShouldBindJSON(&a); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if a.Email == "" || a.Password == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "email 和 password 必填"})
|
||||
return
|
||||
}
|
||||
if err := models.CreateAccount(&a); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
a.Password = ""
|
||||
c.JSON(http.StatusOK, a)
|
||||
}
|
||||
|
||||
func UpdateAccount(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
var a models.Account
|
||||
if err := c.ShouldBindJSON(&a); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
a.ID = id
|
||||
if err := models.UpdateAccount(&a); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
func DeleteAccount(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err := models.DeleteAccount(id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
27
mengpost-backend/handlers/auth.go
Normal file
27
mengpost-backend/handlers/auth.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"mengpost-backend/config"
|
||||
)
|
||||
|
||||
// VerifyToken 供前端 token 弹窗使用: 仅返回 token 是否正确.
|
||||
func VerifyToken(cfg *config.Config) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var body struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid body"})
|
||||
return
|
||||
}
|
||||
if body.Token != cfg.Token {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"ok": false})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
}
|
||||
111
mengpost-backend/handlers/email.go
Normal file
111
mengpost-backend/handlers/email.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"mengpost-backend/models"
|
||||
"mengpost-backend/services"
|
||||
)
|
||||
|
||||
func getAccount(c *gin.Context) *models.Account {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
acc, err := models.GetAccount(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "account not found"})
|
||||
return nil
|
||||
}
|
||||
return acc
|
||||
}
|
||||
|
||||
// GET /api/accounts/:id/mailboxes
|
||||
func ListMailboxes(c *gin.Context) {
|
||||
acc := getAccount(c)
|
||||
if acc == nil {
|
||||
return
|
||||
}
|
||||
boxes, err := services.ListMailboxes(acc)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, boxes)
|
||||
}
|
||||
|
||||
// GET /api/accounts/:id/messages?mailbox=INBOX&limit=30
|
||||
func ListMessages(c *gin.Context) {
|
||||
acc := getAccount(c)
|
||||
if acc == nil {
|
||||
return
|
||||
}
|
||||
mailbox := c.DefaultQuery("mailbox", "INBOX")
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "30"))
|
||||
list, err := services.FetchMessages(acc, mailbox, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, list)
|
||||
}
|
||||
|
||||
// GET /api/accounts/:id/messages/:uid?mailbox=INBOX
|
||||
func GetMessage(c *gin.Context) {
|
||||
acc := getAccount(c)
|
||||
if acc == nil {
|
||||
return
|
||||
}
|
||||
uid64, _ := strconv.ParseUint(c.Param("uid"), 10, 32)
|
||||
mailbox := c.DefaultQuery("mailbox", "INBOX")
|
||||
detail, err := services.FetchMessage(acc, mailbox, uint32(uid64))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, detail)
|
||||
}
|
||||
|
||||
// POST /api/accounts/:id/send
|
||||
func SendMessage(c *gin.Context) {
|
||||
acc := getAccount(c)
|
||||
if acc == nil {
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
To string `json:"to"`
|
||||
Subject string `json:"subject"`
|
||||
Body string `json:"body"`
|
||||
HTML bool `json:"html"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
log := &models.SentLog{AccountID: acc.ID, To: body.To, Subject: body.Subject, Body: body.Body}
|
||||
if err := services.SendMail(acc, body.To, body.Subject, body.Body, body.HTML); err != nil {
|
||||
log.Status = "failed"
|
||||
log.Error = err.Error()
|
||||
_ = models.AddSentLog(log)
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
log.Status = "ok"
|
||||
_ = models.AddSentLog(log)
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
// GET /api/accounts/:id/sent?limit=50
|
||||
func ListSentLogs(c *gin.Context) {
|
||||
acc := getAccount(c)
|
||||
if acc == nil {
|
||||
return
|
||||
}
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))
|
||||
list, err := models.ListSentLogs(acc.ID, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, list)
|
||||
}
|
||||
Reference in New Issue
Block a user