v2.4.6
1、优化初始化设置时的操作说明 2、发件人和发件时间修复 3、发件空指针异常修复
This commit is contained in:
parent
89c24884f2
commit
7a3d056e77
@ -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) {
|
||||
|
||||
@ -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>
|
||||
@ -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"
|
||||
|
||||
@ -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()
|
||||
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(),
|
||||
}
|
||||
|
||||
if sqlerr != nil || emailId <= 0 {
|
||||
_, 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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
server/utils/ip/ip.go
Normal file
32
server/utils/ip/ip.go
Normal file
@ -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]"
|
||||
}
|
||||
@ -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
|
||||
})
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user