gitea

Development moved to Codeberg

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  100. 100
  101. 101
  102. 102
  103. 103
  104. 104
  105. 105
  106. 106
  107. 107
  108. 108
  109. 109
  110. 110
  111. 111
  112. 112
  113. 113
  114. 114
  115. 115
  116. 116
  117. 117
  118. 118
  119. 119
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package log

import (
	"fmt"
	"net/smtp"
	"strings"

	"code.gitea.io/gitea/modules/json"
)

type smtpWriter struct {
	owner *SMTPLogger
}

// Write sends the message as an email
func (s *smtpWriter) Write(p []byte) (int, error) {
	return s.owner.sendMail(p)
}

// Close does nothing
func (s *smtpWriter) Close() error {
	return nil
}

// SMTPLogger implements LoggerProvider and is used to send emails via given SMTP-server.
type SMTPLogger struct {
	WriterLogger
	Username           string   `json:"Username"`
	Password           string   `json:"password"`
	Host               string   `json:"host"`
	Subject            string   `json:"subject"`
	RecipientAddresses []string `json:"sendTos"`
	sendMailFn         func(string, smtp.Auth, string, []string, []byte) error
}

// NewSMTPLogger creates smtp writer.
func NewSMTPLogger() LoggerProvider {
	s := &SMTPLogger{}
	s.Level = TRACE
	s.sendMailFn = smtp.SendMail
	return s
}

// Init smtp writer with json config.
// config like:
//
//	{
//		"Username":"example@gmail.com",
//		"password:"password",
//		"host":"smtp.gmail.com:465",
//		"subject":"email title",
//		"sendTos":["email1","email2"],
//		"level":LevelError
//	}
func (log *SMTPLogger) Init(jsonconfig string) error {
	err := json.Unmarshal([]byte(jsonconfig), log)
	if err != nil {
		return fmt.Errorf("Unable to parse JSON: %w", err)
	}
	log.NewWriterLogger(&smtpWriter{
		owner: log,
	})
	log.sendMailFn = smtp.SendMail
	return nil
}

// WriteMsg writes message in smtp writer.
// it will send an email with subject and only this message.
func (log *SMTPLogger) sendMail(p []byte) (int, error) {
	hp := strings.Split(log.Host, ":")

	// Set up authentication information.
	auth := smtp.PlainAuth(
		"",
		log.Username,
		log.Password,
		hp[0],
	)
	// Connect to the server, authenticate, set the sender and recipient,
	// and send the email all in one step.
	contentType := "Content-Type: text/plain" + "; charset=UTF-8"
	mailmsg := []byte("To: " + strings.Join(log.RecipientAddresses, ";") + "\r\nFrom: " + log.Username + "<" + log.Username +
		">\r\nSubject: " + log.Subject + "\r\n" + contentType + "\r\n\r\n")
	mailmsg = append(mailmsg, p...)
	return len(p), log.sendMailFn(
		log.Host,
		auth,
		log.Username,
		log.RecipientAddresses,
		mailmsg,
	)
}

// Content returns the content accumulated in the content provider
func (log *SMTPLogger) Content() (string, error) {
	return "", fmt.Errorf("not supported")
}

// Flush when log should be flushed
func (log *SMTPLogger) Flush() {
}

// ReleaseReopen does nothing
func (log *SMTPLogger) ReleaseReopen() error {
	return nil
}

// GetName returns the default name for this implementation
func (log *SMTPLogger) GetName() string {
	return "smtp"
}

func init() {
	Register("smtp", NewSMTPLogger)
}