Implement sendmail (#355)
* Implemented sendmail. This piggybacks on existing configuration to keep the change simple * Changed privicy of new sendSMTP and sendSendmail functions * Fixed Lint errors * Seperated SMTP and sendmail into their own senders * Making new structs private as they should not be used externally now * Added sendmail setting to ini file * Minor code cleanuprelease/v1.15
parent
8de8ec027d
commit
d4924d45d6
|
@ -226,6 +226,10 @@ USER =
|
|||
PASSWD =
|
||||
; Use text/html as alternative format of content
|
||||
ENABLE_HTML_ALTERNATIVE = false
|
||||
; Enable sendmail (override SMTP)
|
||||
USE_SENDMAIL = false
|
||||
; Specifiy an alternative sendmail binary
|
||||
SENDMAIL_PATH = sendmail
|
||||
|
||||
[cache]
|
||||
; Either "memory", "redis", or "memcache", default is "memory"
|
||||
|
|
|
@ -40,7 +40,7 @@ func InitMailRender(tmpls *template.Template) {
|
|||
|
||||
// SendTestMail sends a test mail
|
||||
func SendTestMail(email string) error {
|
||||
return gomail.Send(&mailer.Sender{}, mailer.NewMessage([]string{email}, "Gitea Test Email!", "Gitea Test Email!").Message)
|
||||
return gomail.Send(mailer.Sender, mailer.NewMessage([]string{email}, "Gitea Test Email!", "Gitea Test Email!").Message)
|
||||
}
|
||||
|
||||
// SendUserMail sends a mail to the user
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"net"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -87,12 +88,12 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// Sender mail sender
|
||||
type Sender struct {
|
||||
// Sender SMTP mail sender
|
||||
type smtpSender struct {
|
||||
}
|
||||
|
||||
// Send send email
|
||||
func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
|
||||
func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
|
||||
opts := setting.MailService
|
||||
|
||||
host, port, err := net.SplitHostPort(opts.Host)
|
||||
|
@ -195,14 +196,51 @@ func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
|
|||
return client.Quit()
|
||||
}
|
||||
|
||||
func processMailQueue() {
|
||||
sender := &Sender{}
|
||||
// Sender sendmail mail sender
|
||||
type sendmailSender struct {
|
||||
}
|
||||
|
||||
// Send send email
|
||||
func (s *sendmailSender) Send(from string, to []string, msg io.WriterTo) error {
|
||||
var err error
|
||||
var closeError error
|
||||
var waitError error
|
||||
|
||||
args := []string{"-F", from, "-i"}
|
||||
args = append(args, to...)
|
||||
log.Trace("Sending with: %s %v", setting.MailService.SendmailPath, args)
|
||||
cmd := exec.Command(setting.MailService.SendmailPath, args...)
|
||||
pipe, err := cmd.StdinPipe()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_,err = msg.WriteTo(pipe)
|
||||
|
||||
// we MUST close the pipe or sendmail will hang waiting for more of the message
|
||||
// Also we should wait on our sendmail command even if something fails
|
||||
closeError = pipe.Close()
|
||||
waitError = cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
} else if closeError != nil {
|
||||
return closeError
|
||||
} else {
|
||||
return waitError
|
||||
}
|
||||
}
|
||||
|
||||
func processMailQueue() {
|
||||
for {
|
||||
select {
|
||||
case msg := <-mailQueue:
|
||||
log.Trace("New e-mail sending request %s: %s", msg.GetHeader("To"), msg.Info)
|
||||
if err := gomail.Send(sender, msg.Message); err != nil {
|
||||
if err := gomail.Send(Sender, msg.Message); err != nil {
|
||||
log.Error(3, "Fail to send emails %s: %s - %v", msg.GetHeader("To"), msg.Info, err)
|
||||
} else {
|
||||
log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info)
|
||||
|
@ -213,6 +251,9 @@ func processMailQueue() {
|
|||
|
||||
var mailQueue chan *Message
|
||||
|
||||
// Sender sender for sending mail synchronously
|
||||
var Sender gomail.Sender
|
||||
|
||||
// NewContext start mail queue service
|
||||
func NewContext() {
|
||||
// Need to check if mailQueue is nil because in during reinstall (user had installed
|
||||
|
@ -222,6 +263,13 @@ func NewContext() {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
if setting.MailService.UseSendmail {
|
||||
Sender = &sendmailSender{}
|
||||
} else {
|
||||
Sender = &smtpSender{}
|
||||
}
|
||||
|
||||
mailQueue = make(chan *Message, setting.MailService.QueueLength)
|
||||
go processMailQueue()
|
||||
}
|
||||
|
|
|
@ -858,18 +858,25 @@ func newSessionService() {
|
|||
|
||||
// Mailer represents mail service.
|
||||
type Mailer struct {
|
||||
// Mailer
|
||||
QueueLength int
|
||||
Name string
|
||||
Host string
|
||||
From string
|
||||
FromEmail string
|
||||
EnableHTMLAlternative bool
|
||||
|
||||
// SMTP sender
|
||||
Host string
|
||||
User, Passwd string
|
||||
DisableHelo bool
|
||||
HeloHostname string
|
||||
SkipVerify bool
|
||||
UseCertificate bool
|
||||
CertFile, KeyFile string
|
||||
EnableHTMLAlternative bool
|
||||
|
||||
// Sendmail sender
|
||||
UseSendmail bool
|
||||
SendmailPath string
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -887,6 +894,8 @@ func newMailService() {
|
|||
MailService = &Mailer{
|
||||
QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
|
||||
Name: sec.Key("NAME").MustString(AppName),
|
||||
EnableHTMLAlternative: sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(),
|
||||
|
||||
Host: sec.Key("HOST").String(),
|
||||
User: sec.Key("USER").String(),
|
||||
Passwd: sec.Key("PASSWD").String(),
|
||||
|
@ -896,7 +905,9 @@ func newMailService() {
|
|||
UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
|
||||
CertFile: sec.Key("CERT_FILE").String(),
|
||||
KeyFile: sec.Key("KEY_FILE").String(),
|
||||
EnableHTMLAlternative: sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(),
|
||||
|
||||
UseSendmail: sec.Key("USE_SENDMAIL").MustBool(),
|
||||
SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
|
||||
}
|
||||
MailService.From = sec.Key("FROM").MustString(MailService.User)
|
||||
|
||||
|
|
Loading…
Reference in New Issue