recover 时发邮件

This commit is contained in:
xing 2022-10-17 20:04:29 +08:00
parent 952ccfd2ca
commit 12d33898d4
9 changed files with 860 additions and 2 deletions

View File

@ -15,6 +15,14 @@ mysql:
maxIdleConn: 10
# 连接的生命时长
connMaxLifetime: 236
Mail:
user: xx@163.com
alias: xx
pass:
Host: smtp.163.com
Port: 465
Ssl: true
# 最近文章缓存时间
recentPostCacheTime: 5m
# 分类缓存时间

2
go.mod
View File

@ -34,4 +34,6 @@ require (
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
)

56
mail/mail.go Normal file
View File

@ -0,0 +1,56 @@
package mail
import (
"crypto/tls"
"fmt"
"github/fthvgb1/wp-go/vars"
"gopkg.in/gomail.v2"
"mime"
"strings"
)
type AttacheFile struct {
Name string
Path string
}
func (f AttacheFile) GetName() string {
t := strings.Split(f.Path, ".")
return fmt.Sprintf("%s.%s", f.Name, t[len(t)-1])
}
func SendMail(mailTo []string, subject string, body string, a ...AttacheFile) error {
m := gomail.NewMessage(
gomail.SetEncoding(gomail.Base64),
)
m.SetHeader("From",
m.FormatAddress(vars.Conf.Mail.User,
vars.Conf.Mail.Alias,
))
m.SetHeader("To", mailTo...)
m.SetHeader("Subject", subject)
m.SetBody("text/html", body)
for _, files := range a {
m.Attach(files.Path,
gomail.Rename(files.Name), //重命名
gomail.SetHeader(map[string][]string{
"Content-Disposition": {
fmt.Sprintf(`attachment; filename="%s"`, mime.QEncoding.Encode("UTF-8", files.GetName())),
},
}),
)
}
d := gomail.NewDialer(
vars.Conf.Mail.Host,
vars.Conf.Mail.Port,
vars.Conf.Mail.User,
vars.Conf.Mail.Pass,
)
if vars.Conf.Mail.Ssl {
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
}
err := d.DialAndSend(m)
return err
}

43
mail/mail_test.go Normal file
View File

