113 lines
3.2 KiB
Go
113 lines
3.2 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/mail"
|
|
"net/smtp"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
const contactExportCompleteSubject = "Your contact's export file is available to download."
|
|
|
|
// ContactExportMailer delivers the administrator notification emitted by
|
|
// Chatwoot's Account::ContactsExportJob after the CSV artifact is attached.
|
|
type ContactExportMailer interface {
|
|
SendContactExportComplete(ctx context.Context, account *model.Account, user *model.User, export *model.ContactExport) error
|
|
}
|
|
|
|
type SMTPContactExportMailer struct {
|
|
Address string
|
|
Port int
|
|
Username string
|
|
Password string
|
|
From string
|
|
FrontendURL string
|
|
}
|
|
|
|
func NewEnvContactExportMailer() *SMTPContactExportMailer {
|
|
return &SMTPContactExportMailer{
|
|
Address: strings.TrimSpace(os.Getenv("SMTP_ADDRESS")),
|
|
Port: envInt("SMTP_PORT", 587),
|
|
Username: firstEnv("SMTP_USERNAME", "SMTP_LOGIN"),
|
|
Password: os.Getenv("SMTP_PASSWORD"),
|
|
From: firstEnv("MAILER_SENDER_EMAIL", "SMTP_FROM"),
|
|
FrontendURL: strings.TrimRight(os.Getenv("FRONTEND_URL"), "/"),
|
|
}
|
|
}
|
|
|
|
func (m *SMTPContactExportMailer) SendContactExportComplete(ctx context.Context, account *model.Account, user *model.User, export *model.ContactExport) error {
|
|
_ = ctx
|
|
if m == nil || strings.TrimSpace(m.Address) == "" || user == nil || strings.TrimSpace(user.Email) == "" || export == nil {
|
|
return nil
|
|
}
|
|
fromHeader := strings.TrimSpace(m.From)
|
|
if fromHeader == "" {
|
|
fromHeader = "Chatwoot <accounts@chatwoot.com>"
|
|
}
|
|
fromAddress := fromHeader
|
|
if parsed, err := mail.ParseAddress(fromHeader); err == nil {
|
|
fromAddress = parsed.Address
|
|
}
|
|
|
|
to := strings.TrimSpace(user.Email)
|
|
body := contactExportEmailBody(account, export, m.FrontendURL)
|
|
message := smtpMessage(fromHeader, to, contactExportCompleteSubject, body)
|
|
addr := fmt.Sprintf("%s:%d", strings.TrimSpace(m.Address), m.Port)
|
|
|
|
var auth smtp.Auth
|
|
if strings.TrimSpace(m.Username) != "" {
|
|
auth = smtp.PlainAuth("", strings.TrimSpace(m.Username), m.Password, strings.TrimSpace(m.Address))
|
|
}
|
|
return smtp.SendMail(addr, auth, fromAddress, []string{to}, []byte(message))
|
|
}
|
|
|
|
func contactExportEmailBody(account *model.Account, export *model.ContactExport, frontendURL string) string {
|
|
accountName := "your account"
|
|
if account != nil && strings.TrimSpace(account.Name) != "" {
|
|
accountName = account.Name
|
|
}
|
|
fileURL := export.FileURL
|
|
if frontendURL != "" && strings.HasPrefix(fileURL, "/") {
|
|
fileURL = frontendURL + fileURL
|
|
}
|
|
return fmt.Sprintf("The contact export for %s is ready.\n\nDownload: %s\n", accountName, fileURL)
|
|
}
|
|
|
|
func smtpMessage(from, to, subject, body string) string {
|
|
return strings.Join([]string{
|
|
"From: " + from,
|
|
"To: " + to,
|
|
"Subject: " + subject,
|
|
"MIME-Version: 1.0",
|
|
"Content-Type: text/plain; charset=UTF-8",
|
|
"",
|
|
body,
|
|
}, "\r\n")
|
|
}
|
|
|
|
func firstEnv(keys ...string) string {
|
|
for _, key := range keys {
|
|
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
|
|
return value
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func envInt(key string, fallback int) int {
|
|
value := strings.TrimSpace(os.Getenv(key))
|
|
if value == "" {
|
|
return fallback
|
|
}
|
|
parsed, err := strconv.Atoi(value)
|
|
if err != nil || parsed <= 0 {
|
|
return fallback
|
|
}
|
|
return parsed
|
|
}
|