Add SMTP for sending emails (#1228)

## Tests
Tested for templated mails in user.go, userauth.go, stripe.go,
public_collection.go, playstore.go, admin.go, email_notification.go

Screenshots for all the templates -
[https://drive.google.com/drive/folders/1f7BjM5MHicRUbr5jlCe2-4MGz7s1moLw?usp=sharing](url)
This commit is contained in:
Manav Rathi 2024-03-29 09:22:40 +05:30 committed by GitHub
commit 54d93647ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 92 additions and 2 deletions

View file

@ -157,8 +157,24 @@ key:
jwt:
secret: i2DecQmfGreG6q1vBj5tCokhlN41gcfS2cjOs9Po-u8=
# SMTP configuration (optional)
#
# Configure credentials here for sending mails from museum (e.g. OTP emails).
#
# The smtp credentials will be used if the host is specified. Otherwise it will
# try to use the transmail credentials. Ideally, one of smtp or transmail should
# be configured for a production instance.
smtp:
host:
port:
username:
password:
# Zoho Zeptomail config (optional)
# Use case: Sending emails
#
# This is an alternative to the `smtp` configuration for sending emails. If this
# is set (and SMTP credentials are not set), then museum will use the transmail
# SDK for sending emails using Zoho Zeptomail.
transmail:
# Transmail token
# Mail agent: dev
@ -279,4 +295,4 @@ jobs:
# By default, this job is disabled.
enabled: false
# If provided, only objects that begin with this prefix are pruned.
prefix: ""
prefix: ""

View file

@ -10,6 +10,7 @@ import (
"encoding/json"
"html/template"
"net/http"
"net/smtp"
"strings"
"github.com/ente-io/museum/ente"
@ -20,6 +21,78 @@ import (
// Send sends an email
func Send(toEmails []string, fromName string, fromEmail string, subject string, htmlBody string, inlineImages []map[string]interface{}) error {
smtpHost := viper.GetString("smtp.host")
if smtpHost != "" {
return sendViaSMTP(toEmails, fromName, fromEmail, subject, htmlBody, inlineImages)
} else {
return sendViaTransmail(toEmails, fromName, fromEmail, subject, htmlBody, inlineImages)
}
}
func sendViaSMTP(toEmails []string, fromName string, fromEmail string, subject string, htmlBody string, inlineImages []map[string]interface{}) error {
if len(toEmails) == 0 {
return ente.ErrBadRequest
}
smtpServer := viper.GetString("smtp.host")
smtpPort := viper.GetString("smtp.port")
smtpUsername := viper.GetString("smtp.username")
smtpPassword := viper.GetString("smtp.password")
var emailMessage string
// Construct 'emailAddresses' with comma-separated email addresses
var emailAddresses string
for i, email := range toEmails {
if i != 0 {
emailAddresses += ","
}
emailAddresses += email
}
header := "From: " + fromName + " <" + fromEmail + ">\n" +
"To: " + emailAddresses + "\n" +
"Subject: " + subject + "\n" +
"MIME-Version: 1.0\n" +
"Content-Type: multipart/related; boundary=boundary\n\n" +
"--boundary\n"
htmlContent := "Content-Type: text/html; charset=us-ascii\n\n" + htmlBody + "\n"
emailMessage = header + htmlContent
if inlineImages == nil {
emailMessage += "--boundary--"
} else {
for _, inlineImage := range inlineImages {
emailMessage += "--boundary\n"
var mimeType = inlineImage["mime_type"].(string)
var contentID = inlineImage["cid"].(string)
var imgBase64Str = inlineImage["content"].(string)
var image = "Content-Type: " + mimeType + "\n" +
"Content-Transfer-Encoding: base64\n" +
"Content-ID: <" + contentID + ">\n" +
"Content-Disposition: inline\n\n" + imgBase64Str + "\n"
emailMessage += image
}
emailMessage += "--boundary--"
}
// Send the email to each recipient
for _, toEmail := range toEmails {
auth := smtp.PlainAuth("", smtpUsername, smtpPassword, smtpServer)
err := smtp.SendMail(smtpServer+":"+smtpPort, auth, fromEmail, []string{toEmail}, []byte(emailMessage))
if err != nil {
return stacktrace.Propagate(err, "")
}
}
return nil
}
func sendViaTransmail(toEmails []string, fromName string, fromEmail string, subject string, htmlBody string, inlineImages []map[string]interface{}) error {
if len(toEmails) == 0 {
return ente.ErrBadRequest
}
@ -69,6 +142,7 @@ func SendTemplatedEmail(to []string, fromName string, fromEmail string, subject
if err != nil {
return stacktrace.Propagate(err, "")
}
return Send(to, fromName, fromEmail, subject, body, inlineImages)
}