Sfoglia il codice sorgente

v2.4.6

1、优化初始化设置时的操作说明
2、发件人和发件时间修复
3、发件空指针异常修复
jinnrry 1 anno fa
parent
commit
7a3d056e77

+ 2 - 0
fe/src/i18n/i18n.js

@@ -86,6 +86,7 @@ var lang = {
     "move":"Move to group",
     "del_rule_confirm":"Are you sure to delete this?",
     "rule_params":"Executed params",
+    "autoSSLWarn":"PMail is not currently running on port 80. If you want PMail to manage SSL certificates automatically, please forward the /.well-known/* route to PMail. See https://github.com/Jinnrry/PMail/issues/94 for details."
 };
 
 
@@ -178,6 +179,7 @@ var zhCN = {
     "move":"移动分组",
     "del_rule_confirm":"确定要删除吗?",
     "rule_params":"执行参数",
+    "autoSSLWarn":"PMail当前未使用80端口启动,如果想要PMail自动管理SSL证书,请将/.well-known/*路由转发到PMail。 详见https://github.com/Jinnrry/PMail/issues/94"
 }
 
 switch (navigator.language) {

+ 12 - 4
fe/src/views/SetupView.vue

@@ -95,8 +95,8 @@
             </div>
         </div>
 
-
         <div v-if="active == 4" class="ctn_s">
+
             <div class="desc">
                 <h2>{{ lang.setDNS }}</h2>
                 <div style="margin-top: 10px;">{{ lang.dns_desc }}</div>
@@ -121,6 +121,10 @@
             </div>
         </div>
 
+        <el-alert  :closable="false" title="Warning!" type="error"  center  v-if="active == 5 && sslSettings.type == 0 && port != 80 " 
+                    :description="lang.autoSSLWarn"
+                />
+
         <div v-if="active == 5" class="ctn">
             <div class="desc">
                 <h2>{{ lang.setSSL }}</h2>
@@ -142,9 +146,11 @@
                     <el-form-item :label="lang.ssl_crt_path" v-if="sslSettings.type == '1'">
                         <el-input placeholder="./config/ssl/public.crt" v-model="sslSettings.crt_path"></el-input>
                     </el-form-item>
-
                 </el-form>
+
+
             </div>
+
         </div>
 
         <el-button v-loading.fullscreen.lock="fullscreenLoading" id="next" style="margin-top: 12px" @click="next">{{
@@ -192,6 +198,8 @@ const fullscreenLoading = ref(false)
 const dnsInfos = ref([
 ])
 
+const port = ref(80)
+
 const setPassword = () => {
     if (adminSettings.hadSeted) {
         active.value++;
@@ -279,7 +287,8 @@ const getSSLConfig = () => {
         if (res.errorNo != 0) {
             ElMessage.error(res.errorMsg)
         } else {
-            sslSettings.type = res.data
+            sslSettings.type = res.data.type
+            port.value = res.data.port
         }
     })
 }
@@ -368,6 +377,5 @@ const next = () => {
     flex-direction: column;
 
 }
-
 #next {}
 </style>

+ 9 - 0
server/config/config.go

@@ -33,6 +33,15 @@ type Config struct {
 	WebPushToken         string            `json:"webPushToken"`
 	Tables               map[string]string `json:"-"`
 	TablesInitData       map[string]string `json:"-"`
+	setupPort            int               // 初始化阶段端口
+}
+
+func (c *Config) GetSetupPort() int {
+	return c.setupPort
+}
+
+func (c *Config) SetSetupPort(setupPort int) {
+	c.setupPort = setupPort
 }
 
 const DBTypeMySQL = "mysql"

+ 42 - 27
server/controllers/email/send.go

@@ -1,9 +1,11 @@
 package email
 
 import (
+	"database/sql"
 	"encoding/base64"
 	"encoding/json"
 	log "github.com/sirupsen/logrus"
+	"github.com/spf13/cast"
 	"io"
 	"net/http"
 	"pmail/config"
@@ -13,6 +15,7 @@ import (
 	"pmail/hooks"
 	"pmail/hooks/framework"
 	"pmail/i18n"
+	"pmail/models"
 	"pmail/utils/async"
 	"pmail/utils/context"
 	"pmail/utils/send"
@@ -107,6 +110,18 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 		Name:         reqData.From.Name,
 		EmailAddress: reqData.From.Email,
 	}
+	if reqData.Sender.Email != "" {
+		e.Sender = &parsemail.User{
+			Name:         reqData.Sender.Name,
+			EmailAddress: reqData.Sender.Email,
+		}
+	} else {
+		e.Sender = &parsemail.User{
+			Name:         reqData.From.Name,
+			EmailAddress: reqData.From.Email,
+		}
+	}
+
 	e.Text = []byte(reqData.Text)
 	e.HTML = []byte(reqData.HTML)
 	e.Subject = reqData.Subject
@@ -138,36 +153,36 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 	}
 	log.WithContext(ctx).Debugf("插件执行--SendBefore End")
 
-	// 邮件落库
-	sql := "INSERT INTO email (type,subject, reply_to, from_name, from_address, `to`, bcc, cc, text, html, sender, attachments,spf_check, dkim_check, create_time,send_user_id,error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
-	sqlRes, sqlerr := db.Instance.Exec(db.WithContext(ctx, sql),
-		1,
-		e.Subject,
-		json2string(e.ReplyTo),
-		e.From.Name,
-		e.From.EmailAddress,
-		json2string(e.To),
-		json2string(e.Bcc),
-		json2string(e.Cc),
-		e.Text,
-		e.HTML,
-		json2string(e.Sender),
-		json2string(e.Attachments),
-		1,
-		1,
-		time.Now(),
-		ctx.UserID,
-		"",
-	)
-	emailId, _ := sqlRes.LastInsertId()
-
-	if sqlerr != nil || emailId <= 0 {
+	modelEmail := models.Email{
+		Type:        1,
+		Subject:     e.Subject,
+		ReplyTo:     json2string(e.ReplyTo),
+		FromName:    e.From.Name,
+		FromAddress: e.From.EmailAddress,
+		To:          json2string(e.To),
+		Bcc:         json2string(e.Bcc),
+		Cc:          json2string(e.Cc),
+		Text:        sql.NullString{String: string(e.Text), Valid: true},
+		Html:        sql.NullString{String: string(e.HTML), Valid: true},
+		Sender:      json2string(e.Sender),
+		Attachments: json2string(e.Attachments),
+		SPFCheck:    1,
+		DKIMCheck:   1,
+		SendUserID:  ctx.UserID,
+		SendDate:    time.Now(),
+		Status:      1,
+		CreateTime:  time.Now(),
+	}
+
+	_, err = db.Instance.Insert(&modelEmail)
+
+	if err != nil || modelEmail.Id <= 0 {
 		log.Println("mysql insert error:", err.Error())
 		response.NewErrorResponse(response.ServerError, i18n.GetText(ctx.Lang, "send_fail"), err.Error()).FPrint(w)
 		return
 	}
 
-	e.MessageId = emailId
+	e.MessageId = cast.ToInt64(modelEmail.Id)
 
 	async.New(ctx).Process(func(p any) {
 		errMsg := ""
@@ -189,12 +204,12 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 
 		if err != nil {
 			errMsg = err.Error()
-			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =2 ,error=? where id = ? "), errMsg, emailId)
+			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =2 ,error=? where id = ? "), errMsg, modelEmail.Id)
 			if err != nil {
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 			}
 		} else {
-			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =1  where id = ? "), emailId)
+			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =1  where id = ? "), modelEmail.Id)
 			if err != nil {
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 			}

+ 10 - 1
server/controllers/setup.go

@@ -26,6 +26,11 @@ func AcmeChallenge(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+type sslResponse struct {
+	Port int    `json:"port"`
+	Type string `json:"type"`
+}
+
 func Setup(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 	reqBytes, err := io.ReadAll(req.Body)
 	if err != nil {
@@ -121,7 +126,11 @@ func Setup(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 
 	if reqData["step"] == "ssl" && reqData["action"] == "get" {
 		sslType := ssl.GetSSL()
-		response.NewSuccessResponse(sslType).FPrint(w)
+		res := sslResponse{
+			Type: sslType,
+			Port: config.Instance.GetSetupPort(),
+		}
+		response.NewSuccessResponse(res).FPrint(w)
 		return
 	}
 

+ 9 - 2
server/http_server/setup_server.go

@@ -6,12 +6,12 @@ import (
 	log "github.com/sirupsen/logrus"
 	"io/fs"
 	"net/http"
+	"pmail/config"
 	"pmail/controllers"
+	"pmail/utils/ip"
 	"time"
 )
 
-var ip string
-
 // 项目初始化引导用的服务,初始化引导结束后即退出
 var setupServer *http.Server
 
@@ -29,7 +29,14 @@ func SetupStart() {
 	HttpPort := 80
 	flag.IntVar(&HttpPort, "p", 80, "初始化阶段Http服务端口")
 	flag.Parse()
+	config.Instance.SetSetupPort(HttpPort)
 	log.Infof("HttpServer Start On Port :%d", HttpPort)
+	if HttpPort == 80 {
+		log.Infof("Please click http://%s to continue.\n", ip.GetIp())
+	} else {
+		log.Infof("Please click http://%s:%d to continue.", ip.GetIp(), HttpPort)
+	}
+
 	setupServer = &http.Server{
 		Addr:         fmt.Sprintf(":%d", HttpPort),
 		Handler:      mux,

+ 0 - 1
server/res_init/init.go

@@ -23,7 +23,6 @@ func Init(serverVersion string) {
 	if !config.IsInit {
 		dirInit()
 
-		log.Infof("Please click http://127.0.0.1 to continue.\n")
 		go http_server.SetupStart()
 		<-signal.InitChan
 		http_server.SetupStop()

+ 3 - 24
server/services/setup/dns.go

@@ -1,14 +1,12 @@
 package setup
 
 import (
-	"encoding/json"
 	"fmt"
-	"io"
-	"net/http"
 	"pmail/i18n"
 	"pmail/services/auth"
 	"pmail/utils/context"
 	"pmail/utils/errors"
+	"pmail/utils/ip"
 )
 
 type DNSItem struct {
@@ -26,30 +24,11 @@ func GetDNSSettings(ctx *context.Context) ([]*DNSItem, error) {
 	}
 
 	ret := []*DNSItem{
-		{Type: "A", Host: "smtp", Value: getIp(), TTL: 3600, Tips: i18n.GetText(ctx.Lang, "ip_taps")},
-		{Type: "A", Host: "pop", Value: getIp(), TTL: 3600, Tips: i18n.GetText(ctx.Lang, "ip_taps")},
+		{Type: "A", Host: "smtp", Value: ip.GetIp(), TTL: 3600, Tips: i18n.GetText(ctx.Lang, "ip_taps")},
+		{Type: "A", Host: "pop", Value: ip.GetIp(), TTL: 3600, Tips: i18n.GetText(ctx.Lang, "ip_taps")},
 		{Type: "MX", Host: "-", Value: fmt.Sprintf("smtp.%s", configData.Domain), TTL: 3600},
 		{Type: "TXT", Host: "-", Value: "v=spf1 a mx ~all", TTL: 3600},
 		{Type: "TXT", Host: "default._domainkey", Value: auth.DkimGen(), TTL: 3600},
 	}
 	return ret, nil
 }
-
-func getIp() string {
-	resp, err := http.Get("http://ip-api.com/json/?lang=zh-CN ")
-	if err != nil {
-		return "Your Server IP"
-	}
-	defer resp.Body.Close()
-
-	if resp.StatusCode == 200 {
-		body, err := io.ReadAll(resp.Body)
-		if err == nil {
-			var queryRes map[string]string
-			_ = json.Unmarshal(body, &queryRes)
-
-			return queryRes["query"]
-		}
-	}
-	return "Your Server IP"
-}

+ 32 - 0
server/utils/ip/ip.go

@@ -0,0 +1,32 @@
+package ip
+
+import (
+	"encoding/json"
+	"io"
+	"net/http"
+)
+
+var ip string
+
+func GetIp() string {
+	if ip != "" {
+		return ip
+	}
+
+	resp, err := http.Get("http://ip-api.com/json/?lang=zh-CN ")
+	if err != nil {
+		return "[Your Server IP]"
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode == 200 {
+		body, err := io.ReadAll(resp.Body)
+		if err == nil {
+			var queryRes map[string]string
+			_ = json.Unmarshal(body, &queryRes)
+			ip = queryRes["query"]
+			return queryRes["query"]
+		}
+	}
+	return "[Your Server IP]"
+}

+ 6 - 1
server/utils/send/send.go

@@ -188,7 +188,12 @@ func Send(ctx *context.Context, e *parsemail.Email) (error, map[string]error) {
 
 	orgMap := map[string]error{}
 	errMap.Range(func(key, value any) bool {
-		orgMap[key.(string)] = value.(error)
+		if value != nil {
+			orgMap[key.(string)] = value.(error)
+		}else {
+			orgMap[key.(string)] = nil
+		}
+
 		return true
 	})