Explorar el Código

Merge branch 'master' of github.com:Jinnrry/PMail

jinnrry hace 1 año
padre
commit
fbd9645507

+ 8 - 0
fe/src/views/ListView.vue

@@ -40,6 +40,14 @@
                                 </el-tooltip>
                                 </el-tooltip>
                                 
                                 
                             </span>
                             </span>
+                            <span style="font-weight: 900;color: #FF0000;" v-if="scope.row.error != ''">
+                                <el-tooltip effect="dark" 
+                                :content="scope.row.error"
+                                    placement="top-start">
+                                    !
+                                </el-tooltip>
+                                
+                            </span>
                         </div>
                         </div>
                     </template>
                     </template>
                 </el-table-column>
                 </el-table-column>

+ 11 - 10
server/config/config.json

@@ -1,16 +1,17 @@
 {
 {
-  "logLevel": "debug",
-  "domain": "domain.com",
-  "webDomain": "mail.domain.com",
+  "logLevel": "",
+  "domain": "test.domain",
+  "domains": null,
+  "webDomain": "mail.test.domain",
   "dkimPrivateKeyPath": "config/dkim/dkim.priv",
   "dkimPrivateKeyPath": "config/dkim/dkim.priv",
-  "sslType": "0",
-  "SSLPrivateKeyPath": "config/ssl/private.key",
-  "SSLPublicKeyPath": "config/ssl/public.crt",
-  "dbDSN": "./config/pmail.db",
+  "sslType": "1",
+  "SSLPrivateKeyPath": "./config/ssl/private.key",
+  "SSLPublicKeyPath": "./config/ssl/public.crt",
+  "dbDSN": "./config/pmail_temp.db",
   "dbType": "sqlite",
   "dbType": "sqlite",
-  "spamFilterLevel": 1,
+  "httpsEnabled": 1,
+  "spamFilterLevel": 0,
   "httpPort": 80,
   "httpPort": 80,
   "httpsPort": 443,
   "httpsPort": 443,
-  "isInit": true,
-  "httpsEnabled": 1
+  "isInit": true
 }
 }

+ 25 - 25
server/config/ssl/private.key

@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
 -----END RSA PRIVATE KEY-----

+ 20 - 59
server/config/ssl/public.crt

@@ -1,61 +1,22 @@
 -----BEGIN CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