@ -0,0 +1,43 @@
package mail
import (
"github/fthvgb1/wp-go/vars"
"testing"
)
func TestSendMail(t *testing.T) {
vars.InitConfig()
type args struct {
mailTo []string
subject string
body string
a []AttacheFile
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "t1",
args: args{
mailTo: []string{"fthvgb1@163.com"},
subject: "测试发邮件",
body: "测试发邮件",
a: []AttacheFile{
{
Name: "附件",
Path: "/home/xing/Downloads/favicon.ico",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := SendMail(tt.args.mailTo, tt.args.subject, tt.args.body, tt.args.a...); (err != nil) != tt.wantErr {
t.Errorf("SendMail() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

View File

@ -5,7 +5,7 @@ import "github.com/gin-gonic/gin"
func SearchLimit(num int64) func(ctx *gin.Context) {
fn := IpLimit(num)
return func(c *gin.Context) {
if "/" == c.FullPath() && c.Query("s") != "" {
if c.Query("s") != "" {
fn(c)
} else {
c.Next()

139
middleware/sendmail.go Normal file
View File

@ -0,0 +1,139 @@
package middleware
import (
"bytes"
"fmt"
"github.com/gin-gonic/gin"
"github/fthvgb1/wp-go/logs"
"github/fthvgb1/wp-go/mail"
"github/fthvgb1/wp-go/models"
"github/fthvgb1/wp-go/vars"
"io"
"io/ioutil"
"net/http"
"net/http/httputil"
"runtime"
"strings"
"time"
)
func RecoverAndSendMail(w io.Writer) func(ctx *gin.Context) {
return gin.CustomRecoveryWithWriter(w, func(ctx *gin.Context, err any) {
c := ctx.Copy()
stack := stack(4)
go func() {
httpRequest, _ := httputil.DumpRequest(c.Request, true)
headers := strings.Split(string(httpRequest), "\r\n")
for idx, header := range headers {
current := strings.Split(header, ":")
if current[0] == "Authorization" {
headers[idx] = current[0] + ": *"
}
}
headersToStr := strings.Join(headers, "<br/>")
content := `<div><dt>err:</dt><dd>%v</dd><hr/>
<dt>stack: </dt><dd>%v</dd><hr/>
<dt>headers: </dt><dd>%s</dd></div>
`
content = fmt.Sprintf(content,
err,
formatStack(string(stack)),
headersToStr,
)
er := mail.SendMail(
[]string{vars.Conf.Mail.User},
fmt.Sprintf("%s%s %s 发生错误", fmt.Sprintf(models.Options["siteurl"]), c.FullPath(), time.Now().Format(time.RFC1123Z)), content)
if er != nil {
logs.ErrPrintln(er, "recover send mail fail", fmt.Sprintf("%v", err))
}
}()
ctx.AbortWithStatus(http.StatusInternalServerError)
})
}
var (
dunno = []byte("???")
centerDot = []byte("·")
dot = []byte(".")
slash = []byte("/")
)
func formatStack(s string) (r string) {
ss := strings.Builder{}
t := strings.Split(s, "\n")
for i, line := range t {
if i%2 == 0 {
ss.WriteString("<dt>")
ss.WriteString(line)
ss.WriteString("</dt>")
} else {
ss.WriteString("<dd>")
ss.WriteString(strings.Trim(line, "\t"))
ss.WriteString("</dd>")
}
}
r = ss.String()
return
}
func stack(skip int) []byte {
buf := new(bytes.Buffer) // the returned data
// As we loop, we open files and read them. These variables record the currently
// loaded file.
var lines [][]byte
var lastFile string
for i := skip; ; i++ { // Skip the expected number of frames
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
// Print this much at least. If we can't find the source, it won't show.
fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
if file != lastFile {
data, err := ioutil.ReadFile(file)
if err != nil {
continue
}
lines = bytes.Split(data, []byte{'\n'})
lastFile = file
}
fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
}
return buf.Bytes()
}
// function returns, if possible, the name of the function containing the PC.
func function(pc uintptr) []byte {
fn := runtime.FuncForPC(pc)
if fn == nil {
return dunno
}
name := []byte(fn.Name())
// The name includes the path name to the package, which is unnecessary
// since the file name is already included. Plus, it has center dots.
// That is, we see
// runtime/debug.*T·ptrmethod
// and want
// *T.ptrmethod
// Also the package path might contain dot (e.g. code.google.com/...),
// so first eliminate the path prefix
if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 {
name = name[lastSlash+1:]
}
if period := bytes.Index(name, dot); period >= 0 {
name = name[period+1:]
}
name = bytes.Replace(name, centerDot, dot, -1)
return name
}
// source returns a space-trimmed slice of the n'th line.
func source(lines [][]byte, n int) []byte {
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
if n < 0 || n >= len(lines) {
return dunno
}
return bytes.TrimSpace(lines[n])
}

View File

@ -39,7 +39,7 @@ func SetupRouter() *gin.Engine {
r.Use(
middleware.ValidateServerNames(),
gin.Logger(),
gin.Recovery(),
middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
middleware.FlowLimit(vars.Conf.MaxRequestSleepNum, vars.Conf.MaxRequestNum, vars.Conf.SleepTime),
middleware.SetStaticFileCache,
)

View File

@ -0,0 +1,600 @@
/* vietnamese */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyxq15Mjs.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyx615Mjs.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 400;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyya15.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyxq15Mjs.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyx615Mjs.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 700;
font-stretch: 100%;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/inconsolata/v31/QlddNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLyya15.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARPQ_m87A.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARGQ_m87A.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* devanagari */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARDQ_m87A.woff2) format('woff2');
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* greek-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4AROQ_m87A.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARBQ_m87A.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARNQ_m87A.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARMQ_m87A.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0OIpQlx3QUlC5A4PNr4ARCQ_k.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyOzW1aPQ.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyHzW1aPQ.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* devanagari */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyCzW1aPQ.woff2) format('woff2');
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* greek-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyPzW1aPQ.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyAzW1aPQ.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyMzW1aPQ.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyNzW1aPQ.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Sans';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0TIpQlx3QUlC5A4PNr4Az5ZuyDzW0.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr6DRAW_0.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr4TRAW_0.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* devanagari */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr5DRAW_0.woff2) format('woff2');
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* greek-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr6TRAW_0.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr5jRAW_0.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr6jRAW_0.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr6zRAW_0.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0IIpQlx3QUlC5A4PNr5TRA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVadyB1Wk.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVYNyB1Wk.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* devanagari */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVZdyB1Wk.woff2) format('woff2');
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* greek-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVaNyB1Wk.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVZ9yB1Wk.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVa9yB1Wk.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVatyB1Wk.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notosans/v27/o-0NIpQlx3QUlC5A4PNjXhFVZNyB.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImZzC7TMQ.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImbjC7TMQ.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImZjC7TMQ.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImaTC7TMQ.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImZTC7TMQ.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImZDC7TMQ.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Kaw1J5X9T9RW6j9bNfFImajC7.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufuVMCoY.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWud-VMCoY.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWuf-VMCoY.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWucOVMCoY.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufOVMCoY.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWufeVMCoY.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Serif';
font-style: italic;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Vaw1J5X9T9RW6j9bNfFIu0RWuc-VM.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFoWaCi_.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFMWaCi_.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFsWaCi_.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFQWaCi_.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFgWaCi_.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFkWaCi_.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Iaw1J5X9T9RW6j9bNfFcWaA.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfRqecf1I.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfROecf1I.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfRuecf1I.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfRSecf1I.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfRiecf1I.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfRmecf1I.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Noto Serif';
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url(https://fonts.gstatic.com/s/notoserif/v21/ga6Law1J5X9T9RW6j9bNdOwzfReecQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@ -11,6 +11,7 @@ var Conf Config
type Config struct {
Mysql Mysql `yaml:"mysql"`
Mail Mail `yaml:"mail"`
RecentPostCacheTime time.Duration `yaml:"recentPostCacheTime"`
CategoryCacheTime time.Duration `yaml:"categoryCacheTime"`
ArchiveCacheTime time.Duration `yaml:"archiveCacheTime"`
@ -37,6 +38,15 @@ type Config struct {
TrustServerNames []string `yaml:"trustServerNames"`
}
type Mail struct {
User string `yaml:"user"`
Alias string `yaml:"alias"`
Pass string `yaml:"pass"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Ssl bool `yaml:"ssl"`
}
type Mysql struct {
Dsn Dsn `yaml:"dsn"`
Pool Pool `yaml:"pool"`