mirror of
https://github.com/go-gitea/gitea
synced 2025-12-07 13:28:25 +00:00
fix
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mailer
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/middleware"
|
||||
)
|
||||
|
||||
// Create New mail message use MailFrom and MailUser
|
||||
func NewMailMessageFrom(To []string, from, subject, body string) Message {
|
||||
msg := NewHtmlMessage(To, from, subject, body)
|
||||
msg.User = base.MailService.User
|
||||
return msg
|
||||
}
|
||||
|
||||
// Create New mail message use MailFrom and MailUser
|
||||
func NewMailMessage(To []string, subject, body string) Message {
|
||||
return NewMailMessageFrom(To, base.MailService.User, subject, body)
|
||||
}
|
||||
|
||||
func GetMailTmplData(user *models.User) map[interface{}]interface{} {
|
||||
data := make(map[interface{}]interface{}, 10)
|
||||
data["AppName"] = base.AppName
|
||||
data["AppVer"] = base.AppVer
|
||||
data["AppUrl"] = base.AppUrl
|
||||
data["AppLogo"] = base.AppLogo
|
||||
data["ActiveCodeLives"] = base.Service.ActiveCodeLives / 60
|
||||
data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives / 60
|
||||
if user != nil {
|
||||
data["User"] = user
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// create a time limit code for user active
|
||||
func CreateUserActiveCode(user *models.User, startInf interface{}) string {
|
||||
minutes := base.Service.ActiveCodeLives
|
||||
data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands
|
||||
code := base.CreateTimeLimitCode(data, minutes, startInf)
|
||||
|
||||
// add tail hex username
|
||||
code += hex.EncodeToString([]byte(user.LowerName))
|
||||
return code
|
||||
}
|
||||
|
||||
// Send user register mail with active code
|
||||
func SendRegisterMail(r *middleware.Render, user *models.User) {
|
||||
code := CreateUserActiveCode(user, nil)
|
||||
subject := "Register success, Welcome"
|
||||
|
||||
data := GetMailTmplData(user)
|
||||
data["Code"] = code
|
||||
body, err := r.HTMLString("mail/auth/register_success", data)
|
||||
if err != nil {
|
||||
log.Error("mail.SendRegisterMail(fail to render): %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := NewMailMessage([]string{user.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, send register mail", user.Id)
|
||||
|
||||
SendAsync(&msg)
|
||||
}
|
||||
|
||||
// Send email verify active email.
|
||||
func SendActiveMail(r *middleware.Render, user *models.User) {
|
||||
code := CreateUserActiveCode(user, nil)
|
||||
|
||||
subject := "Verify your e-mail address"
|
||||
|
||||
data := GetMailTmplData(user)
|
||||
data["Code"] = code
|
||||
body, err := r.HTMLString("mail/auth/active_email", data)
|
||||
if err != nil {
|
||||
log.Error("mail.SendActiveMail(fail to render): %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := NewMailMessage([]string{user.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, send active mail", user.Id)
|
||||
|
||||
SendAsync(&msg)
|
||||
}
|
||||
|
||||
// Send reset password email.
|
||||
func SendResetPasswdMail(r *middleware.Render, user *models.User) {
|
||||
code := CreateUserActiveCode(user, nil)
|
||||
|
||||
subject := "Reset your password"
|
||||
|
||||
data := GetMailTmplData(user)
|
||||
data["Code"] = code
|
||||
body, err := r.HTMLString("mail/auth/reset_passwd", data)
|
||||
if err != nil {
|
||||
log.Error("mail.SendResetPasswdMail(fail to render): %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
msg := NewMailMessage([]string{user.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, send reset password email", user.Id)
|
||||
|
||||
SendAsync(&msg)
|
||||
}
|
||||
|
||||
// SendIssueNotifyMail sends mail notification of all watchers of repository.
|
||||
func SendIssueNotifyMail(user, owner *models.User, repo *models.Repository, issue *models.Issue) ([]string, error) {
|
||||
watches, err := models.GetWatches(repo.Id)
|
||||
if err != nil {
|
||||
return nil, errors.New("mail.NotifyWatchers(get watches): " + err.Error())
|
||||
}
|
||||
|
||||
tos := make([]string, 0, len(watches))
|
||||
for i := range watches {
|
||||
uid := watches[i].UserId
|
||||
if user.Id == uid {
|
||||
continue
|
||||
}
|
||||
u, err := models.GetUserById(uid)
|
||||
if err != nil {
|
||||
return nil, errors.New("mail.NotifyWatchers(get user): " + err.Error())
|
||||
}
|
||||
tos = append(tos, u.Email)
|
||||
}
|
||||
|
||||
if len(tos) == 0 {
|
||||
return tos, nil
|
||||
}
|
||||
|
||||
subject := fmt.Sprintf("[%s] %s", repo.Name, issue.Name)
|
||||
content := fmt.Sprintf("%s<br>-<br> <a href=\"%s%s/%s/issues/%d\">View it on Gogs</a>.",
|
||||
base.RenderSpecialLink([]byte(issue.Content), owner.Name+"/"+repo.Name),
|
||||
base.AppUrl, owner.Name, repo.Name, issue.Index)
|
||||
msg := NewMailMessageFrom(tos, user.Name, subject, content)
|
||||
msg.Info = fmt.Sprintf("Subject: %s, send issue notify emails", subject)
|
||||
SendAsync(&msg)
|
||||
return tos, nil
|
||||
}
|
||||
|
||||
// SendIssueMentionMail sends mail notification for who are mentioned in issue.
|
||||
func SendIssueMentionMail(user, owner *models.User, repo *models.Repository, issue *models.Issue, tos []string) error {
|
||||
if len(tos) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
issueLink := fmt.Sprintf("%s%s/%s/issues/%d", base.AppUrl, owner.Name, repo.Name, issue.Index)
|
||||
body := fmt.Sprintf(`%s mentioned you.`)
|
||||
subject := fmt.Sprintf("[%s] %s", repo.Name, issue.Name)
|
||||
content := fmt.Sprintf("%s<br>-<br> <a href=\"%s\">View it on Gogs</a>.", body, issueLink)
|
||||
msg := NewMailMessageFrom(tos, user.Name, subject, content)
|
||||
msg.Info = fmt.Sprintf("Subject: %s, send issue mention emails", subject)
|
||||
SendAsync(&msg)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mailer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
To []string
|
||||
From string
|
||||
Subject string
|
||||
Body string
|
||||
User string
|
||||
Type string
|
||||
Massive bool
|
||||
Info string
|
||||
}
|
||||
|
||||
// create mail content
|
||||
func (m Message) Content() string {
|
||||
// set mail type
|
||||
contentType := "text/plain; charset=UTF-8"
|
||||
if m.Type == "html" {
|
||||
contentType = "text/html; charset=UTF-8"
|
||||
}
|
||||
|
||||
// create mail content
|
||||
content := "From: " + m.From + "<" + m.User +
|
||||
">\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body
|
||||
return content
|
||||
}
|
||||
|
||||
var mailQueue chan *Message
|
||||
|
||||
func NewMailerContext() {
|
||||
mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10))
|
||||
go processMailQueue()
|
||||
}
|
||||
|
||||
func processMailQueue() {
|
||||
for {
|
||||
select {
|
||||
case msg := <-mailQueue:
|
||||
num, err := Send(msg)
|
||||
tos := strings.Join(msg.To, "; ")
|
||||
info := ""
|
||||
if err != nil {
|
||||
if len(msg.Info) > 0 {
|
||||
info = ", info: " + msg.Info
|
||||
}
|
||||
log.Error(fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err))
|
||||
} else {
|
||||
log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Direct Send mail message
|
||||
func Send(msg *Message) (int, error) {
|
||||
log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
|
||||
host := strings.Split(base.MailService.Host, ":")
|
||||
|
||||
// get message body
|
||||
content := msg.Content()
|
||||
|
||||
auth := smtp.PlainAuth("", base.MailService.User, base.MailService.Passwd, host[0])
|
||||
|
||||
if len(msg.To) == 0 {
|
||||
return 0, fmt.Errorf("empty receive emails")
|
||||
}
|
||||
|
||||
if len(msg.Body) == 0 {
|
||||
return 0, fmt.Errorf("empty email body")
|
||||
}
|
||||
|
||||
if msg.Massive {
|
||||
// send mail to multiple emails one by one
|
||||
num := 0
|
||||
for _, to := range msg.To {
|
||||
body := []byte("To: " + to + "\r\n" + content)
|
||||
err := smtp.SendMail(base.MailService.Host, auth, msg.From, []string{to}, body)
|
||||
if err != nil {
|
||||
return num, err
|
||||
}
|
||||
num++
|
||||
}
|
||||
return num, nil
|
||||
} else {
|
||||
body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content)
|
||||
|
||||
// send to multiple emails in one message
|
||||
err := smtp.SendMail(base.MailService.Host, auth, msg.From, msg.To, body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Async Send mail message
|
||||
func SendAsync(msg *Message) {
|
||||
go func() {
|
||||
mailQueue <- msg
|
||||
}()
|
||||
}
|
||||
|
||||
// Create html mail message
|
||||
func NewHtmlMessage(To []string, From, Subject, Body string) Message {
|
||||
return Message{
|
||||
To: To,
|
||||
From: From,
|
||||
Subject: Subject,
|
||||
Body: Body,
|
||||
Type: "html",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user