mirror of
https://github.com/ente-io/ente.git
synced 2025-06-01 15:08:58 +00:00
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
// The email package contains functions for directly sending emails.
|
|
//
|
|
// These functions can be used for directly sending emails to given email
|
|
// addresses. This is used for transactional emails, for example OTP requests.
|
|
// Currently, we use Zoho Transmail to send out the actual mail.
|
|
package email
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"html/template"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/ente-io/museum/ente"
|
|
"github.com/ente-io/stacktrace"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// Send sends an email
|
|
func Send(toEmails []string, fromName string, fromEmail string, subject string, htmlBody string, inlineImages []map[string]interface{}) error {
|
|
if len(toEmails) == 0 {
|
|
return ente.ErrBadRequest
|
|
}
|
|
|
|
authKey := viper.GetString("transmail.key")
|
|
silent := viper.GetBool("internal.silent")
|
|
if authKey == "" || silent {
|
|
log.Infof("Skipping sending email to %s: %s", toEmails[0], subject)
|
|
return nil
|
|
}
|
|
|
|
var to []ente.ToEmailAddress
|
|
for _, toEmail := range toEmails {
|
|
to = append(to, ente.ToEmailAddress{EmailAddress: ente.EmailAddress{Address: toEmail}})
|
|
}
|
|
mail := &ente.Mail{
|
|
BounceAddress: ente.TransmailEndBounceAddress,
|
|
From: ente.EmailAddress{Address: fromEmail, Name: fromName},
|
|
Subject: subject,
|
|
Htmlbody: htmlBody,
|
|
InlineImages: inlineImages,
|
|
}
|
|
if len(toEmails) == 1 {
|
|
mail.To = to
|
|
} else {
|
|
mail.Bcc = to
|
|
}
|
|
postBody, err := json.Marshal(mail)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "")
|
|
}
|
|
reqBody := bytes.NewBuffer(postBody)
|
|
client := &http.Client{}
|
|
req, err := http.NewRequest("POST", ente.TransmailEndPoint, reqBody)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "")
|
|
}
|
|
req.Header.Set("accept", "application/json")
|
|
req.Header.Set("content-type", "application/json")
|
|
req.Header.Set("authorization", authKey)
|
|
_, err = client.Do(req)
|
|
return stacktrace.Propagate(err, "")
|
|
}
|
|
|
|
func SendTemplatedEmail(to []string, fromName string, fromEmail string, subject string, templateName string, templateData map[string]interface{}, inlineImages []map[string]interface{}) error {
|
|
body, err := getMailBody(templateName, templateData)
|
|
if err != nil {
|
|
return stacktrace.Propagate(err, "")
|
|
}
|
|
return Send(to, fromName, fromEmail, subject, body, inlineImages)
|
|
}
|
|
|
|
func GetMaskedEmail(email string) string {
|
|
at := strings.LastIndex(email, "@")
|
|
if at >= 0 {
|
|
username, domain := email[:at], email[at+1:]
|
|
maskedUsername := ""
|
|
for i := 0; i < len(username); i++ {
|
|
maskedUsername += "*"
|
|
}
|
|
return maskedUsername + "@" + domain
|
|
} else {
|
|
// Should ideally never happen, there should always be an @ symbol
|
|
return "[invalid_email]"
|
|
}
|
|
}
|
|
|
|
// getMailBody generates the mail html body from provided template and data
|
|
func getMailBody(templateName string, templateData map[string]interface{}) (string, error) {
|
|
htmlbody := new(bytes.Buffer)
|
|
t := template.Must(template.New(templateName).ParseFiles("mail-templates/" + templateName))
|
|
err := t.Execute(htmlbody, templateData)
|
|
if err != nil {
|
|
return "", stacktrace.Propagate(err, "")
|
|
}
|
|
return htmlbody.String(), nil
|
|
}
|