Compare commits

..

3 Commits

Author SHA1 Message Date
Yang Luo
66d0758b13 feat: fix DisableVerificationCode bug about empty email and phone 2024-04-19 13:28:13 +08:00
Yang Luo
46ad0fe0be Improve Email Send() logic 2024-04-11 19:09:48 +08:00
Yang Luo
6b637e3b2e feat: fix SendgridEmailProvider error handling, fix send-email template 2024-04-11 00:18:39 +08:00
5 changed files with 96 additions and 49 deletions

View File

@@ -261,16 +261,20 @@ func (c *ApiController) Signup() {
c.SetSessionUsername(user.GetId())
}
err = object.DisableVerificationCode(authForm.Email)
if err != nil {
c.ResponseError(err.Error())
return
if authForm.Email != "" {
err = object.DisableVerificationCode(authForm.Email)
if err != nil {
c.ResponseError(err.Error())
return
}
}
err = object.DisableVerificationCode(checkPhone)
if err != nil {
c.ResponseError(err.Error())
return
if checkPhone != "" {
err = object.DisableVerificationCode(checkPhone)
if err != nil {
c.ResponseError(err.Error())
return
}
}
c.Ctx.Input.SetParam("recordUserId", user.GetId())

View File

@@ -113,25 +113,25 @@ func (c *ApiController) SendEmail() {
content := emailForm.Content
if content == "" {
code := "123456"
content = provider.Content
}
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
content = strings.Replace(provider.Content, "%s", code, 1)
if !strings.HasPrefix(userId, "app/") {
var user *object.User
user, err = object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
userString := "Hi"
if user != nil {
userString = user.GetFriendlyName()
}
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
code := "123456"
// "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes."
content = strings.Replace(content, "%s", code, 1)
userString := "Hi"
if !strings.HasPrefix(userId, "app/") {
var user *object.User
user, err = object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
if user != nil {
userString = user.GetFriendlyName()
}
}
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
for _, receiver := range emailForm.Receivers {
err = object.SendEmail(provider, emailForm.Title, content, receiver, emailForm.Sender)

View File

@@ -111,46 +111,44 @@ func newEmail(fromAddress string, toAddress string, subject string, content stri
Subject: subject,
HTML: content,
},
Importance: importanceNormal,
Importance: importanceNormal,
Attachments: []Attachment{},
}
}
func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
postBody, err := json.Marshal(e)
if err != nil {
return fmt.Errorf("email JSON marshall failed: %s", err)
}
func (a *AzureACSEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
email := newEmail(fromAddress, toAddress, subject, content)
bodyBuffer := bytes.NewBuffer(postBody)
postBody, err := json.Marshal(email)
if err != nil {
return err
}
endpoint := strings.TrimSuffix(a.Endpoint, "/")
url := fmt.Sprintf("%s/emails:send?api-version=2023-03-31", endpoint)
bodyBuffer := bytes.NewBuffer(postBody)
req, err := http.NewRequest("POST", url, bodyBuffer)
if err != nil {
return fmt.Errorf("error creating AzureACS API request: %s", err)
return err
}
// Sign the request using the AzureACS access key and HMAC-SHA256
err = signRequestHMAC(a.AccessKey, req)
if err != nil {
return fmt.Errorf("error signing AzureACS API request: %s", err)
return err
}
req.Header.Set("Content-Type", "application/json")
// Some important header
req.Header.Set("repeatability-request-id", uuid.New().String())
req.Header.Set("repeatability-first-sent", time.Now().UTC().Format(http.TimeFormat))
// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("error sending AzureACS API request: %s", err)
return err
}
defer resp.Body.Close()
// Response error Handling
if resp.StatusCode == http.StatusBadRequest || resp.StatusCode == http.StatusUnauthorized {
commError := ErrorResponse{}
@@ -159,11 +157,11 @@ func (a *AzureACSEmailProvider) sendEmail(e *Email) error {
return err
}
return fmt.Errorf("error sending email: %s", commError.Error.Message)
return fmt.Errorf("status code: %d, error message: %s", resp.StatusCode, commError.Error.Message)
}
if resp.StatusCode != http.StatusAccepted {
return fmt.Errorf("error sending email: status: %d", resp.StatusCode)
return fmt.Errorf("status code: %d", resp.StatusCode)
}
return nil
@@ -221,9 +219,3 @@ func GetHmac(content string, key []byte) string {
return base64.StdEncoding.EncodeToString(hmac.Sum(nil))
}
func (a *AzureACSEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
e := newEmail(fromAddress, toAddress, subject, content)
return a.sendEmail(e)
}

View File

@@ -15,6 +15,10 @@
package email
import (
"encoding/json"
"fmt"
"strings"
"github.com/sendgrid/sendgrid-go"
"github.com/sendgrid/sendgrid-go/helpers/mail"
)
@@ -23,6 +27,14 @@ type SendgridEmailProvider struct {
ApiKey string
}
type SendgridResponseBody struct {
Errors []struct {
Message string `json:"message"`
Field interface{} `json:"field"`
Help interface{} `json:"help"`
} `json:"errors"`
}
func NewSendgridEmailProvider(apiKey string) *SendgridEmailProvider {
return &SendgridEmailProvider{ApiKey: apiKey}
}
@@ -32,6 +44,25 @@ func (s *SendgridEmailProvider) Send(fromAddress string, fromName, toAddress str
to := mail.NewEmail("", toAddress)
message := mail.NewSingleEmail(from, subject, to, "", content)
client := sendgrid.NewSendClient(s.ApiKey)
_, err := client.Send(message)
return err
response, err := client.Send(message)
if err != nil {
return err
}
if response.StatusCode >= 300 {
var responseBody SendgridResponseBody
err = json.Unmarshal([]byte(response.Body), &responseBody)
if err != nil {
return err
}
messages := []string{}
for _, sendgridError := range responseBody.Errors {
messages = append(messages, sendgridError.Message)
}
return fmt.Errorf("SendGrid status code: %d, error message: %s", response.StatusCode, strings.Join(messages, " | "))
}
return nil
}

View File

@@ -110,6 +110,26 @@ class VerificationListPage extends BaseListPage {
);
},
},
{
title: i18next.t("general:Client IP"),
dataIndex: "remoteAddr",
key: "remoteAddr",
width: "100px",
sorter: true,
...this.getColumnSearchProps("remoteAddr"),
render: (text, record, index) => {
let clientIp = text;
if (clientIp.endsWith(": ")) {
clientIp = clientIp.slice(0, -2);
}
return (
<a target="_blank" rel="noreferrer" href={`https://db-ip.com/${clientIp}`}>
{clientIp}
</a>
);
},
},
{
title: i18next.t("verification:Receiver"),
dataIndex: "receiver",