Merge pull request #621 from tamcore/feature/email-with-access-control
Make email publishing work, when access-control is enabledpull/626/head
commit
33e75375fd
|
@ -2582,6 +2582,11 @@ format is:
|
|||
ntfy-$topic@ntfy.sh
|
||||
```
|
||||
|
||||
If [access control](config.md#access-control) is enabled, and the target topic does not support anonymous writes, e-mail publishing won't work without providing an authorized access token. That will change the format of the e-mail's recipient address to
|
||||
```
|
||||
ntfy-$topic+$token@ntfy.sh
|
||||
```
|
||||
|
||||
As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority,
|
||||
delay and other features are not supported (yet). Here's an example that will publish a message with the
|
||||
title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)):
|
||||
|
|
|
@ -65,6 +65,7 @@ type smtpSession struct {
|
|||
backend *smtpBackend
|
||||
conn *smtp.Conn
|
||||
topic string
|
||||
token string
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
|
@ -81,6 +82,7 @@ func (s *smtpSession) Mail(from string, opts *smtp.MailOptions) error {
|
|||
func (s *smtpSession) Rcpt(to string) error {
|
||||
logem(s.conn).Field("smtp_rcpt_to", to).Debug("RCPT TO: %s", to)
|
||||
return s.withFailCount(func() error {
|
||||
token := ""
|
||||
conf := s.backend.config
|
||||
addressList, err := mail.ParseAddressList(to)
|
||||
if err != nil {
|
||||
|
@ -92,18 +94,27 @@ func (s *smtpSession) Rcpt(to string) error {
|
|||
if !strings.HasSuffix(to, "@"+conf.SMTPServerDomain) {
|
||||
return errInvalidDomain
|
||||
}
|
||||
// remove @ntfy.sh from end of email
|
||||
to = strings.TrimSuffix(to, "@"+conf.SMTPServerDomain)
|
||||
if conf.SMTPServerAddrPrefix != "" {
|
||||
if !strings.HasPrefix(to, conf.SMTPServerAddrPrefix) {
|
||||
return errInvalidAddress
|
||||
}
|
||||
// remove ntfy- from beginning of email
|
||||
to = strings.TrimPrefix(to, conf.SMTPServerAddrPrefix)
|
||||
}
|
||||
// if email contains token, split topic and token
|
||||
if strings.Contains(to, "+") {
|
||||
parts := strings.Split(to, "+")
|
||||
to = parts[0]
|
||||
token = parts[1]
|
||||
}
|
||||
if !topicRegex.MatchString(to) {
|
||||
return errInvalidTopic
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.topic = to
|
||||
s.token = token
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
})
|
||||
|
@ -177,6 +188,9 @@ func (s *smtpSession) publishMessage(m *message) error {
|
|||
if m.Title != "" {
|
||||
req.Header.Set("Title", m.Title)
|
||||
}
|
||||
if s.token != "" {
|
||||
req.Header.Add("Authorization", "Bearer "+s.token)
|
||||
}
|
||||
rr := httptest.NewRecorder()
|
||||
s.backend.handler(rr, req)
|
||||
if rr.Code != http.StatusOK {
|
||||
|
|
|
@ -492,6 +492,27 @@ L0VOIj4KClRoaXMgaXMgYSB0ZXN0IG1lc3NhZ2UgZnJvbSBUcnVlTkFTIENPUkUuCg==
|
|||
writeAndReadUntilLine(t, email, c, scanner, "554 5.0.0 Error: transaction failed, blame it on the weather: multipart message nested too deep")
|
||||
}
|
||||
|
||||
func TestSmtpBackend_PlaintextWithToken(t *testing.T) {
|
||||
email := `EHLO example.com
|
||||
MAIL FROM: phil@example.com
|
||||
RCPT TO: ntfy-mytopic+tk_KLORUqSqvNRLpY11DfkHVbHu9NGG2@ntfy.sh
|
||||
DATA
|
||||
Subject: Very short mail
|
||||
|
||||
what's up
|
||||
.
|
||||
`
|
||||
s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/mytopic", r.URL.Path)
|
||||
require.Equal(t, "Very short mail", r.Header.Get("Title"))
|
||||
require.Equal(t, "Bearer tk_KLORUqSqvNRLpY11DfkHVbHu9NGG2", r.Header.Get("Authorization"))
|
||||
require.Equal(t, "what's up", readAll(t, r.Body))
|
||||
})
|
||||
defer s.Close()
|
||||
defer c.Close()
|
||||
writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued")
|
||||
}
|
||||
|
||||
type smtpHandlerFunc func(http.ResponseWriter, *http.Request)
|
||||
|
||||
func newTestSMTPServer(t *testing.T, handler smtpHandlerFunc) (s *smtp.Server, c net.Conn, conf *Config, scanner *bufio.Scanner) {
|
||||
|
|
Loading…
Reference in New Issue