| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- // Copyright 2024 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package sender
-
- import (
- "fmt"
- "io"
- "os/exec"
- "strings"
-
- "code.gitea.io/gitea/modules/graceful"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/process"
- "code.gitea.io/gitea/modules/setting"
- )
-
- // SendmailSender Sender sendmail mail sender
- type SendmailSender struct{}
-
- var _ Sender = &SendmailSender{}
-
- // Send send email
- func (s *SendmailSender) Send(from string, to []string, msg io.WriterTo) error {
- var err error
- var closeError error
- var waitError error
-
- envelopeFrom := from
- if setting.MailService.OverrideEnvelopeFrom {
- envelopeFrom = setting.MailService.EnvelopeFrom
- }
-
- args := []string{"-f", envelopeFrom, "-i"}
- args = append(args, setting.MailService.SendmailArgs...)
- args = append(args, to...)
- log.Trace("Sending with: %s %v", setting.MailService.SendmailPath, args)
-
- desc := fmt.Sprintf("SendMail: %s %v", setting.MailService.SendmailPath, args)
-
- ctx, _, finished := process.GetManager().AddContextTimeout(graceful.GetManager().HammerContext(), setting.MailService.SendmailTimeout, desc)
- defer finished()
-
- cmd := exec.CommandContext(ctx, setting.MailService.SendmailPath, args...)
- pipe, err := cmd.StdinPipe()
- if err != nil {
- return err
- }
- process.SetSysProcAttribute(cmd)
-
- if err = cmd.Start(); err != nil {
- _ = pipe.Close()
- return err
- }
-
- if setting.MailService.SendmailConvertCRLF {
- buf := &strings.Builder{}
- _, err = msg.WriteTo(buf)
- if err == nil {
- _, err = strings.NewReplacer("\r\n", "\n").WriteString(pipe, buf.String())
- }
- } else {
- _, 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
- }
- return waitError
- }
|