gitea源码

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package sender
  4. import (
  5. "fmt"
  6. "io"
  7. "os/exec"
  8. "strings"
  9. "code.gitea.io/gitea/modules/graceful"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/process"
  12. "code.gitea.io/gitea/modules/setting"
  13. )
  14. // SendmailSender Sender sendmail mail sender
  15. type SendmailSender struct{}
  16. var _ Sender = &SendmailSender{}
  17. // Send send email
  18. func (s *SendmailSender) Send(from string, to []string, msg io.WriterTo) error {
  19. var err error
  20. var closeError error
  21. var waitError error
  22. envelopeFrom := from
  23. if setting.MailService.OverrideEnvelopeFrom {
  24. envelopeFrom = setting.MailService.EnvelopeFrom
  25. }
  26. args := []string{"-f", envelopeFrom, "-i"}
  27. args = append(args, setting.MailService.SendmailArgs...)
  28. args = append(args, to...)
  29. log.Trace("Sending with: %s %v", setting.MailService.SendmailPath, args)
  30. desc := fmt.Sprintf("SendMail: %s %v", setting.MailService.SendmailPath, args)
  31. ctx, _, finished := process.GetManager().AddContextTimeout(graceful.GetManager().HammerContext(), setting.MailService.SendmailTimeout, desc)
  32. defer finished()
  33. cmd := exec.CommandContext(ctx, setting.MailService.SendmailPath, args...)
  34. pipe, err := cmd.StdinPipe()
  35. if err != nil {
  36. return err
  37. }
  38. process.SetSysProcAttribute(cmd)
  39. if err = cmd.Start(); err != nil {
  40. _ = pipe.Close()
  41. return err
  42. }
  43. if setting.MailService.SendmailConvertCRLF {
  44. buf := &strings.Builder{}
  45. _, err = msg.WriteTo(buf)
  46. if err == nil {
  47. _, err = strings.NewReplacer("\r\n", "\n").WriteString(pipe, buf.String())
  48. }
  49. } else {
  50. _, err = msg.WriteTo(pipe)
  51. }
  52. // we MUST close the pipe or sendmail will hang waiting for more of the message
  53. // Also we should wait on our sendmail command even if something fails
  54. closeError = pipe.Close()
  55. waitError = cmd.Wait()
  56. if err != nil {
  57. return err
  58. } else if closeError != nil {
  59. return closeError
  60. }
  61. return waitError
  62. }