-MIIFFDCCA/ygAwIBAgISBNoMwrAFQkkwJmbpDuLTLHLiMA0GCSqGSIb3DQEBCwUA
-MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
-EwJSMzAeFw0yNDA0MTUwNTQ3MzlaFw0yNDA3MTQwNTQ3MzhaMBwxGjAYBgNVBAMT
-EXNtdHAuamlhbmd3ZWkub25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEAycVukHU+lPXo01d0W8ok0pxfy8/+tHKqd6gd9g1J6EOpf2SUvR77+URpKNXx
-MokVX84VHnBGxDMvh5hM8oN5gqbJEwhTqOwZi19MQVfI5a1wrkYep1+hcAS/MsLg
-wqxFp7ABsH2oljQLLYsGZTs/+QooDcmE2K+Nnj2nM5VZ9ouGX2ANPFMvSm1yuADm
-P4962xXEN730UfEamRTGsuU9U1g51cAUasblIf2RU9nKdEQsEihpApS45X2qayWg
-o3YJ6BAaqbZKmnekeIWkjlhHNYudNVxIqvp5MzndMPCNjfz/+xEcVn3hS5vzJMZQ
-eOPJjSes6E2Cr0X2cvXnQGUfzQIDAQABo4ICODCCAjQwDgYDVR0PAQH/BAQDAgWg
-MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0G
-A1UdDgQWBBS+FIEsLeo9FCo2y2tOmFUfhiv/LzAfBgNVHSMEGDAWgBQULrMXt1hW
-y65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUHMAGGFWh0dHA6
-Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3IzLmkubGVuY3Iu
-b3JnLzBBBgNVHREEOjA4ghFtYWlsLmppYW5nd2VpLm9uZYIQcG9wLmppYW5nd2Vp
-Lm9uZYIRc210cC5qaWFuZ3dlaS5vbmUwEwYDVR0gBAwwCjAIBgZngQwBAgEwggEE
-BgorBgEEAdZ5AgQCBIH1BIHyAPAAdgAZmBBxCfDWUi4wgNKeP2S7g24ozPkPUo7u
-385KPxa0ygAAAY7ggunqAAAEAwBHMEUCIFEMkK6C5zyorCJEM2nZqH75nkl6KQjI
-RUiwLpcoupL0AiEAtKRWHmGBfL+AtLkurTurZlFURZIsrTqrreOFzThnSHoAdgBI
-sONr2qZHNA/lagL6nTDrHFIBy1bdLIHZu7+rOdiEcwAAAY7ggunmAAAEAwBHMEUC
-IGqaf3PAFZnvoKac1ASRb9eRpaGp7m+x/+Z1siJYegCnAiEAsLQJO7QvX/dXe+Bq
-oCH1QhEqDFNhQLCavqrUyTi1wQ0wDQYJKoZIhvcNAQELBQADggEBABlSBbOwICT5
-zE+U4vyaeU0ufVSyjT7ZbohpMAJh8WK7zG7xj/XgAA0EX2LB62NVk3/3u/GF3uz6
-HsuCYUTsKY3MmwWttmwqWIxkMJk57j18J5vsJXW/YwqOz+v6h3QcUhUZW7c8Kl9I
-t9t20uTssCWJ2OLe3TtumjxKX9iqeQ5CD3GDLTJlKP3UJ6eFGN5E42JjnIxk9GH5
-yvqcPd9OHwDXbrA13Q6Xn7tdV8rzerGi/gGo18QvCtvH8wda/T+AUxRxXM9Ggit8
-ITBsP3PWuIDvECTdQ+Zbft9Ut6PxOBLSH3Gqtghe+Fn7XQpchODw+0LbLi1fOgrW
-8O+lguPxZ9w=
------END CERTIFICATE-----
-
------BEGIN CERTIFICATE-----
-MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
-TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
-cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
-WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
-RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
-AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
-R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
-sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
-NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
-Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
-/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
-AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
-Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
-FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
-AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
-Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
-gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
-PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
-ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
-CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
-lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
-avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
-yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
-yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
-hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
-HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
-MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
-nLRbwHOoq7hHwg==
+MIIDmTCCAoECFH0cnkhiRVka2ZAWxpjtD+JgCv2GMA0GCSqGSIb3DQEBCwUAMIGI
+MQswCQYDVQQGEwJDTjETMBEGA1UECAwKU29tZS1TdGF0ZTELMAkGA1UEBwwCQkox
+DjAMBgNVBAoMBVBNYWlsMQ4wDAYDVQQLDAVQTWFpbDEWMBQGA1UEAwwNKi50ZXN0
+LmRvbWFpbjEfMB0GCSqGSIb3DQEJARYQdGVzdEB0ZXN0LmRvbWFpbjAeFw0yNDA3
+MDUwODA5MTVaFw0zNDA3MDMwODA5MTVaMIGIMQswCQYDVQQGEwJDTjETMBEGA1UE
+CAwKU29tZS1TdGF0ZTELMAkGA1UEBwwCQkoxDjAMBgNVBAoMBVBNYWlsMQ4wDAYD
+VQQLDAVQTWFpbDEWMBQGA1UEAwwNKi50ZXN0LmRvbWFpbjEfMB0GCSqGSIb3DQEJ
+ARYQdGVzdEB0ZXN0LmRvbWFpbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAPbn/CpeOKV04CUs57Okr8kluCEV4fitVYvRReDUZNwcrDNJCADRVPlZh+3l
+f0JdReC68M2pbHrd0CLearARRQwPJnuNphdimF6iFVr3EoPtTDzzJFKW/YxDyQBD
+rTFVVij7uwJ7QnFnJjREoEjS1w7ezpO/4UPd44YlEM63r+juYzVb7H4skJ3HzLmh
+4t46EcaIxX6uOeHY7MDctAxrMGjfahfurhoAYHcHO7zgPNWM1Q5Yt9zQo8Kv0Y2L
+vHxSUmZVrb4GHQhKDnvaoZJy80AA98As3ZJJiCmT/4oIPHb4c+9S/uDVqg4WHtc5
+pAFy+mPArnKYltRawkWI6Q17ZOsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAIl8L
+nL+wICckIRTfO4K4+F+7UHgLI2iTYRic6Hsy3K0aPvZAdVJiOlz0qaEcce+bFzj7
+BZiHQWDgiPF4vNFqcmas4oFV+Au2K8AoYQFJrq+3dtiUaMStT7JkjNjci3C2NhPO
+U7Gjq2OJx6IrJr7ECr2SFW4Sstw/h+s/mBfNl2BbE7kmT1xu/lyxpIiT7bYgSk/l
+A3cJFE1JIoa7eUPpV4Kh0titwJnDYVfQmEeBNYivyeNwe4hiHtiZDamI6H7Wu95b
+ldRRiFELoVs0GCn/ttIaSFvGUPeahn9rTNUUkjp4Un0RxuQFx8umQYl50zt1GZ1X
+DICmWUwYYejqdXrrww==
 -----END CERTIFICATE-----
 -----END CERTIFICATE-----

