Build post chat and attachment workflows
This commit is contained in:
150
backend/internal/mail/smtp.go
Normal file
150
backend/internal/mail/smtp.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package mail
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SMTPConfig struct {
|
||||
Host string
|
||||
Port string
|
||||
User string
|
||||
Password string
|
||||
From string
|
||||
FromName string
|
||||
}
|
||||
|
||||
type Sender struct {
|
||||
cfg SMTPConfig
|
||||
}
|
||||
|
||||
func NewSender(cfg SMTPConfig) Sender {
|
||||
if strings.TrimSpace(cfg.Port) == "" {
|
||||
cfg.Port = "587"
|
||||
}
|
||||
return Sender{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s Sender) IsConfigured() bool {
|
||||
return strings.TrimSpace(s.cfg.Host) != "" &&
|
||||
strings.TrimSpace(s.cfg.Port) != "" &&
|
||||
strings.TrimSpace(s.cfg.From) != ""
|
||||
}
|
||||
|
||||
func (s Sender) SendInvitation(to string, invitationURL string) error {
|
||||
subject := "Convite para acessar o Mira"
|
||||
textBody := "Voce foi convidado para acessar o Mira.\n\nCrie sua senha pelo link abaixo:\n" + invitationURL + "\n\nEste convite expira em 7 dias."
|
||||
htmlBody := `<p>Voce foi convidado para acessar o Mira.</p><p><a href="` + invitationURL + `">Criar minha senha</a></p><p>Este convite expira em 7 dias.</p>`
|
||||
|
||||
return s.send(to, subject, textBody, htmlBody)
|
||||
}
|
||||
|
||||
func (s Sender) send(to string, subject string, textBody string, htmlBody string) error {
|
||||
if !s.IsConfigured() {
|
||||
return nil
|
||||
}
|
||||
|
||||
from := mail.Address{Name: strings.TrimSpace(s.cfg.FromName), Address: strings.TrimSpace(s.cfg.From)}
|
||||
recipient := mail.Address{Address: strings.TrimSpace(to)}
|
||||
boundary := "mira-mail-boundary"
|
||||
message := strings.Join([]string{
|
||||
"From: " + from.String(),
|
||||
"To: " + recipient.String(),
|
||||
"Subject: " + subject,
|
||||
"MIME-Version: 1.0",
|
||||
"Content-Type: multipart/alternative; boundary=\"" + boundary + "\"",
|
||||
"",
|
||||
"--" + boundary,
|
||||
"Content-Type: text/plain; charset=UTF-8",
|
||||
"",
|
||||
textBody,
|
||||
"--" + boundary,
|
||||
"Content-Type: text/html; charset=UTF-8",
|
||||
"",
|
||||
htmlBody,
|
||||
"--" + boundary + "--",
|
||||
"",
|
||||
}, "\r\n")
|
||||
|
||||
host := strings.TrimSpace(s.cfg.Host)
|
||||
port := strings.TrimSpace(s.cfg.Port)
|
||||
addr := net.JoinHostPort(host, port)
|
||||
var auth smtp.Auth
|
||||
if strings.TrimSpace(s.cfg.User) != "" || strings.TrimSpace(s.cfg.Password) != "" {
|
||||
auth = smtp.PlainAuth("", strings.TrimSpace(s.cfg.User), strings.TrimSpace(s.cfg.Password), host)
|
||||
}
|
||||
|
||||
if port == "465" {
|
||||
if err := sendMailTLS(addr, host, auth, from.Address, []string{recipient.Address}, []byte(message)); err != nil {
|
||||
return fmt.Errorf("send smtp email: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := sendMailStartTLS(addr, host, auth, from.Address, []string{recipient.Address}, []byte(message)); err != nil {
|
||||
return fmt.Errorf("send smtp email: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendMailStartTLS(addr string, host string, auth smtp.Auth, from string, to []string, message []byte) error {
|
||||
client, err := smtp.Dial(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Quit()
|
||||
|
||||
if ok, _ := client.Extension("STARTTLS"); ok {
|
||||
if err := client.StartTLS(&tls.Config{ServerName: host, MinVersion: tls.VersionTLS12}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sendMailWithClient(client, auth, from, to, message)
|
||||
}
|
||||
|
||||
func sendMailTLS(addr string, host string, auth smtp.Auth, from string, to []string, message []byte) error {
|
||||
conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: host, MinVersion: tls.VersionTLS12})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := smtp.NewClient(conn, host)
|
||||
if err != nil {
|
||||
_ = conn.Close()
|
||||
return err
|
||||
}
|
||||
defer client.Quit()
|
||||
|
||||
return sendMailWithClient(client, auth, from, to, message)
|
||||
}
|
||||
|
||||
func sendMailWithClient(client *smtp.Client, auth smtp.Auth, from string, to []string, message []byte) error {
|
||||
if auth != nil {
|
||||
if err := client.Auth(auth); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := client.Mail(from); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, recipient := range to {
|
||||
if err := client.Rcpt(recipient); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
writer, err := client.Data()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := writer.Write(message); err != nil {
|
||||
_ = writer.Close()
|
||||
return err
|
||||
}
|
||||
return writer.Close()
|
||||
}
|
||||
Reference in New Issue
Block a user