diff --git a/email-tester/.gitignore b/email-tester/.gitignore
new file mode 100644
index 0000000..62c8935
--- /dev/null
+++ b/email-tester/.gitignore
@@ -0,0 +1 @@
+.idea/
\ No newline at end of file
diff --git a/email-tester/README.md b/email-tester/README.md
new file mode 100644
index 0000000..36557c5
--- /dev/null
+++ b/email-tester/README.md
@@ -0,0 +1,11 @@
+# email-tester
+
+нужен для тестирования текущей логики отправки формы, все что нужно это запустить в терминале проект, вписать тип события - toClient или reminder, а также что config.yaml находящийся в проекте в той же директории заполенен и все выходящие из него штуки, таки как шаблоны и файл json должны быть заполены
+
+процесс работы:
+- установить конфигурационный файл, пример в проекте
+- поставить шаблоны, пример в проекте
+- при запуске указать тип работы, toClient или reminder
+- после этого произойдет логика работы с шаблоном и проведется отправка на почту данных
+- далее информация в консоль выведется, если произойдет ошибка в консоли выведется
+- в конце нужно прописать exit чтобы выйти из текущего сеанса и консоли, далее запуск снова и т.д.
\ No newline at end of file
diff --git a/email-tester/client/mail.go b/email-tester/client/mail.go
new file mode 100644
index 0000000..341de8a
--- /dev/null
+++ b/email-tester/client/mail.go
@@ -0,0 +1,121 @@
+package client
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "github.com/gofiber/fiber/v2"
+ "mime/multipart"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/model"
+)
+
+type Deps struct {
+ SmtpApiUrl string
+ SmtpSender string
+ ApiKey string
+ FiberClient *fiber.Client
+}
+
+type SmtpClient struct {
+ smtpApiUrl string
+ smtpSender string
+ apiKey string
+ fiberClient *fiber.Client
+}
+
+func NewSmtpClient(deps Deps) *SmtpClient {
+ if deps.FiberClient == nil {
+ deps.FiberClient = fiber.AcquireClient()
+ }
+ return &SmtpClient{
+ smtpApiUrl: deps.SmtpApiUrl,
+ smtpSender: deps.SmtpSender,
+ apiKey: deps.ApiKey,
+ fiberClient: deps.FiberClient,
+ }
+}
+
+type Message struct {
+ To string
+ Subject string
+ HtmlBody string
+ Attachments []Attachment
+}
+
+type Attachment struct {
+ Name string `json:"name"`
+ // data в base64 это файл
+ Data string `json:"body"`
+}
+
+type TemplateData struct {
+ QuizConfig model.ResultInfo
+ AnswerContent model.ResultContent
+ AllAnswers []model.ResultAnswer
+ QuestionsMap map[uint64]string
+ AnswerTime string
+}
+
+func (m *SmtpClient) MailSender(data Message) error {
+ form := new(bytes.Buffer)
+ writer := multipart.NewWriter(form)
+
+ fields := map[string]string{
+ "from": m.smtpSender,
+ "to": data.To,
+ "subject": data.Subject,
+ "html": data.HtmlBody,
+ }
+
+ if data.Attachments != nil && len(data.Attachments) > 0 {
+ attachmentJson, err := json.Marshal(data.Attachments)
+ if err != nil {
+ return err
+ }
+ fields["files"] = string(attachmentJson)
+ }
+
+ for key, value := range fields {
+ if err := writer.WriteField(key, value); err != nil {
+ return err
+ }
+ }
+
+ if err := writer.Close(); err != nil {
+ return err
+ }
+
+ req := m.fiberClient.Post(m.smtpApiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType())
+ if m.apiKey != "" {
+ req.Set("Authorization", m.apiKey)
+ }
+
+ statusCode, body, errs := req.Bytes()
+ if errs != nil {
+ return errs[0]
+ }
+
+ if statusCode != fiber.StatusOK {
+ err := fmt.Errorf("the SMTP service returned an error: %d Response body: %s", statusCode, body)
+ return err
+ }
+
+ return nil
+}
+
+func (m *SmtpClient) SendMailWithAttachment(recipient, subject string, emailTemplate string, data TemplateData, attachments []Attachment) error {
+ sanitizedData := sanitizeHTMLData(data)
+ text, err := generateTextFromTemplate(sanitizedData, emailTemplate)
+ if err != nil {
+ return err
+ }
+
+ msg := Message{
+ To: recipient,
+ Subject: subject,
+ HtmlBody: text,
+ Attachments: attachments,
+ }
+
+ return m.MailSender(msg)
+}
diff --git a/email-tester/client/tools.go b/email-tester/client/tools.go
new file mode 100644
index 0000000..637d11e
--- /dev/null
+++ b/email-tester/client/tools.go
@@ -0,0 +1,144 @@
+package client
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "golang.org/x/net/html"
+ "html/template"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/model"
+ "strings"
+)
+
+func generateTextFromTemplate(data TemplateData, tpl string) (string, error) {
+ t, err := template.New("email").Funcs(tmplFuncs).Parse(tpl)
+ if err != nil {
+ return "", fmt.Errorf("error parsing template: %w", err)
+ }
+
+ var text bytes.Buffer
+ if err := t.Execute(&text, TemplateData{
+ QuizConfig: data.QuizConfig,
+ AnswerContent: data.AnswerContent,
+ AllAnswers: data.AllAnswers,
+ QuestionsMap: data.QuestionsMap,
+ AnswerTime: data.AnswerTime,
+ }); err != nil {
+ return "", fmt.Errorf("error executing template: %w", err)
+ }
+
+ return text.String(), nil
+}
+
+var tmplFuncs = template.FuncMap{
+ "renderImage": RenderImage,
+}
+
+func RenderImage(content string) template.HTML {
+ var res model.ImageContent
+ err := json.Unmarshal([]byte(content), &res)
+ if err != nil {
+ return SplitContent(content)
+ }
+ tpl := template.HTML(fmt.Sprintf("
%s
 | ", res.Description, res.Image))
+ return tpl
+}
+
+func SplitContent(content string) template.HTML {
+ parts := strings.Split(content, "|")
+ if len(parts) == 2 {
+ url := strings.TrimSpace(parts[0])
+ filename := strings.TrimSpace(parts[1])
+ return template.HTML(fmt.Sprintf(`%s`, url, filename))
+ }
+ return template.HTML(content)
+}
+
+func sanitizeHTMLData(data TemplateData) TemplateData {
+ sanitized := TemplateData{
+ QuizConfig: stripHTMLResultInfo(data.QuizConfig),
+ AnswerContent: stripHTMLResultContent(data.AnswerContent),
+ AllAnswers: stripHTMLResultAnswers(data.AllAnswers),
+ QuestionsMap: stripHTMLResultMap(data.QuestionsMap),
+ AnswerTime: StripHTML(data.AnswerTime),
+ }
+ return sanitized
+}
+
+func stripHTMLResultInfo(input model.ResultInfo) model.ResultInfo {
+ return model.ResultInfo{
+ When: StripHTML(input.When),
+ Theme: StripHTML(input.Theme),
+ Reply: StripHTML(input.Reply),
+ ReplName: StripHTML(input.ReplName),
+ }
+}
+
+func stripHTMLResultContent(input model.ResultContent) model.ResultContent {
+ return model.ResultContent{
+ Text: StripHTML(input.Text),
+ Name: StripHTML(input.Name),
+ Email: StripHTML(input.Email),
+ Phone: StripHTML(input.Phone),
+ Address: StripHTML(input.Address),
+ Telegram: StripHTML(input.Telegram),
+ Wechat: StripHTML(input.Wechat),
+ Viber: StripHTML(input.Viber),
+ Vk: StripHTML(input.Vk),
+ Skype: StripHTML(input.Skype),
+ Whatsup: StripHTML(input.Whatsup),
+ Messenger: StripHTML(input.Messenger),
+ Custom: stripHTMLCustom(input.Custom),
+ }
+}
+
+func stripHTMLResultAnswers(answers []model.ResultAnswer) []model.ResultAnswer {
+ sanitized := make([]model.ResultAnswer, len(answers))
+ for i, j := range answers {
+ sanitized[i] = model.ResultAnswer{
+ Content: StripHTML(j.Content),
+ CreatedAt: j.CreatedAt,
+ QuestionID: j.QuestionID,
+ AnswerID: j.AnswerID,
+ }
+ }
+ return sanitized
+}
+
+func stripHTMLResultMap(questionsMap map[uint64]string) map[uint64]string {
+ sanitized := make(map[uint64]string)
+ for i, j := range questionsMap {
+ sanitized[i] = StripHTML(j)
+ }
+ return sanitized
+}
+
+func stripHTMLCustom(custom map[string]string) map[string]string {
+ sanitized := make(map[string]string)
+ for i, j := range custom {
+ sanitized[i] = StripHTML(j)
+ }
+ return sanitized
+}
+
+func StripHTML(htmlString string) string {
+ tokenizer := html.NewTokenizer(bytes.NewBufferString(htmlString))
+ var result bytes.Buffer
+ for {
+ tokenType := tokenizer.Next()
+ switch tokenType {
+ case html.ErrorToken:
+ return strings.TrimSpace(result.String())
+ case html.TextToken:
+ result.WriteString(tokenizer.Token().Data)
+ result.WriteString("\n")
+ case html.StartTagToken, html.EndTagToken:
+ tagName, _ := tokenizer.TagName()
+ if string(tagName) == "a" {
+ _, attrVal, _ := tokenizer.TagAttr()
+ result.WriteString(string(attrVal))
+ result.WriteString("\n")
+ }
+ }
+ }
+}
diff --git a/email-tester/config.yaml b/email-tester/config.yaml
new file mode 100644
index 0000000..e0ad1df
--- /dev/null
+++ b/email-tester/config.yaml
@@ -0,0 +1,10 @@
+apiUrl: "https://api.smtp.bz/v1/smtp/send"
+apiKey: "P0YsjUB137upXrr1NiJefHmXVKW1hmBWlpev"
+subject: "test"
+sender: "noreply@mailing.pena.digital"
+to: "pashamullin2001@gmail.com"
+pathToTemplateData: "template/templateData.json"
+pathToReminderTemplate: "template/reminder_base.tmpl"
+pathToToClientTemplate: "template/to_client_base.tmpl"
+
+
diff --git a/email-tester/go.mod b/email-tester/go.mod
new file mode 100644
index 0000000..a70ca92
--- /dev/null
+++ b/email-tester/go.mod
@@ -0,0 +1,23 @@
+module penahub.gitlab.yandexcloud.net/pena-services/email-tester
+
+go 1.22.4
+
+require (
+ github.com/gofiber/fiber/v2 v2.52.5
+ golang.org/x/net v0.17.0
+ gopkg.in/yaml.v2 v2.4.0
+)
+
+require (
+ github.com/andybalholm/brotli v1.0.5 // indirect
+ github.com/google/uuid v1.5.0 // indirect
+ github.com/klauspost/compress v1.17.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.51.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+)
diff --git a/email-tester/go.sum b/email-tester/go.sum
new file mode 100644
index 0000000..bdf88e3
--- /dev/null
+++ b/email-tester/go.sum
@@ -0,0 +1,33 @@
+github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
+github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
+github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
+github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
+github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
+github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
diff --git a/email-tester/main.go b/email-tester/main.go
new file mode 100644
index 0000000..9d09ac1
--- /dev/null
+++ b/email-tester/main.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "fmt"
+ "gopkg.in/yaml.v2"
+ "io/ioutil"
+ "os"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/model"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/senders"
+)
+
+type event string
+
+var toClient event = "toClient"
+var reminder event = "reminder"
+
+func main() {
+ fmt.Println("Need event type 'toClient' or 'reminder':")
+ var eventFlag string
+ fmt.Scanln(&eventFlag)
+ defer func() {
+ fmt.Println("if you want exit write 'exit'")
+ var exit string
+ fmt.Scanln(&exit)
+ if exit == "exit" {
+ return
+ }
+ }()
+ config, err := loadConfig("config.yaml")
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ err = config.Validate()
+ if err != nil {
+ fmt.Println("failed validate config:", err)
+ return
+ }
+ switch eventFlag {
+ case string(toClient):
+ fmt.Println("Processing 'toClient' event")
+ err = senders.ToClientTesting(config)
+ if err != nil {
+ fmt.Println("error process task for toClient test:", err)
+ return
+ }
+ fmt.Println("OK check mailbox")
+ case string(reminder):
+ fmt.Println("Processing 'reminder' event")
+ err = senders.ReminderTesting(config)
+ if err != nil {
+ fmt.Println("error process task for reminder test:", err)
+ return
+ }
+ fmt.Println("OK check mailbox")
+ default:
+ fmt.Println("No event type or unknown event type specified need 'toClient' or 'reminder'")
+ }
+}
+
+func loadConfig(filename string) (model.Config, error) {
+ var config model.Config
+
+ file, err := os.Open(filename)
+ if err != nil {
+ return config, err
+ }
+ defer file.Close()
+
+ data, err := ioutil.ReadAll(file)
+ if err != nil {
+ return config, err
+ }
+
+ err = yaml.Unmarshal(data, &config)
+ if err != nil {
+ return config, err
+ }
+
+ return config, nil
+}
diff --git a/email-tester/model/model.go b/email-tester/model/model.go
new file mode 100644
index 0000000..14e75f7
--- /dev/null
+++ b/email-tester/model/model.go
@@ -0,0 +1,81 @@
+package model
+
+import (
+ "errors"
+ "time"
+)
+
+type Config struct {
+ ApiURL string `yaml:"apiUrl"`
+ ApiKey string `yaml:"apiKey"`
+ Subject string `yaml:"subject"`
+ Sender string `yaml:"sender"`
+ PathToTemplateData string `yaml:"pathToTemplateData"`
+ PathToReminderTemplate string `yaml:"pathToReminderTemplate"`
+ PathToToClientTemplate string `yaml:"pathToToClientTemplate"`
+ To string `yaml:"to"`
+}
+
+func (c *Config) Validate() error {
+ if c.ApiURL == "" {
+ return errors.New("ApiURL dont be nil")
+ }
+ if c.ApiKey == "" {
+ return errors.New("ApiKey dont be nil")
+ }
+ if c.Subject == "" {
+ return errors.New("Subject dont be nil")
+ }
+ if c.Sender == "" {
+ return errors.New("Sender dont be nil")
+ }
+ if c.PathToTemplateData == "" {
+ return errors.New("PathToTemplateData dont be nil")
+ }
+ if c.PathToReminderTemplate == "" {
+ return errors.New("PathToReminderTemplate dont be nil")
+ }
+ if c.PathToToClientTemplate == "" {
+ return errors.New("PathToToClientTemplate dont be nil")
+ }
+ if c.To == "" {
+ return errors.New("To dont be nil")
+ }
+ return nil
+}
+
+type ResultInfo struct {
+ When string `json:"when"` // before|after|email
+ Theme string `json:"theme"` // тема письма
+ Reply string `json:"reply"` // email для ответов, указывается в создании письма
+ ReplName string `json:"repl_name"` // имя отправителя
+}
+
+type ResultContent struct {
+ Text string `json:"text"`
+ Name string `json:"name"`
+ Email string `json:"email"`
+ Phone string `json:"phone"`
+ Address string `json:"address"`
+ Telegram string `json:"telegram"`
+ Wechat string `json:"wechat"`
+ Viber string `json:"viber"`
+ Vk string `json:"vk"`
+ Skype string `json:"skype"`
+ Whatsup string `json:"whatsup"`
+ Messenger string `json:"messenger"`
+ Custom map[string]string `json:"customs"`
+ Start bool `json:"start"`
+}
+
+type ResultAnswer struct {
+ Content string
+ CreatedAt time.Time
+ QuestionID uint64
+ AnswerID uint64
+}
+
+type ImageContent struct {
+ Description string
+ Image string
+}
diff --git a/email-tester/senders/reminder.go b/email-tester/senders/reminder.go
new file mode 100644
index 0000000..91661bd
--- /dev/null
+++ b/email-tester/senders/reminder.go
@@ -0,0 +1,30 @@
+package senders
+
+import (
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/client"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/model"
+)
+
+func ReminderTesting(config model.Config) error {
+ smtpClient := client.NewSmtpClient(client.Deps{
+ SmtpApiUrl: config.ApiURL,
+ SmtpSender: config.Sender,
+ ApiKey: config.ApiKey,
+ })
+
+ templateData, err := parseTemplateData(config.PathToTemplateData)
+ if err != nil {
+ return err
+ }
+
+ body, err := loadTemplate(config.PathToReminderTemplate)
+ if err != nil {
+ return err
+ }
+
+ err = smtpClient.SendMailWithAttachment(config.To, config.Subject, body, templateData, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/email-tester/senders/toClient.go b/email-tester/senders/toClient.go
new file mode 100644
index 0000000..15a841b
--- /dev/null
+++ b/email-tester/senders/toClient.go
@@ -0,0 +1,56 @@
+package senders
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/client"
+ "penahub.gitlab.yandexcloud.net/pena-services/email-tester/model"
+)
+
+func ToClientTesting(config model.Config) error {
+ smtpClient := client.NewSmtpClient(client.Deps{
+ SmtpApiUrl: config.ApiURL,
+ SmtpSender: config.Sender,
+ ApiKey: config.ApiKey,
+ })
+
+ templateData, err := parseTemplateData(config.PathToTemplateData)
+ if err != nil {
+ return err
+ }
+
+ body, err := loadTemplate(config.PathToToClientTemplate)
+ if err != nil {
+ return err
+ }
+
+ err = smtpClient.SendMailWithAttachment(config.To, config.Subject, body, templateData, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func parseTemplateData(filePath string) (client.TemplateData, error) {
+ var data client.TemplateData
+
+ file, err := ioutil.ReadFile(filePath)
+ if err != nil {
+ return data, err
+ }
+
+ err = json.Unmarshal(file, &data)
+ if err != nil {
+ return data, err
+ }
+
+ return data, nil
+}
+
+func loadTemplate(filePath string) (string, error) {
+ fileContent, err := ioutil.ReadFile(filePath)
+ if err != nil {
+ return "", err
+ }
+ return string(fileContent), nil
+}
diff --git a/email-tester/template/reminder_base.tmpl b/email-tester/template/reminder_base.tmpl
new file mode 100644
index 0000000..f966af0
--- /dev/null
+++ b/email-tester/template/reminder_base.tmpl
@@ -0,0 +1,191 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ |
+
+ Квиз для вашего бизнеса
+ |
+
+
+
+
+
+ Поступила новая заявка с квиза “{{ .QuizConfig.Theme }}”!
+
+ |
+
+
+
+
+ Но у вас закончились средства на балансе :(
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+ Аккаунт
+
+ |
+
+
+
+
+
+
+
+ Email
+ |
+
+
+ {{ .QuizConfig.Reply }}
+
+ |
+
+
+ |
+
+
+
+
+
+ Пополните баланс и посмотрите заявку в личном кабинете:
+
+ |
+
+
+
+
+
+ Посмотреть в личном кабинете
+
+ |
+
+
+
+
+
+
+ quiz.pena.digital
+
+ |
+
+
+
+
diff --git a/email-tester/template/templateData.json b/email-tester/template/templateData.json
new file mode 100644
index 0000000..d6e5c5e
--- /dev/null
+++ b/email-tester/template/templateData.json
@@ -0,0 +1,57 @@
+{
+ "QuizConfig": {
+ "when": "test@example.com",
+ "theme": "Taemplste Quiz",
+ "reply": "test@example.com",
+ "repl_name": "test@example.com"
+ },
+ "AnswerContent": {
+ "text": "",
+ "name": "test",
+ "email": "test@example.com",
+ "phone": "+723456789",
+ "address": "",
+ "telegram": "@test",
+ "wechat": "test_wechat",
+ "viber": "+723456789",
+ "vk": "test_vk",
+ "skype": "test_skype",
+ "whatsup": "test_whatsup",
+ "messenger": "test_messenger",
+ "customs": {},
+ "start": false
+ },
+ "AllAnswers": [
+ {
+ "Content": "https://www.google.com/search?q=ku,n",
+ "CreatedAt": "2024-07-05T18:54:37Z",
+ "QuestionID": 1,
+ "AnswerID": 1
+ },
+ {
+ "Content": "From a friend",
+ "CreatedAt": "2024-07-05T18:54:37Z",
+ "QuestionID": 2,
+ "AnswerID": 2
+ },
+ {
+ "Content": "From a friend",
+ "CreatedAt": "2024-07-05T18:54:37Z",
+ "QuestionID": 3,
+ "AnswerID": 3
+ },
+ {
+ "Content": "{\"Image\": \"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZvq8kZl7QhYC_7f0jMlepfnLkr8Y94tJY1g&s\", \"Description\": \"Gekon\"}",
+ "CreatedAt": "2024-07-05T18:54:37Z",
+ "QuestionID": 4,
+ "AnswerID": 4
+ }
+ ],
+ "QuestionsMap": {
+ "1": "?",
+ "2": "How did you hear about us?",
+ "3": "que 3",
+ "4": "que 4"
+ },
+ "AnswerTime": "2024-07-05T18:54:37Z"
+}
\ No newline at end of file
diff --git a/email-tester/template/to_client_base.tmpl b/email-tester/template/to_client_base.tmpl
new file mode 100644
index 0000000..fe36b93
--- /dev/null
+++ b/email-tester/template/to_client_base.tmpl
@@ -0,0 +1,537 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+ |
+
+ Квиз для вашего бизнеса
+ |
+
+
+
+
+
+ Поступила новая заявка с квиза “{{.QuizConfig.Theme}}”!
+
+ |
+
+
+
+
+ Время заявки: {{ .AnswerTime }}
+
+ |
+
+
+
+
+
+ Посмотреть в личном кабинете
+
+ |
+
+
+
+
+
+ Контакты
+
+ |
+
+
+
+
+
+
+
+ Имя
+ |
+
+
+ {{ .AnswerContent.Name}}
+
+ |
+
+ {{ if .AnswerContent.Email }}
+
+
+ Email
+ |
+
+
+ {{ .AnswerContent.Email }}
+
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Phone }}
+
+
+ Телефон
+ |
+
+ {{ .AnswerContent.Phone }}
+ |
+
+ {{ end }}
+
+ {{ if .AnswerContent.Telegram }}
+
+
+ Telegram
+ |
+
+ {{ .AnswerContent.Telegram }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Wechat }}
+
+
+ Wechat
+ |
+
+ {{ .AnswerContent.Wechat }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Viber }}
+
+
+ Viber
+ |
+
+ {{ .AnswerContent.Viber }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Vk }}
+
+
+ Vk
+ |
+
+ {{ .AnswerContent.Vk }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Skype }}
+
+
+ Skype
+ |
+
+ {{ .AnswerContent.Skype }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Whatsup }}
+
+
+ Whatsup
+ |
+
+ {{ .AnswerContent.Whatsup }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Messenger }}
+
+
+ Messenger
+ |
+
+ {{ .AnswerContent.Messenger }}
+ |
+
+ {{ end }}
+ {{ if .AnswerContent.Address }}
+
+
+ Адрес
+ |
+
+ {{ .AnswerContent.Address }}
+ |
+
+ {{ end }}
+ {{ range $key, $value := .AnswerContent.Custom }}
+
+
+
+ {{ $key }}
+ |
+
+ {{ $value }}
+ |
+
+ {{ end }}
+
+ |
+
+
+
+
+
+ Ответы
+
+ |
+
+
+ {{ range .AllAnswers }}
+ {{ if index $.QuestionsMap .AnswerID }}
+
+
+
+
+
+
+ {{ index $.QuestionsMap .AnswerID }}
+
+ |
+
+
+
+
+ {{ renderImage .Content }}
+ |
+
+
+ |
+
+ {{ end }}
+ {{end}}
+
+
+
+
+ quiz.pena.digital
+
+ |
+
+
+
+