Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sendmail #355

Merged
merged 8 commits into from
Dec 25, 2016
45 changes: 43 additions & 2 deletions modules/mailer/mailer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net"
"net/smtp"
"os"
"os/exec"
"strings"
"time"

Expand Down Expand Up @@ -91,8 +92,7 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
type Sender struct {
}

// Send send email
func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
func (s *Sender) sendSMTP(from string, to []string, msg io.WriterTo) error {
opts := setting.MailService

host, port, err := net.SplitHostPort(opts.Host)
Expand Down Expand Up @@ -195,6 +195,47 @@ func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
return client.Quit()
}

func (s *Sender) sendSendmail(from string, to []string, msg io.WriterTo) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really be implemented as a separate Sender instead, this way you don't have to do checks for every single sent email...

Config-reading and setup could be done here: https://github.com/go-gitea/gitea/pull/355/files#diff-bdf9b0a2ed1413ee986db72787e5b5d7R265

var err error
var closeError error
var waitError error

args := []string{"-F", from, "-i"}
args = append(args, to...)
cmd := exec.Command(setting.MailService.Host, 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
}
}

// Send send email
func (s *Sender) Send(from string, to []string, msg io.WriterTo) error {
if strings.Contains(setting.MailService.Host, "/") {
return s.sendSendmail(from, to, msg)
}
return s.sendSMTP(from, to, msg)
}

func processMailQueue() {
sender := &Sender{}

Expand Down