package command import ( "bytes" "context" "fmt" "forge.cadoles.com/wpetit/hydra-passwordless/internal/config" "forge.cadoles.com/wpetit/hydra-passwordless/internal/hydra" "forge.cadoles.com/wpetit/hydra-passwordless/internal/mail" "forge.cadoles.com/wpetit/hydra-passwordless/internal/token" "github.com/aymerick/douceur/inliner" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/cqrs" "gitlab.com/wpetit/goweb/middleware/container" "gitlab.com/wpetit/goweb/service/build" "gitlab.com/wpetit/goweb/service/template" ) type SendConfirmationEmailRequest struct { Email string Challenge string DefaultScheme string DefaultAddress string RememberMe bool ClientName string ClientURI string } func HandleSendConfirmationEmailRequest(ctx context.Context, cmd cqrs.Command) error { req, ok := cmd.Request().(*SendConfirmationEmailRequest) if !ok { return cqrs.ErrUnexpectedRequest } ctn := container.Must(ctx) tmpl := template.Must(ctn) hydr := hydra.Must(ctn) info := build.Must(ctn) ml := mail.Must(ctn) conf := config.Must(ctn) _, err := hydr.LoginRequest(req.Challenge) if err != nil { return errors.Wrap(err, "could not retrieve hydra login response") } token, err := token.Generate( conf.HTTP.TokenSigningKey, conf.HTTP.TokenEncryptionKey, req.Email, req.Challenge, req.RememberMe, ) if err != nil { return errors.Wrap(err, "could not generate jwt") } address := req.DefaultAddress if conf.HTTP.PublicAddress != "" { address = conf.HTTP.PublicAddress } scheme := req.DefaultScheme if scheme == "" { scheme = "http:" } if conf.HTTP.PublicScheme != "" { scheme = conf.HTTP.PublicScheme } verificationLink := fmt.Sprintf("%s//%s/verify?token=%s", scheme, address, token) data := template.Data{ "ClientName": req.ClientName, "ClientURI": req.ClientURI, "BuildInfo": info, "VerificationLink": verificationLink, } var buf bytes.Buffer if err := tmpl.Render(&buf, "verification_email.html.tmpl", data); err != nil { return errors.Wrap(err, "could not render email template") } // Inline CSS for mail clients html, err := inliner.Inline(buf.String()) if err != nil { return errors.Wrap(err, "could not inline css") } err = ml.Send( mail.WithSender(conf.SMTP.SenderAddress, conf.SMTP.SenderName), mail.WithRecipients(req.Email), mail.WithSubject(fmt.Sprintf("[%s] Connexion", req.ClientName)), mail.WithBody(mail.ContentTypeHTML, html, nil), mail.WithAlternativeBody(mail.ContentTypeText, "", nil), ) if err != nil { return errors.Wrap(err, "could not send email") } return nil }