From 1b0ba712605076314da9d15497a654e834aaf630 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte Date: Fri, 24 Feb 2023 14:09:36 +0100 Subject: [PATCH] specify recipient from query param and sed body and subject email from a template --- internal/http/services/sciencemesh/email.go | 118 ++++++++++++++++++ .../http/services/sciencemesh/sciencemesh.go | 3 + internal/http/services/sciencemesh/token.go | 40 +++--- pkg/smtpclient/smtpclient.go | 2 +- 4 files changed, 144 insertions(+), 19 deletions(-) create mode 100644 internal/http/services/sciencemesh/email.go diff --git a/internal/http/services/sciencemesh/email.go b/internal/http/services/sciencemesh/email.go new file mode 100644 index 00000000000..5d3ba576b9c --- /dev/null +++ b/internal/http/services/sciencemesh/email.go @@ -0,0 +1,118 @@ +// Copyright 2018-2023 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package sciencemesh + +import ( + "bytes" + "io" + "os" + "text/template" + + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" +) + +type emailParams struct { + User *userpb.User + Token string + MeshDirectoryURL string +} + +const defaultSubject = `ScienceMesh: {{.User.DisplayName}} wants to collaborate with you` + +const defaultBody = `Hi\n\n + +{{.User.DisplayName}} ({{.User.Mail}}) wants to start sharing OCM resources with you.\n +To accept the invite, please visit the following URL:\n +{{.MeshDirectoryURL}}?token={{.Token}}&providerDomain={{.User.Id.Idp}}\n\n + +Alternatively, you can visit your mesh provider and use the following details:\n +Token: {{.Token}}\n +ProviderDomain: {{.User.Id.Idp}}\n\n + +Best,\n +The ScienceMesh team` + +func (h *tokenHandler) sendEmail(recipient string, obj *emailParams) error { + subj, err := h.generateEmailSubject(obj) + if err != nil { + return err + } + + body, err := h.generateEmailBody(obj) + if err != nil { + return err + } + + return h.smtpCredentials.SendMail(recipient, subj, body) +} + +func (h *tokenHandler) generateEmailSubject(obj *emailParams) (string, error) { + var buf bytes.Buffer + err := h.tplSubj.Execute(&buf, obj) + return buf.String(), err +} + +func (h *tokenHandler) generateEmailBody(obj *emailParams) (string, error) { + var buf bytes.Buffer + err := h.tplBody.Execute(&buf, obj) + return buf.String(), err +} + +func (h *tokenHandler) initBodyTemplate(bodyTemplPath string) error { + var body string + if bodyTemplPath == "" { + body = defaultBody + } else { + f, err := os.Open(bodyTemplPath) + if err != nil { + return err + } + defer f.Close() + + data, err := io.ReadAll(f) + if err != nil { + return err + } + body = string(data) + } + + tpl, err := template.New("tpl_body").Parse(body) + if err != nil { + return err + } + + h.tplBody = tpl + return nil +} + +func (h *tokenHandler) initSubjectTemplate(subjTempl string) error { + var subj string + if subjTempl == "" { + subj = defaultSubject + } else { + subj = subjTempl + } + + tpl, err := template.New("tpl_subj").Parse(subj) + if err != nil { + return err + } + h.tplSubj = tpl + return nil +} diff --git a/internal/http/services/sciencemesh/sciencemesh.go b/internal/http/services/sciencemesh/sciencemesh.go index 5d7bc989d49..ec9a2355192 100644 --- a/internal/http/services/sciencemesh/sciencemesh.go +++ b/internal/http/services/sciencemesh/sciencemesh.go @@ -66,6 +66,9 @@ type config struct { SMTPCredentials *smtpclient.SMTPCredentials `mapstructure:"smtp_credentials"` GatewaySvc string `mapstructure:"gatewaysvc"` MeshDirectoryURL string `mapstructure:"mesh_directory_url"` + ProviderDomain string `mapstructure:"provider_domain"` + SubjectTemplate string `mapstructure:"subject_template"` + BodyTemplatePath string `mapstructure:"body_template_path"` } func (c *config) init() { diff --git a/internal/http/services/sciencemesh/token.go b/internal/http/services/sciencemesh/token.go index e0f61d295ef..286530f5e75 100644 --- a/internal/http/services/sciencemesh/token.go +++ b/internal/http/services/sciencemesh/token.go @@ -21,9 +21,9 @@ package sciencemesh import ( "encoding/json" "errors" - "fmt" "mime" "net/http" + "text/template" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" invitepb "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1" @@ -40,6 +40,9 @@ type tokenHandler struct { gatewayClient gateway.GatewayAPIClient smtpCredentials *smtpclient.SMTPCredentials meshDirectoryURL string + + tplSubj *template.Template + tplBody *template.Template } func (h *tokenHandler) init(c *config) error { @@ -54,6 +57,14 @@ func (h *tokenHandler) init(c *config) error { } h.meshDirectoryURL = c.MeshDirectoryURL + + if err := h.initSubjectTemplate(c.SubjectTemplate); err != nil { + return err + } + + if err := h.initBodyTemplate(c.BodyTemplatePath); err != nil { + return err + } return nil } @@ -63,30 +74,23 @@ func (h *tokenHandler) init(c *config) error { func (h *tokenHandler) Generate(w http.ResponseWriter, r *http.Request) { ctx := r.Context() + query := r.URL.Query() token, err := h.gatewayClient.GenerateInviteToken(ctx, &invitepb.GenerateInviteTokenRequest{ - Description: r.URL.Query().Get("description"), + Description: query.Get("description"), }) if err != nil { reqres.WriteError(w, r, reqres.APIErrorServerError, "error generating token", err) return } - if r.FormValue("recipient") != "" && h.smtpCredentials != nil { - usr := ctxpkg.ContextMustGetUser(ctx) - - // TODO: the message body needs to point to the meshdirectory service - subject := fmt.Sprintf("ScienceMesh: %s wants to collaborate with you", usr.DisplayName) - body := "Hi,\n\n" + - usr.DisplayName + " (" + usr.Mail + ") wants to start sharing OCM resources with you. " + - "To accept the invite, please visit the following URL:\n" + - h.meshDirectoryURL + "?token=" + token.InviteToken.Token + "&providerDomain=" + usr.Id.Idp + "\n\n" + - "Alternatively, you can visit your mesh provider and use the following details:\n" + - "Token: " + token.InviteToken.Token + "\n" + - "ProviderDomain: " + usr.Id.Idp + "\n\n" + - "Best,\nThe ScienceMesh team" - - err = h.smtpCredentials.SendMail(r.FormValue("recipient"), subject, body) - if err != nil { + recipient := query.Get("recipient") + if recipient != "" && h.smtpCredentials != nil { + templObj := &emailParams{ + User: ctxpkg.ContextMustGetUser(ctx), + Token: token.InviteToken.Token, + MeshDirectoryURL: h.meshDirectoryURL, + } + if err := h.sendEmail(recipient, templObj); err != nil { reqres.WriteError(w, r, reqres.APIErrorServerError, "error sending token by mail", err) return } diff --git a/pkg/smtpclient/smtpclient.go b/pkg/smtpclient/smtpclient.go index 77546089d46..21fa14b304d 100644 --- a/pkg/smtpclient/smtpclient.go +++ b/pkg/smtpclient/smtpclient.go @@ -71,7 +71,7 @@ func (creds *SMTPCredentials) SendMail(recipient, subject, body string) error { "Date": time.Now().Format(time.RFC1123Z), "Message-ID": uuid.New().String(), "MIME-Version": "1.0", - "Content-Type": "text/plain; charset=\"utf-8\"", + "Content-Type": "text/html; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", }