mirror of https://gitee.com/answerdev/answer.git
feat(email): translator all email template
This commit is contained in:
parent
e26d608aaf
commit
350df2da8b
10
go.mod
10
go.mod
|
@ -29,10 +29,10 @@ require (
|
||||||
github.com/ory/dockertest/v3 v3.9.1
|
github.com/ory/dockertest/v3 v3.9.1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
|
||||||
github.com/segmentfault/pacman v1.0.3
|
github.com/segmentfault/pacman v1.0.4
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
||||||
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221219081300-f734f4a16aa0
|
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093245-f9384b820548
|
||||||
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05
|
||||||
github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05
|
||||||
github.com/spf13/cobra v1.6.1
|
github.com/spf13/cobra v1.6.1
|
||||||
|
@ -129,10 +129,10 @@ require (
|
||||||
go.uber.org/multierr v1.8.0 // indirect
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
go.uber.org/zap v1.23.0 // indirect
|
go.uber.org/zap v1.23.0 // indirect
|
||||||
golang.org/x/image v0.1.0 // indirect
|
golang.org/x/image v0.1.0 // indirect
|
||||||
golang.org/x/mod v0.6.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.2.0 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
|
18
go.sum
18
go.sum
|
@ -627,12 +627,14 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/segmentfault/pacman v1.0.3 h1:/K8LJHQMiCaCIvC/e8GQITpYTEG6RH4KTLTZjPTghl4=
|
github.com/segmentfault/pacman v1.0.3 h1:/K8LJHQMiCaCIvC/e8GQITpYTEG6RH4KTLTZjPTghl4=
|
||||||
github.com/segmentfault/pacman v1.0.3/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
github.com/segmentfault/pacman v1.0.3/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
||||||
|
github.com/segmentfault/pacman v1.0.4 h1:6UIXuMHUeYMWe5toflV9SXZQizRny1RczjZJLj9kul0=
|
||||||
|
github.com/segmentfault/pacman v1.0.4/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0 h1:4x0qG7H2M3qH7Yo2BhGrVlji1iTmRAWgINY/JyENeHs=
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0 h1:4x0qG7H2M3qH7Yo2BhGrVlji1iTmRAWgINY/JyENeHs=
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0/go.mod h1:rmf1TCwz67dyM+AmTwSd1BxTo2AOYHj262lP93bOZbs=
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk=
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05 h1:BlqTgc3/MYKG6vMI2MI+6o+7P4Gy5PXlawu185wPXAk=
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05/go.mod h1:prPjFam7MyZ5b3S9dcDOt2tMPz6kf7C9c243s9zSwPY=
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05/go.mod h1:prPjFam7MyZ5b3S9dcDOt2tMPz6kf7C9c243s9zSwPY=
|
||||||
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221219081300-f734f4a16aa0 h1:zaAwBSpwUVrV2BBs1f1hfkv0rY/KdZLyKK8U9NKiurI=
|
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093245-f9384b820548 h1:R+FH23Qrdp5ECuHXmZy4BvoO/x7m2wZgNeiC46+jqCQ=
|
||||||
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20221219081300-f734f4a16aa0/go.mod h1:7QcRmnV7OYq4hNOOCWXT5HXnN/u756JUsqIW0Bw8n9E=
|
github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093245-f9384b820548/go.mod h1:7QcRmnV7OYq4hNOOCWXT5HXnN/u756JUsqIW0Bw8n9E=
|
||||||
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05 h1:jcGZU2juv0L3eFEkuZYV14ESLUlWfGMWnP0mjOfrSZc=
|
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05 h1:jcGZU2juv0L3eFEkuZYV14ESLUlWfGMWnP0mjOfrSZc=
|
||||||
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05/go.mod h1:L4GqtXLoR73obTYqUQIzfkm8NG8pvZafxFb6KZFSSHk=
|
github.com/segmentfault/pacman/contrib/log/zap v0.0.0-20221018072427-a15dd1434e05/go.mod h1:L4GqtXLoR73obTYqUQIzfkm8NG8pvZafxFb6KZFSSHk=
|
||||||
github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05 h1:91is1nKNbfTOl8CvMYiFgg4c5Vmol+5mVmMV/jDXD+A=
|
github.com/segmentfault/pacman/contrib/server/http v0.0.0-20221018072427-a15dd1434e05 h1:91is1nKNbfTOl8CvMYiFgg4c5Vmol+5mVmMV/jDXD+A=
|
||||||
|
@ -822,8 +824,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -893,6 +895,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -981,8 +984,9 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -1050,8 +1054,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
# The following fields are used for back-end
|
# The following fields are used for back-end
|
||||||
|
# backend.email.tpl.change_email.title.other = Confirm your new email address for {{.SiteName}} by clicking on the following link:\u003cbr\u003e\u003cbr\u003e\n\n\u003ca href='{{.ChangeEmailUrl}}' target='_blank'\u003e{{.ChangeEmailUrl}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\nIf you did not request this change, please ignore this email.\n
|
||||||
|
# backend.email.tpl.change_email.body.other = [{{.SiteName}}] Confirm your new email address
|
||||||
|
# backend.email.tpl.new_answer.title.other = \u003cstrong\u003e\u003ca href='{{.AnswerUrl}}'\u003e{{.QuestionTitle}}\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003e{{.DisplayName}}:\u003c/small\u003e\u003cbr\u003e\n\u003cblockquote\u003e{{.AnswerSummary}}\u003c/blockquote\u003e\u003cbr\u003e\n\u003ca href='{{.AnswerUrl}}'\u003eView it on {{.SiteName}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003eYou are receiving this because you authored the thread. \u003ca href='{{.UnsubscribeUrl}}'\u003eUnsubscribe\u003c/a\u003e\u003c/small\u003e
|
||||||
|
# backend.email.tpl.new_answer.body.other = [{{.SiteName}}] {{.DisplayName}} answered your question
|
||||||
|
# backend.email.tpl.new_comment.title.other = \u003cstrong\u003e\u003ca href='{{.CommentUrl}}'\u003e{{.QuestionTitle}}\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003e{{.DisplayName}}:\u003c/small\u003e\u003cbr\u003e\n\u003cblockquote\u003e{{.CommentSummary}}\u003c/blockquote\u003e\u003cbr\u003e\n\u003ca href='{{.CommentUrl}}'\u003eView it on {{.SiteName}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\n\u003csmall\u003eYou are receiving this because you authored the thread. \u003ca href='{{.UnsubscribeUrl}}'\u003eUnsubscribe\u003c/a\u003e\u003c/small\u003e
|
||||||
|
# backend.email.tpl.new_comment.body.other = [{{.SiteName}}] {{.DisplayName}} commented on your post
|
||||||
|
# backend.email.tpl.pass_reset.title.other = Somebody asked to reset your password on [{{.SiteName}}].\u003cbr\u003e\u003cbr\u003e\n\nIf it was not you, you can safely ignore this email.\u003cbr\u003e\u003cbr\u003e\n\nClick the following link to choose a new password:\u003cbr\u003e\n\u003ca href='{{.PassResetUrl}}' target='_blank'\u003e{{.PassResetUrl}}\u003c/a\u003e\n
|
||||||
|
# backend.email.tpl.pass_reset.body.other = [{{.SiteName }}] Password reset
|
||||||
|
# backend.email.tpl.register.title.other = Welcome to {{.SiteName}}\u003cbr\u003e\u003cbr\u003e\n\nClick the following link to confirm and activate your new account:\u003cbr\u003e\n\u003ca href='{{.RegisterUrl}}' target='_blank'\u003e{{.RegisterUrl}}\u003c/a\u003e\u003cbr\u003e\u003cbr\u003e\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n
|
||||||
|
# backend.email.tpl.register.body.other = [{{.SiteName}}] Confirm your new account
|
||||||
|
# backend.email.tpl.test.title.other = This is a test email.
|
||||||
|
# backend.email.tpl.test.body.other = [{{.SiteName}}] Test Email
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
base:
|
base:
|
||||||
|
@ -384,6 +398,37 @@ backend:
|
||||||
other: downvoted answer
|
other: downvoted answer
|
||||||
up_voted_comment:
|
up_voted_comment:
|
||||||
other: upvoted comment
|
other: upvoted comment
|
||||||
|
email_tpl:
|
||||||
|
change_email:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] Confirm your new email address"
|
||||||
|
body:
|
||||||
|
other: "Confirm your new email address for {{.SiteName}} by clicking on the following link:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\nIf you did not request this change, please ignore this email.\n"
|
||||||
|
new_answer:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] {{.DisplayName}} answered your question"
|
||||||
|
body:
|
||||||
|
other: "<strong><a href='{{.AnswerUrl}}'>{{.QuestionTitle}}</a></strong><br><br>\n\n<small>{{.DisplayName}}:</small><br>\n<blockquote>{{.AnswerSummary}}</blockquote><br>\n<a href='{{.AnswerUrl}}'>View it on {{.SiteName}}</a><br><br>\n\n<small>You are receiving this because you authored the thread. <a href='{{.UnsubscribeUrl}}'>Unsubscribe</a></small>"
|
||||||
|
new_comment:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] {{.DisplayName}} commented on your post"
|
||||||
|
body:
|
||||||
|
other: "<strong><a href='{{.CommentUrl}}'>{{.QuestionTitle}}</a></strong><br><br>\n\n<small>{{.DisplayName}}:</small><br>\n<blockquote>{{.CommentSummary}}</blockquote><br>\n<a href='{{.CommentUrl}}'>View it on {{.SiteName}}</a><br><br>\n\n<small>You are receiving this because you authored the thread. <a href='{{.UnsubscribeUrl}}'>Unsubscribe</a></small>"
|
||||||
|
pass_reset:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName }}] Password reset"
|
||||||
|
body:
|
||||||
|
other: "Somebody asked to reset your password on [{{.SiteName}}].<br><br>\n\nIf it was not you, you can safely ignore this email.<br><br>\n\nClick the following link to choose a new password:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n"
|
||||||
|
register:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] Confirm your new account"
|
||||||
|
body:
|
||||||
|
other: "Welcome to {{.SiteName}}<br><br>\n\nClick the following link to confirm and activate your new account:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\nIf the above link is not clickable, try copying and pasting it into the address bar of your web browser.\n"
|
||||||
|
test:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] Test Email"
|
||||||
|
body:
|
||||||
|
other: "This is a test email."
|
||||||
|
|
||||||
# The following fields are used for interface presentation(Front-end)
|
# The following fields are used for interface presentation(Front-end)
|
||||||
ui:
|
ui:
|
||||||
|
|
|
@ -373,6 +373,37 @@ backend:
|
||||||
other: 踩了答案
|
other: 踩了答案
|
||||||
up_voted_comment:
|
up_voted_comment:
|
||||||
other: 赞了评论
|
other: 赞了评论
|
||||||
|
email_tpl:
|
||||||
|
change_email:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] 确认您的新电子邮件地址"
|
||||||
|
body:
|
||||||
|
other: "请点击以下链接确认您在 {{.SiteName}} 上的新电子邮件地址:<br><br>\n\n<a href='{{.ChangeEmailUrl}}' target='_blank'>{{.ChangeEmailUrl}}</a><br><br>\n\n如果您没有请求此更改,请忽略此电子邮件。\n"
|
||||||
|
new_answer:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] {{.DisplayName}} 回答了您的问题"
|
||||||
|
body:
|
||||||
|
other: "<strong><a href='{{.AnswerUrl}}'>{{.QuestionTitle}}</a></strong><br><br>\n\n<small>{{.DisplayName}}:</small><br>\n<blockquote>{{.AnswerSummary}}</blockquote><br>\n<a href='{{.AnswerUrl}}'>在 {{.SiteName}} 上查看</a><br><br>\n\n<small>您会收到此邮件是因为您是该讨论的作者。<a href='{{.UnsubscribeUrl}}'>取消订阅</a></small>"
|
||||||
|
new_comment:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] {{.DisplayName}} 评论了您的帖子"
|
||||||
|
body:
|
||||||
|
other: "<strong><a href='{{.CommentUrl}}'>{{.QuestionTitle}}</a></strong><br><br>\n\n<small>{{.DisplayName}}:</small><br>\n<blockquote>{{.CommentSummary}}</blockquote><br>\n<a href='{{.CommentUrl}}'>在 {{.SiteName}} 上查看</a><br><br>\n\n<small>您会收到此邮件是因为您是该讨论的作者。<a href='{{.UnsubscribeUrl}}'>取消订阅</a></small>"
|
||||||
|
pass_reset:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName }}] 重置密码"
|
||||||
|
body:
|
||||||
|
other: "有人要求在 [{{.SiteName}}] 上重置您的密码。<br><br>\n\n如果这不是您的操作,请安心忽略此电子邮件。<br><br>\n\n请点击以下链接选择一个新密码:<br>\n<a href='{{.PassResetUrl}}' target='_blank'>{{.PassResetUrl}}</a>\n"
|
||||||
|
register:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] 确认您的新账户"
|
||||||
|
body:
|
||||||
|
other: "欢迎加入 {{.SiteName}}<br><br>\n\n请点击以下链接确认并激活您的新账户:<br>\n<a href='{{.RegisterUrl}}' target='_blank'>{{.RegisterUrl}}</a><br><br>\n\n如果上面的链接不能点击,请将其复制并粘贴到您的浏览器地址栏中。\n"
|
||||||
|
test:
|
||||||
|
title:
|
||||||
|
other: "[{{.SiteName}}] 测试邮件"
|
||||||
|
body:
|
||||||
|
other: "这是一封测试邮件。"
|
||||||
#The following fields are used for interface presentation(Front-end)
|
#The following fields are used for interface presentation(Front-end)
|
||||||
ui:
|
ui:
|
||||||
how_to_format:
|
how_to_format:
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package constant
|
||||||
|
|
||||||
|
const (
|
||||||
|
EmailTplKeyChangeEmailTitle = "email_tpl.change_email.title"
|
||||||
|
EmailTplKeyChangeEmailBody = "email_tpl.change_email.body"
|
||||||
|
|
||||||
|
EmailTplKeyNewAnswerTitle = "email_tpl.new_answer.title"
|
||||||
|
EmailTplKeyNewAnswerBody = "email_tpl.new_answer.body"
|
||||||
|
|
||||||
|
EmailTplKeyNewCommentTitle = "email_tpl.new_comment.title"
|
||||||
|
EmailTplKeyNewCommentBody = "email_tpl.new_comment.body"
|
||||||
|
|
||||||
|
EmailTplKeyPassResetTitle = "email_tpl.pass_reset.title"
|
||||||
|
EmailTplKeyPassResetBody = "email_tpl.pass_reset.body"
|
||||||
|
|
||||||
|
EmailTplKeyRegisterTitle = "email_tpl.register.title"
|
||||||
|
EmailTplKeyRegisterBody = "email_tpl.register.body"
|
||||||
|
|
||||||
|
EmailTplKeyTestTitle = "email_tpl.test.title"
|
||||||
|
EmailTplKeyTestBody = "email_tpl.test.body"
|
||||||
|
)
|
|
@ -131,3 +131,15 @@ func Tr(lang i18n.Language, data string) string {
|
||||||
}
|
}
|
||||||
return translation
|
return translation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrWithData translate key with template data, it will replace the template data {{ .PlaceHolder }} in the translation.
|
||||||
|
func TrWithData(lang i18n.Language, key string, templateData any) string {
|
||||||
|
if GlobalTrans == nil {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
translation := GlobalTrans.TrWithData(lang, key, templateData)
|
||||||
|
if translation == key {
|
||||||
|
return GlobalTrans.TrWithData(i18n.DefaultLanguage, key, templateData)
|
||||||
|
}
|
||||||
|
return translation
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package export
|
package export
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"mime"
|
"mime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/entity"
|
"github.com/answerdev/answer/internal/entity"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/internal/service/config"
|
"github.com/answerdev/answer/internal/service/config"
|
||||||
|
@ -162,11 +163,6 @@ func (es *EmailService) GetSiteGeneral(ctx context.Context) (resp schema.SiteGen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EmailService) RegisterTemplate(ctx context.Context, registerUrl string) (title, body string, err error) {
|
func (es *EmailService) RegisterTemplate(ctx context.Context, registerUrl string) (title, body string, err error) {
|
||||||
emailConfig, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteInfo, err := es.GetSiteGeneral(ctx)
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -176,123 +172,59 @@ func (es *EmailService) RegisterTemplate(ctx context.Context, registerUrl string
|
||||||
RegisterUrl: registerUrl,
|
RegisterUrl: registerUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
title, err = es.parseTemplateData(emailConfig.RegisterTitle, templateData)
|
lang := handler.GetLangByCtx(ctx)
|
||||||
if err != nil {
|
title = translator.TrWithData(lang, constant.EmailTplKeyRegisterTitle, templateData)
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
body = translator.TrWithData(lang, constant.EmailTplKeyRegisterBody, templateData)
|
||||||
}
|
|
||||||
|
|
||||||
body, err = es.parseTemplateData(emailConfig.RegisterBody, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
|
||||||
}
|
|
||||||
return title, body, nil
|
return title, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EmailService) PassResetTemplate(ctx context.Context, passResetUrl string) (title, body string, err error) {
|
func (es *EmailService) PassResetTemplate(ctx context.Context, passResetUrl string) (title, body string, err error) {
|
||||||
ec, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteinfo, err := es.GetSiteGeneral(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
templateData := PassResetTemplateData{SiteName: siteinfo.Name, PassResetUrl: passResetUrl}
|
|
||||||
tmpl, err := template.New("pass_reset_title").Parse(ec.PassResetTitle)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
titleBuf := &bytes.Buffer{}
|
|
||||||
bodyBuf := &bytes.Buffer{}
|
|
||||||
err = tmpl.Execute(titleBuf, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err = template.New("pass_reset_body").Parse(ec.PassResetBody)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(bodyBuf, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return titleBuf.String(), bodyBuf.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es *EmailService) ChangeEmailTemplate(ctx context.Context, changeEmailUrl string) (title, body string, err error) {
|
|
||||||
ec, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteinfo, err := es.GetSiteGeneral(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
templateData := ChangeEmailTemplateData{
|
|
||||||
SiteName: siteinfo.Name,
|
|
||||||
ChangeEmailUrl: changeEmailUrl,
|
|
||||||
}
|
|
||||||
tmpl, err := template.New("email_change_title").Parse(ec.ChangeTitle)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
titleBuf := &bytes.Buffer{}
|
|
||||||
bodyBuf := &bytes.Buffer{}
|
|
||||||
err = tmpl.Execute(titleBuf, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err = template.New("email_change_body").Parse(ec.ChangeBody)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(bodyBuf, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return titleBuf.String(), bodyBuf.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestTemplate send test email template parse
|
|
||||||
func (es *EmailService) TestTemplate(ctx context.Context) (title, body string, err error) {
|
|
||||||
emailConfig, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteInfo, err := es.GetSiteGeneral(ctx)
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
templateData := TestTemplateData{
|
|
||||||
SiteName: siteInfo.Name,
|
templateData := PassResetTemplateData{SiteName: siteInfo.Name, PassResetUrl: passResetUrl}
|
||||||
|
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
|
title = translator.TrWithData(lang, constant.EmailTplKeyPassResetTitle, templateData)
|
||||||
|
body = translator.TrWithData(lang, constant.EmailTplKeyPassResetBody, templateData)
|
||||||
|
return title, body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *EmailService) ChangeEmailTemplate(ctx context.Context, changeEmailUrl string) (title, body string, err error) {
|
||||||
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
templateData := ChangeEmailTemplateData{
|
||||||
|
SiteName: siteInfo.Name,
|
||||||
|
ChangeEmailUrl: changeEmailUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
title, err = es.parseTemplateData(emailConfig.TestTitle, templateData)
|
lang := handler.GetLangByCtx(ctx)
|
||||||
if err != nil {
|
title = translator.TrWithData(lang, constant.EmailTplKeyChangeEmailTitle, templateData)
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
body = translator.TrWithData(lang, constant.EmailTplKeyChangeEmailBody, templateData)
|
||||||
}
|
return title, body, nil
|
||||||
|
}
|
||||||
|
|
||||||
body, err = es.parseTemplateData(emailConfig.TestBody, templateData)
|
// TestTemplate send test email template parse
|
||||||
|
func (es *EmailService) TestTemplate(ctx context.Context) (title, body string, err error) {
|
||||||
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
return
|
||||||
}
|
}
|
||||||
|
templateData := TestTemplateData{SiteName: siteInfo.Name}
|
||||||
|
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
|
title = translator.TrWithData(lang, constant.EmailTplKeyTestTitle, templateData)
|
||||||
|
body = translator.TrWithData(lang, constant.EmailTplKeyTestBody, templateData)
|
||||||
return title, body, nil
|
return title, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAnswerTemplate new answer template
|
// NewAnswerTemplate new answer template
|
||||||
func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAnswerTemplateRawData) (
|
func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAnswerTemplateRawData) (
|
||||||
title, body string, err error) {
|
title, body string, err error) {
|
||||||
emailConfig, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteInfo, err := es.GetSiteGeneral(ctx)
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -307,26 +239,15 @@ func (es *EmailService) NewAnswerTemplate(ctx context.Context, raw *schema.NewAn
|
||||||
}
|
}
|
||||||
templateData.SiteName = siteInfo.Name
|
templateData.SiteName = siteInfo.Name
|
||||||
|
|
||||||
title, err = es.parseTemplateData(emailConfig.NewAnswerTitle, templateData)
|
lang := handler.GetLangByCtx(ctx)
|
||||||
if err != nil {
|
title = translator.TrWithData(lang, constant.EmailTplKeyNewAnswerTitle, templateData)
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
body = translator.TrWithData(lang, constant.EmailTplKeyNewAnswerBody, templateData)
|
||||||
}
|
|
||||||
|
|
||||||
body, err = es.parseTemplateData(emailConfig.NewAnswerBody, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
|
||||||
}
|
|
||||||
return title, body, nil
|
return title, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommentTemplate new comment template
|
// NewCommentTemplate new comment template
|
||||||
func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewCommentTemplateRawData) (
|
func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewCommentTemplateRawData) (
|
||||||
title, body string, err error) {
|
title, body string, err error) {
|
||||||
emailConfig, err := es.GetEmailConfig()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
siteInfo, err := es.GetSiteGeneral(ctx)
|
siteInfo, err := es.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -347,31 +268,12 @@ func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewC
|
||||||
}
|
}
|
||||||
templateData.SiteName = siteInfo.Name
|
templateData.SiteName = siteInfo.Name
|
||||||
|
|
||||||
title, err = es.parseTemplateData(emailConfig.NewCommentTitle, templateData)
|
lang := handler.GetLangByCtx(ctx)
|
||||||
if err != nil {
|
title = translator.TrWithData(lang, constant.EmailTplKeyNewCommentTitle, templateData)
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
body = translator.TrWithData(lang, constant.EmailTplKeyNewCommentBody, templateData)
|
||||||
}
|
|
||||||
|
|
||||||
body, err = es.parseTemplateData(emailConfig.NewCommentBody, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf("email template parse error: %s", err)
|
|
||||||
}
|
|
||||||
return title, body, nil
|
return title, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *EmailService) parseTemplateData(templateContent string, templateData interface{}) (parsedData string, err error) {
|
|
||||||
parsedDataBuf := &bytes.Buffer{}
|
|
||||||
tmpl, err := template.New("").Parse(templateContent)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
err = tmpl.Execute(parsedDataBuf, templateData)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return parsedDataBuf.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es *EmailService) GetEmailConfig() (ec *EmailConfig, err error) {
|
func (es *EmailService) GetEmailConfig() (ec *EmailConfig, err error) {
|
||||||
emailConf, err := es.configRepo.GetString("email.config")
|
emailConf, err := es.configRepo.GetString("email.config")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue