add and init smtp client
This commit is contained in:
parent
93f667d170
commit
5e1a04a02c
25
.env
25
.env
@ -1,22 +1,21 @@
|
||||
# General application settings
|
||||
APP_NAME=codeword
|
||||
HTTP_HOST=localhost
|
||||
HTTP_PORT=8000
|
||||
HTTP_HOST="localhost"
|
||||
HTTP_PORT="8000"
|
||||
|
||||
# MongoDB settings
|
||||
MONGO_HOST=127.0.0.1
|
||||
MONGO_PORT=27020
|
||||
MONGO_USER=test
|
||||
MONGO_PASSWORD=test
|
||||
MONGO_DB=admin
|
||||
MONGO_AUTH=admin
|
||||
MONGO_HOST="127.0.0.1"
|
||||
MONGO_PORT="27020"
|
||||
MONGO_USER="test"
|
||||
MONGO_PASSWORD="test"
|
||||
MONGO_DB="admin"
|
||||
MONGO_AUTH="admin"
|
||||
|
||||
# Redis settings
|
||||
REDIS_ADDR="localhost:6379"
|
||||
REDIS_PASS="admin"
|
||||
REDIS_DB=2
|
||||
|
||||
|
||||
# Keys
|
||||
PUBLIC_CURVE_KEY="-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyt4XuLovUY7i12K2PIMbQZOKn+wFFKUvxvKQDel049/+VMpHMx1FLolUKuyGp9zi6gOwjHsBPgc9oqr/eaXGQSh7Ult7i9f+Ht563Y0er5UU9Zc5ZPSxf9O75KYD48ruGkqiFoncDqPENK4dtUa7w0OqlN4bwVBbmIsP8B3EDC5Dof+vtiNTSHSXPx+zifKeZGyknp+nyOHVrRDhPjOhzQzCom0MSZA/sJYmps8QZgiPA0k4Z6jTupDymPOIwYeD2C57zSxnAv0AfC3/pZYJbZYH/0TszRzmy052DME3zMnhMK0ikdN4nzYqU0dkkA5kb5GtKDymspHIJ9eWbUuwgtg8Rq/LrVBj1I3UFgs0ibio40k6gqinLKslc5Y1I5mro7J3OSEP5eO/XeDLOLlOJjEqkrx4fviI1cL3m5L6QV905xmcoNZG1+RmOg7D7cZQUf27TXqM381jkbNdktm1JLTcMScxuo3vaRftnIVw70V8P8sIkaKY8S8HU1sQgE2LB9t04oog5u59htx2FHv4B13NEm8tt8Tv1PexpB4UVh7PIualF6SxdFBrKbraYej72wgjXVPQ0eGXtGGD57j8DUEzk7DK2OvIWhehlVqtiRnFdAvdBj2ynHT2/5FJ/Zpd4n5dKGJcQvy1U1qWMs+8M7AHfWyt2+nZ04s48+bK3yMCAwEAAQ==\n-----END PUBLIC KEY-----"
|
||||
|
||||
@ -24,3 +23,11 @@ PRIVATE_CURVE_KEY="-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIKn0BKwF3vZv
|
||||
|
||||
SIGN_SECRET=group
|
||||
|
||||
# SMTP settings
|
||||
SMTP_API_URL="https://api.smtp.bz/v1/smtp/send"
|
||||
SMTP_HOST="connect.mailclient.bz"
|
||||
SMTP_PORT="587"
|
||||
SMTP_UNAME="kotilion.95@gmail.com"
|
||||
SMTP_PASS="vWwbCSg4bf0p"
|
||||
SMTP_API_KEY="P0YsjUB137upXrr1NiJefHmXVKW1hmBWlpev"
|
||||
SMTP_SENDER="noreply@mailing.pena.digital"
|
||||
|
@ -4,7 +4,7 @@ services:
|
||||
mongo:
|
||||
image: mongo
|
||||
ports:
|
||||
- "${MONGO_PORT}:27017"
|
||||
- "27020:27017"
|
||||
environment:
|
||||
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}
|
||||
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
|
||||
|
@ -1,36 +1,87 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
type RecoveryEmailSender struct {
|
||||
SmtpHost string
|
||||
SmtpPort string
|
||||
Username string
|
||||
Password string
|
||||
ApiKey string
|
||||
type RecoveryEmailSenderDeps struct {
|
||||
SmtpApiUrl string
|
||||
SmtpHost string
|
||||
SmtpPort string
|
||||
SmtpSender string
|
||||
Username string
|
||||
Password string
|
||||
ApiKey string
|
||||
FiberClient *fiber.Client
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// SendRecoveryEmail отправляет email с подписью для восстановления доступа
|
||||
func (r *RecoveryEmailSender) SendRecoveryEmail(email, signature string) error {
|
||||
// прост как пример пока что
|
||||
type RecoveryEmailSender struct {
|
||||
deps RecoveryEmailSenderDeps
|
||||
}
|
||||
|
||||
func NewRecoveryEmailSender(deps RecoveryEmailSenderDeps) *RecoveryEmailSender {
|
||||
if deps.FiberClient == nil {
|
||||
deps.FiberClient = fiber.AcquireClient()
|
||||
}
|
||||
return &RecoveryEmailSender{
|
||||
deps: deps,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RecoveryEmailSender) SendRecoveryEmail(email string, signature []byte) error {
|
||||
url := r.deps.SmtpApiUrl
|
||||
|
||||
fmt.Println(email, signature)
|
||||
|
||||
message := fmt.Sprintf("To: %s\r\n"+
|
||||
"Subject: Восстановление доступа\r\n"+
|
||||
"\r\n"+
|
||||
"Чтобы восстановить доступ, пожалуйста, перейдите по ссылке ниже:\r\n"+
|
||||
" https://hub.pena.digital/codeword/restore/%s\r\n", email, signature)
|
||||
|
||||
auth := smtp.PlainAuth("", r.Username, r.Password, r.SmtpHost)
|
||||
form := new(bytes.Buffer)
|
||||
writer := multipart.NewWriter(form)
|
||||
defer writer.Close()
|
||||
|
||||
err := smtp.SendMail(r.SmtpHost+":"+r.SmtpPort, auth, r.Username, []string{email}, []byte(message))
|
||||
if err != nil {
|
||||
fmt.Printf("Ошибка при отправке письма: %s\n", err)
|
||||
fields := map[string]string{
|
||||
"from": r.deps.SmtpSender,
|
||||
"to": "pashamullin202@gmail.com",
|
||||
"subject": "Восстановление доступа",
|
||||
"html": message,
|
||||
}
|
||||
|
||||
for key, value := range fields {
|
||||
if err := writer.WriteField(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Письмо для восстановления доступа отправлено на: %s\n", email)
|
||||
req := r.deps.FiberClient.Post(url).Body(form.Bytes()).ContentType(writer.FormDataContentType())
|
||||
if r.deps.ApiKey != "" {
|
||||
req.Set("Authorization", r.deps.ApiKey)
|
||||
}
|
||||
|
||||
statusCode, body, errs := req.Bytes()
|
||||
if errs != nil {
|
||||
r.deps.Logger.Error("Ошибка при отправке запроса", zap.Error(errs[0]))
|
||||
return errs[0]
|
||||
}
|
||||
|
||||
if statusCode != fiber.StatusOK {
|
||||
err := fmt.Errorf("SMTP сервис вернул ошибку: %s Тело ответа: %s", statusCode, body)
|
||||
r.deps.Logger.Error("Ошибка при отправке электронной почты", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
r.deps.Logger.Info("Письмо для восстановления отправлено", zap.String("email", email))
|
||||
return nil
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"codeword/internal/adapters/client"
|
||||
controller "codeword/internal/controller/recovery"
|
||||
"codeword/internal/initialize"
|
||||
"codeword/internal/repository"
|
||||
@ -9,6 +10,7 @@ import (
|
||||
"codeword/internal/utils/encrypt"
|
||||
"codeword/internal/worker/recovery_worker"
|
||||
"context"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
@ -34,7 +36,17 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
|
||||
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
|
||||
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
|
||||
|
||||
//recoveryEmailSender := &client.RecoveryEmailSender{}
|
||||
recoveryEmailSender := client.NewRecoveryEmailSender(client.RecoveryEmailSenderDeps{
|
||||
SmtpApiUrl: cfg.SmtpApiUrl,
|
||||
SmtpHost: cfg.SmtpHost,
|
||||
SmtpPort: cfg.SmtpPort,
|
||||
SmtpSender: cfg.SmtpSender,
|
||||
Username: cfg.SmtpUsername,
|
||||
Password: cfg.SmtpPassword,
|
||||
ApiKey: cfg.SmtpApiKey,
|
||||
FiberClient: &fiber.Client{},
|
||||
Logger: logger,
|
||||
})
|
||||
|
||||
recoveryService := services.NewRecoveryService(services.Deps{
|
||||
Logger: logger,
|
||||
@ -45,7 +57,11 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
|
||||
|
||||
recoveryController := controller.NewRecoveryController(logger, recoveryService)
|
||||
|
||||
recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{Logger: logger, Redis: rdb})
|
||||
recoveryWC := recovery_worker.NewRecoveryWC(recovery_worker.Deps{
|
||||
Logger: logger,
|
||||
Redis: rdb,
|
||||
EmailSender: recoveryEmailSender,
|
||||
})
|
||||
|
||||
go recoveryWC.Start(ctx)
|
||||
|
||||
|
@ -22,6 +22,13 @@ type Config struct {
|
||||
RedisAddr string `env:"REDIS_ADDR" envDefault:"localhost:6379"`
|
||||
RedisPassword string `env:"REDIS_PASS" envDefault:"admin"`
|
||||
RedisDB int `env:"REDIS_DB" envDefault:"2"`
|
||||
SmtpApiUrl string `env:"SMTP_API_URL"`
|
||||
SmtpHost string `env:"SMTP_HOST"`
|
||||
SmtpPort string `env:"SMTP_PORT"`
|
||||
SmtpUsername string `env:"SMTP_UNAME"`
|
||||
SmtpPassword string `env:"SMTP_PASS"`
|
||||
SmtpApiKey string `env:"SMTP_API_KEY"`
|
||||
SmtpSender string `env:"SMTP_SENDER"`
|
||||
}
|
||||
|
||||
func LoadConfig() (*Config, error) {
|
||||
|
@ -30,6 +30,6 @@ type RestoreRequest struct {
|
||||
type RecoveryRecord struct {
|
||||
UserID string `bson:"user_id"`
|
||||
Email string `bson:"email"`
|
||||
Key string `bson:"key"`
|
||||
Key []byte `bson:"key"`
|
||||
CreatedAt time.Time `bson:"created_at"`
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func (r *codewordRepository) StoreRecoveryRecord(ctx context.Context, userID str
|
||||
record := models.RecoveryRecord{
|
||||
UserID: userID,
|
||||
Email: email,
|
||||
Key: string(key),
|
||||
Key: key,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ func (r *codewordRepository) InsertToQueue(ctx context.Context, userID string, e
|
||||
task := models.RecoveryRecord{
|
||||
UserID: userID + faker.String(),
|
||||
Email: email,
|
||||
Key: string(key),
|
||||
Key: key,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,32 @@
|
||||
package recovery_worker
|
||||
|
||||
import (
|
||||
"codeword/internal/adapters/client"
|
||||
"codeword/internal/models"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"go.uber.org/zap"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Deps struct {
|
||||
Logger *zap.Logger
|
||||
Redis *redis.Client
|
||||
Logger *zap.Logger
|
||||
Redis *redis.Client
|
||||
EmailSender *client.RecoveryEmailSender
|
||||
}
|
||||
|
||||
type recoveryWorker struct {
|
||||
logger *zap.Logger
|
||||
redis *redis.Client
|
||||
logger *zap.Logger
|
||||
redis *redis.Client
|
||||
emailSender *client.RecoveryEmailSender
|
||||
}
|
||||
|
||||
func NewRecoveryWC(deps Deps) *recoveryWorker {
|
||||
return &recoveryWorker{
|
||||
logger: deps.Logger,
|
||||
redis: deps.Redis,
|
||||
logger: deps.Logger,
|
||||
redis: deps.Redis,
|
||||
emailSender: deps.EmailSender,
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,15 +65,19 @@ func (wc *recoveryWorker) processTasks(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
err = wc.sendRecoveryTask(ctx, task)
|
||||
err = wc.sendRecoveryTask(task)
|
||||
if err != nil {
|
||||
wc.logger.Error("Failed to send recovery task", zap.String("key", result[0]), zap.Error(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (wc *recoveryWorker) sendRecoveryTask(ctx context.Context, task models.RecoveryRecord) error {
|
||||
fmt.Println(task)
|
||||
|
||||
func (wc *recoveryWorker) sendRecoveryTask(task models.RecoveryRecord) error {
|
||||
err := wc.emailSender.SendRecoveryEmail(task.Email, task.Key)
|
||||
if err != nil {
|
||||
wc.logger.Error("Failed to send recovery email", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
wc.logger.Info("Recovery email sent successfully", zap.String("email", task.Email))
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user