WIP: mail publish
This commit is contained in:
		
							parent
							
								
									43a2acb756
								
							
						
					
					
						commit
						3001e57bcc
					
				
					 4 changed files with 130 additions and 0 deletions
				
			
		
							
								
								
									
										2
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -8,6 +8,7 @@ require (
 | 
			
		|||
	firebase.google.com/go v3.13.0+incompatible
 | 
			
		||||
	github.com/BurntSushi/toml v0.4.1 // indirect
 | 
			
		||||
	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
 | 
			
		||||
	github.com/emersion/go-smtp v0.15.0
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.14.9
 | 
			
		||||
	github.com/olebedev/when v0.0.0-20211212231525-59bd4edcf9d6
 | 
			
		||||
	github.com/stretchr/testify v1.7.0
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +27,7 @@ require (
 | 
			
		|||
	github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
 | 
			
		||||
	github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
 | 
			
		||||
	github.com/davecgh/go-spew v1.1.1 // indirect
 | 
			
		||||
	github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
 | 
			
		||||
	github.com/envoyproxy/go-control-plane v0.10.1 // indirect
 | 
			
		||||
	github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
 | 
			
		||||
	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -89,6 +89,10 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
 | 
			
		|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
 | 
			
		||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
 | 
			
		||||
github.com/emersion/go-smtp v0.15.0 h1:3+hMGMGrqP/lqd7qoxZc1hTU8LY8gHV9RFGWlqSDmP8=
 | 
			
		||||
github.com/emersion/go-smtp v0.15.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
 | 
			
		||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 | 
			
		||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 | 
			
		||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										102
									
								
								server/mailserver.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								server/mailserver.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,102 @@
 | 
			
		|||
package server
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/emersion/go-smtp"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"net/mail"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// mailBackend implements SMTP server methods.
 | 
			
		||||
type mailBackend struct {
 | 
			
		||||
	s *Server
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *mailBackend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
 | 
			
		||||
	return &Session{s: b.s}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *mailBackend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
 | 
			
		||||
	return &Session{s: b.s}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Session is returned after EHLO.
 | 
			
		||||
type Session struct {
 | 
			
		||||
	s        *Server
 | 
			
		||||
	from, to string
 | 
			
		||||
	mu       sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) AuthPlain(username, password string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) Mail(from string, opts smtp.MailOptions) error {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	s.from = from
 | 
			
		||||
	log.Println("Mail from:", from)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) Rcpt(to string) error {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	s.to = to
 | 
			
		||||
	log.Println("Rcpt to:", to)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) Data(r io.Reader) error {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	b, err := ioutil.ReadAll(r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Data:", string(b))
 | 
			
		||||
	msg, err := mail.ReadMessage(bytes.NewReader(b))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	body, err := io.ReadAll(msg.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	topic := strings.TrimSuffix(s.to, "@ntfy.sh")
 | 
			
		||||
	url := fmt.Sprintf("%s/%s", s.s.config.BaseURL, topic)
 | 
			
		||||
	req, err := http.NewRequest("PUT", url, bytes.NewReader(body))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	subject := msg.Header.Get("Subject")
 | 
			
		||||
	if subject != "" {
 | 
			
		||||
		req.Header.Set("Title", subject)
 | 
			
		||||
	}
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	s.s.handle(rr, req)
 | 
			
		||||
	if rr.Code != http.StatusOK {
 | 
			
		||||
		return errors.New("error: " + rr.Body.String())
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) Reset() {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	s.from = ""
 | 
			
		||||
	s.to = ""
 | 
			
		||||
	s.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Session) Logout() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import (
 | 
			
		|||
	firebase "firebase.google.com/go"
 | 
			
		||||
	"firebase.google.com/go/messaging"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/emersion/go-smtp"
 | 
			
		||||
	"google.golang.org/api/option"
 | 
			
		||||
	"heckel.io/ntfy/util"
 | 
			
		||||
	"html/template"
 | 
			
		||||
| 
						 | 
				
			
			@ -238,10 +239,16 @@ func (s *Server) Run() error {
 | 
			
		|||
			errChan <- s.httpsServer.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile)
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
	if true {
 | 
			
		||||
		go func() {
 | 
			
		||||
			errChan <- s.mailserver()
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
	s.mu.Unlock()
 | 
			
		||||
	go s.runManager()
 | 
			
		||||
	go s.runAtSender()
 | 
			
		||||
	go s.runFirebaseKeepliver()
 | 
			
		||||
 | 
			
		||||
	return <-errChan
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -722,6 +729,21 @@ func (s *Server) updateStatsAndPrune() {
 | 
			
		|||
		s.messages, len(s.topics), subscribers, messages, len(s.visitors))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) mailserver() error {
 | 
			
		||||
	ms := smtp.NewServer(&mailBackend{s})
 | 
			
		||||
 | 
			
		||||
	ms.Addr = ":1025"
 | 
			
		||||
	ms.Domain = "localhost"
 | 
			
		||||
	ms.ReadTimeout = 10 * time.Second
 | 
			
		||||
	ms.WriteTimeout = 10 * time.Second
 | 
			
		||||
	ms.MaxMessageBytes = 1024 * 1024
 | 
			
		||||
	ms.MaxRecipients = 50
 | 
			
		||||
	ms.AllowInsecureAuth = true
 | 
			
		||||
 | 
			
		||||
	log.Println("Starting server at", ms.Addr)
 | 
			
		||||
	return ms.ListenAndServe()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Server) runManager() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue