diff --git a/arn/APIKeys.go b/arn/APIKeys.go index cac7a983..57334167 100644 --- a/arn/APIKeys.go +++ b/arn/APIKeys.go @@ -72,11 +72,10 @@ type APIKeysData struct { PrivateKey string `json:"privateKey"` } `json:"vapid"` - SMTP struct { - Server string `json:"server"` - Address string `json:"address"` - Password string `json:"password"` - } `json:"smtp"` + Mailgun struct { + Domain string `json:"domain"` + PrivateKey string `json:"privateKey"` + } `json:"mailgun"` S3 struct { ID string `json:"id"` diff --git a/arn/EmailRenderer.go b/arn/EmailRenderer.go new file mode 100644 index 00000000..4dea51fd --- /dev/null +++ b/arn/EmailRenderer.go @@ -0,0 +1,33 @@ +package arn + +import ( + "context" + "fmt" + "time" + + "github.com/mailgun/mailgun-go/v3" +) + +// HTMLEmailRenderer is the instance used for rendering emails. +var HTMLEmailRenderer EmailRenderer + +// EmailRenderer is an interface for rendering HTML emails. +type EmailRenderer interface { + Notification(notification *Notification) string +} + +// SendEmail sends an e-mail. +func SendEmail(email string, subject string, html string) error { + mg := mailgun.NewMailgun(APIKeys.Mailgun.Domain, APIKeys.Mailgun.PrivateKey) + sender := fmt.Sprintf("Anime Notifier ", APIKeys.Mailgun.Domain) + message := mg.NewMessage(sender, subject, "", email) + message.SetHtml(html) + + // Allow a 10-second timeout + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + + // Send the message + _, _, err := mg.Send(ctx, message) + return err +} diff --git a/arn/User.go b/arn/User.go index 201fa467..d33aa8c6 100644 --- a/arn/User.go +++ b/arn/User.go @@ -208,6 +208,17 @@ func (user *User) SendNotification(pushNotification *PushNotification) { // Save changes subs.Save() + // Send email notification + if IsDevelopment() && user.ID == "4J6qpK1ve" { + subject := notification.Title + html := HTMLEmailRenderer.Notification(notification) + err := SendEmail(user.Email, subject, html) + + if err != nil { + fmt.Println(err) + } + } + // Send an event to the user's open tabs user.BroadcastEvent(&aero.Event{ Name: "notificationCount", diff --git a/arn/mailer/mailer.go b/arn/mailer/mailer.go deleted file mode 100644 index 3b71cede..00000000 --- a/arn/mailer/mailer.go +++ /dev/null @@ -1,20 +0,0 @@ -package mailer - -import ( - "github.com/animenotifier/notify.moe/arn" - gomail "gopkg.in/gomail.v2" -) - -// SendEmailNotification sends an e-mail notification. -func SendEmailNotification(email string, notification *arn.PushNotification) error { - m := gomail.NewMessage() - m.SetHeader("From", arn.APIKeys.SMTP.Address) - m.SetHeader("To", email) - m.SetHeader("Subject", notification.Title) - m.SetBody("text/html", "

"+notification.Message+"

Anime cover image

") - - d := gomail.NewDialer(arn.APIKeys.SMTP.Server, 587, arn.APIKeys.SMTP.Address, arn.APIKeys.SMTP.Password) - - // Send the email - return d.DialAndSend(m) -} diff --git a/email.go b/email.go new file mode 100644 index 00000000..f5630855 --- /dev/null +++ b/email.go @@ -0,0 +1,14 @@ +package main + +import ( + "github.com/animenotifier/notify.moe/arn" + "github.com/animenotifier/notify.moe/components" +) + +// HTMLEmailRenderer uses pixy templates to render the HTML for our emails. +type HTMLEmailRenderer struct{} + +// Notification renders a notification email. +func (writer *HTMLEmailRenderer) Notification(notification *arn.Notification) string { + return components.NotificationEmail(notification) +} diff --git a/go.mod b/go.mod index 0b799fd3..b1ba62f6 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect github.com/json-iterator/go v1.1.7 github.com/logpacker/PayPal-Go-SDK v1.1.4 + github.com/mailgun/mailgun-go/v3 v3.6.0 github.com/minio/minio-go/v6 v6.0.32 github.com/mssola/user_agent v0.5.0 github.com/pariz/gountries v0.0.0-20171019111738-adb00f6513a3 diff --git a/go.sum b/go.sum index e5e4827c..eb3358c4 100644 --- a/go.sum +++ b/go.sum @@ -128,9 +128,17 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dlespiau/covertool v0.0.0-20180314162135-b0c4c6d0583a/go.mod h1:/eQMcW3eA1bzKx23ZYI2H3tXPdJB5JWYTHzoUPBvQY4= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/frankban/quicktest v1.4.0 h1:rCSCih1FnSWJEel/eub9wclBSqpF2F/PuvxUWGWnbO8= github.com/frankban/quicktest v1.4.0/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ= github.com/gernest/wow v0.1.0/go.mod h1:dEPabJRi5BneI1Nev1VWo0ZlcTWibHWp43qxKms4elY= +github.com/go-chi/chi v4.0.0+incompatible h1:SiLLEDyAkqNnw+T/uDTf3aFB9T4FTrwMpuYrgaRcnW4= +github.com/go-chi/chi v4.0.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -185,6 +193,10 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/logpacker/PayPal-Go-SDK v1.1.4 h1:YXfHvkDLMKkdmHmeusBum45MMG4n3iJeeQ9mZPWPAUQ= github.com/logpacker/PayPal-Go-SDK v1.1.4/go.mod h1:DUf5ncyG0n3jFnU9VsuQqe/Vo6KHtWQ6HYf80JwP4rY= +github.com/mailgun/mailgun-go/v3 v3.6.0 h1:oQWhyDTFjSiuO6vx1PRlfLZ7Fu+oK0Axn0UTREh3k/g= +github.com/mailgun/mailgun-go/v3 v3.6.0/go.mod h1:E81I5Agcfi/u1szdehi6p6ttdRX/UD3Rq2SrUzwyFIU= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= @@ -217,6 +229,8 @@ github.com/mssola/user_agent v0.5.0 h1:gRF7/x8cKt8qzAosYGsBNyirta+F8fvYDlJrgXws9 github.com/mssola/user_agent v0.5.0/go.mod h1:UFiKPVaShrJGW93n4uo8dpPdg1BSVpw2P9bneo0Mtp8= github.com/pariz/gountries v0.0.0-20171019111738-adb00f6513a3 h1:lmQNznFSupyfCDE9d7wdKOU8UiVwWEoYwv8wo6rSgy0= github.com/pariz/gountries v0.0.0-20171019111738-adb00f6513a3/go.mod h1:U0ETmPPEsfd7CpUKNMYi68xIOL8Ww4jPZlaqNngcwqs= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk= diff --git a/main.go b/main.go index c69758e6..40054fc7 100644 --- a/main.go +++ b/main.go @@ -81,6 +81,9 @@ func configure(app *aero.Application) *aero.Application { color.Red(err.Error()) }) + // Emails + arn.HTMLEmailRenderer = &HTMLEmailRenderer{} + // Check that this is the server if !arn.Node.IsServer() && !arn.IsTest() { panic("Another program is currently running as the database server") diff --git a/mixins/Email.pixy b/mixins/Email.pixy new file mode 100644 index 00000000..8c3eb168 --- /dev/null +++ b/mixins/Email.pixy @@ -0,0 +1,10 @@ +component NotificationEmail(notification *arn.Notification) + h2= notification.Message + + p + img(src=notification.Icon, alt="Icon", style="width:125px; height:125px; object-fit: cover;") + + p= notification.Message + + if notification.Link != "" + a(href=notification.Link, target="_blank") View it on Anime Notifier \ No newline at end of file