+ 18 - 0
server/config/ssl/server.csr

@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICzjCCAbYCAQAwgYgxCzAJBgNVBAYTAkNOMRMwEQYDVQQIDApTb21lLVN0YXRl
+MQswCQYDVQQHDAJCSjEOMAwGA1UECgwFUE1haWwxDjAMBgNVBAsMBVBNYWlsMRYw
+FAYDVQQDDA0qLnRlc3QuZG9tYWluMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QHRlc3Qu
+ZG9tYWluMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9uf8Kl44pXTg
+JSzns6SvySW4IRXh+K1Vi9FF4NRk3BysM0kIANFU+VmH7eV/Ql1F4Lrwzalset3Q
+It5qsBFFDA8me42mF2KYXqIVWvcSg+1MPPMkUpb9jEPJAEOtMVVWKPu7AntCcWcm
+NESgSNLXDt7Ok7/hQ93jhiUQzrev6O5jNVvsfiyQncfMuaHi3joRxojFfq454djs
+wNy0DGswaN9qF+6uGgBgdwc7vOA81YzVDli33NCjwq/RjYu8fFJSZlWtvgYdCEoO
+e9qhknLzQAD3wCzdkkmIKZP/igg8dvhz71L+4NWqDhYe1zmkAXL6Y8CucpiW1FrC
+RYjpDXtk6wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAPSNiDkAGFhMWFzQns+a
+6+ujoI8Lf7baN/LklEEMRV2xq5sonj72ZU4PJDAyNFVj+pCKDOH5mb0r5ceRKYx/
+HOlXxYvDhvk3t9mAGrRwG3UhzbCSbIIcvdKbU4FDGaRIzrSsvcv9fUDnw5fKTL61
+IRDNewABlCncsUYfHrXeuMtqdiWyZMfYjiHDunCCo/FbrG70q9LjMHT4zHl9LV8T
+jnrQzX0UaxBgLYDPEJX+2fqaXObv1HHSWlgZ6Ov9eRRKN2oRkb+KIbaTnlQ7Z7Y9
+kzwla/WOKJDL5FA7275tVpC553+rglq/0Jy9Hiq71Sis9gnG8eTYsghN5FHZSMFT
+a1s=
+-----END CERTIFICATE REQUEST-----

+ 2 - 0
server/controllers/email/list.go

@@ -27,6 +27,7 @@ type emilItem struct {
 	IsRead    bool   `json:"is_read"`
 	IsRead    bool   `json:"is_read"`
 	Sender    User   `json:"sender"`
 	Sender    User   `json:"sender"`
 	Dangerous bool   `json:"dangerous"`
 	Dangerous bool   `json:"dangerous"`
+	Error     string `json:"error"`
 }
 }
 
 
 type User struct {
 type User struct {
@@ -83,6 +84,7 @@ func EmailList(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 			IsRead:    email.IsRead == 1,
 			IsRead:    email.IsRead == 1,
 			Sender:    sender,
 			Sender:    sender,
 			Dangerous: email.SPFCheck == 0 && email.DKIMCheck == 0,
 			Dangerous: email.SPFCheck == 0 && email.DKIMCheck == 0,
+			Error:     email.Error.String,
 		})
 		})
 	}
 	}
 
 

+ 17 - 0
server/controllers/email/send.go

@@ -213,11 +213,28 @@ func Send(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
 			if err != nil {
 			if err != nil {
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 			}
 			}
+
+			ue := models.UserEmail{
+				UserID:  ctx.UserID,
+				EmailID: modelEmail.Id,
+				Status:  2,
+				IsRead:  1,
+			}
+			db.Instance.Insert(&ue)
+
 		} else {
 		} else {
 			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =1  where id = ? "), modelEmail.Id)
 			_, err := db.Instance.Exec(db.WithContext(ctx, "update email set status =1  where id = ? "), modelEmail.Id)
 			if err != nil {
 			if err != nil {
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 				log.WithContext(ctx).Errorf("sql Error :%+v", err)
 			}
 			}
+
+			ue := models.UserEmail{
+				UserID:  ctx.UserID,
+				EmailID: modelEmail.Id,
+				Status:  1,
+				IsRead:  1,
+			}
+			db.Instance.Insert(&ue)
 		}
 		}
 
 
 	}, nil)
 	}, nil)

+ 1 - 1
server/controllers/group.go

@@ -31,7 +31,7 @@ func GetUserGroup(ctx *context.Context, w http.ResponseWriter, req *http.Request
 				},
 				},
 				{
 				{
 					Label: i18n.GetText(ctx.Lang, "outbox"),
 					Label: i18n.GetText(ctx.Lang, "outbox"),
-					Tag:   dto.SearchTag{Type: 1, Status: 1}.ToString(),
+					Tag:   dto.SearchTag{Type: 1, Status: -1}.ToString(),
 				},
 				},
 				{
 				{
 					Label: i18n.GetText(ctx.Lang, "sketch"),
 					Label: i18n.GetText(ctx.Lang, "sketch"),

+ 2 - 1
server/main_test.go

@@ -735,8 +735,9 @@ func testEmailList(t *testing.T) {
 		t.Error("Get Email List Api Error!")
 		t.Error("Get Email List Api Error!")
 	}
 	}
 	dt := data.Data.(map[string]interface{})
 	dt := data.Data.(map[string]interface{})
-	if len(dt["list"].([]interface{})) == 0 {
+	if dt["list"] == nil || len(dt["list"].([]interface{})) == 0 {
 		t.Error("Email List Is Empty!")
 		t.Error("Email List Is Empty!")
+		return
 	}
 	}
 
 
 	lst := dt["list"].([]interface{})
 	lst := dt["list"].([]interface{})

+ 2 - 2
server/models/user_email.go

@@ -2,8 +2,8 @@ package models
 
 
 type UserEmail struct {
 type UserEmail struct {
 	ID      int  `xorm:"id int unsigned not null pk autoincr"`
 	ID      int  `xorm:"id int unsigned not null pk autoincr"`
-	UserID  int  `xorm:"user_id int not null unique('uid_eid') index comment('用户id')"`
-	EmailID int  `xorm:"email_id not null unique('uid_eid') index comment('信件id')"`
+	UserID  int  `xorm:"user_id int not null index('idx_eid') index comment('用户id')"`
+	EmailID int  `xorm:"email_id not null index('idx_eid') index comment('信件id')"`
 	IsRead  int8 `xorm:"is_read tinyint(1) comment('是否已读')" json:"is_read"`
 	IsRead  int8 `xorm:"is_read tinyint(1) comment('是否已读')" json:"is_read"`
 	GroupId int  `xorm:"group_id int notnull default(0) comment('分组id')'" json:"group_id"`
 	GroupId int  `xorm:"group_id int notnull default(0) comment('分组id')'" json:"group_id"`
 	Status  int8 `xorm:"status tinyint(4) notnull default(0) comment('0未发送,1已发送,2发送失败,3删除')" json:"status"` // 0未发送,1已发送,2发送失败 3删除
 	Status  int8 `xorm:"status tinyint(4) notnull default(0) comment('0未发送,1已发送,2发送失败,3删除')" json:"status"` // 0未发送,1已发送,2发送失败 3删除

+ 1 - 1
server/services/detail/detail.go

@@ -37,7 +37,7 @@ func GetEmailDetail(ctx *context.Context, id int, markRead bool) (*response.Emai
 
 
 	if markRead && ue.IsRead == 0 {
 	if markRead && ue.IsRead == 0 {
 		ue.IsRead = 1
 		ue.IsRead = 1
-		_, err = db.Instance.Update(&ue)
+		_, err = db.Instance.Where("id=?", ue.ID).Update(&ue)
 		if err != nil {
 		if err != nil {
 			log.WithContext(ctx).Errorf("SQL error:%+v", err)
 			log.WithContext(ctx).Errorf("SQL error:%+v", err)
 		}
 		}

+ 20 - 13
server/utils/send/send.go

@@ -76,24 +76,28 @@ func Forward(ctx *context.Context, e *parsemail.Email, forwardAddress string) er
 		tos := tos
 		tos := tos
 		as.WaitProcess(func(p any) {
 		as.WaitProcess(func(p any) {
 			err := smtp.SendMail("", domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
 			err := smtp.SendMail("", domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
-			if err != nil {
-				log.WithContext(ctx).Warnf("SMTP Send Error! Error:%+v", err)
-			} else {
-				log.WithContext(ctx).Infof("SMTP Send Success !")
-			}
 
 
-			// 重新选取证书域名
+			// 使用其他方式发送
 			if err != nil {
 			if err != nil {
+				// EOF 表示未知错误,此时降级为非tls连接发送(目前仅139邮箱有这个问题)
+				if errors.Is(err, smtp.NoSupportSTARTTLSError) || err.Error() == "EOF" {
+					err = smtp.SendMailWithTls("", domain.mxHost+":465", nil, e.From.EmailAddress, buildAddress(tos), b)
+					if err != nil {
+						log.WithContext(ctx).Warnf("Unsafe! %s Server Not Support SMTPS & STARTTLS", domain.domain)
+						err = smtp.SendMailUnsafe("", domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
+					}
+				}
+
+				// 证书错误,从新选取证书发送
 				if certificateErr, ok := err.(*tls.CertificateVerificationError); ok {
 				if certificateErr, ok := err.(*tls.CertificateVerificationError); ok {
-					if hostnameErr, is := certificateErr.Err.(x509.HostnameError); is {
+					// 单测使用
+					if domain.domain == "localhost" {
+						err = smtp.SendMailUnsafe("", domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
+					} else if hostnameErr, is := certificateErr.Err.(x509.HostnameError); is {
 						if hostnameErr.Certificate != nil {
 						if hostnameErr.Certificate != nil {
 							certificateHostName := hostnameErr.Certificate.DNSNames
 							certificateHostName := hostnameErr.Certificate.DNSNames
+							// 重新选取证书发送
 							err = smtp.SendMail(domainMatch(domain.domain, certificateHostName), domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
 							err = smtp.SendMail(domainMatch(domain.domain, certificateHostName), domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
-							if err != nil {
-								log.WithContext(ctx).Warnf("SMTP Send Error! Error:%+v", err)
-							} else {
-								log.WithContext(ctx).Infof("SMTP Send Success !")
-							}
 						}
 						}
 					}
 					}
 				}
 				}
@@ -185,7 +189,10 @@ func Send(ctx *context.Context, e *parsemail.Email) (error, map[string]error) {
 
 
 				// 证书错误,从新选取证书发送
 				// 证书错误,从新选取证书发送
 				if certificateErr, ok := err.(*tls.CertificateVerificationError); ok {
 				if certificateErr, ok := err.(*tls.CertificateVerificationError); ok {
-					if hostnameErr, is := certificateErr.Err.(x509.HostnameError); is {
+					// 单测使用
+					if domain.domain == "localhost" {
+						err = smtp.SendMailUnsafe("", domain.mxHost+":25", nil, e.From.EmailAddress, buildAddress(tos), b)
+					} else if hostnameErr, is := certificateErr.Err.(x509.HostnameError); is {
 						if hostnameErr.Certificate != nil {
 						if hostnameErr.Certificate != nil {
 							certificateHostName := hostnameErr.Certificate.DNSNames
 							certificateHostName := hostnameErr.Certificate.DNSNames
 							// 重新选取证书发送
 							// 重新选取证书发送