108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"log"
|
||
|
"net"
|
||
|
"time"
|
||
|
|
||
|
"github.com/emersion/go-smtp"
|
||
|
)
|
||
|
|
||
|
// The backend structure is called for authentication of a new session.
|
||
|
type SMTPBackend struct {
|
||
|
smtp.Backend
|
||
|
}
|
||
|
|
||
|
// During the process of receiving an email, this session is called.
|
||
|
type SMTPSession struct {
|
||
|
smtp.Session
|
||
|
remoteAddr net.Addr
|
||
|
from string
|
||
|
to string
|
||
|
}
|
||
|
|
||
|
// On login, we do not care about authentication. So we just start a new session and provide it ;)
|
||
|
func (b *SMTPBackend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
|
||
|
return &SMTPSession{
|
||
|
remoteAddr: state.RemoteAddr,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
// We want to receive all emails, including anonymous emails.
|
||
|
func (b *SMTPBackend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
|
||
|
return &SMTPSession{
|
||
|
remoteAddr: state.RemoteAddr,
|
||
|
}, nil //return nil, smtp.ErrAuthRequired
|
||
|
}
|
||
|
|
||
|
// The session has provided mail options and who the message is from.
|
||
|
func (s *SMTPSession) Mail(from string, opts smtp.MailOptions) error {
|
||
|
// Store the from in the session for when we receive the final message data.
|
||
|
s.from = from
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// The session has provided who the mail is to.
|
||
|
func (s *SMTPSession) Rcpt(to string) error {
|
||
|
// Store who the mail is to for final message data.
|
||
|
s.to = to
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// The session has provided the data for the message.
|
||
|
func (s *SMTPSession) Data(r io.Reader) error {
|
||
|
// Save the message to the database.
|
||
|
err := MailSaveMessage(s.remoteAddr.String(), s.from, s.to, r)
|
||
|
if err != nil {
|
||
|
log.Println("Unable to parse email:", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// When the SMTP session is requested to start over.
|
||
|
func (s *SMTPSession) Reset() {}
|
||
|
|
||
|
// When the session is done completely.
|
||
|
func (s *SMTPSession) Logout() error {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// This function starts the SMTP server.
|
||
|
func SMTPServe() {
|
||
|
// Get the configuration.
|
||
|
smtpBindAddr := app.config.SMTPBindAddr
|
||
|
smtpPort := app.config.SMTPPort
|
||
|
smtpDomain := app.config.SMTPDomain
|
||
|
if app.context.String("smtp-bind") != "" {
|
||
|
smtpBindAddr = app.context.String("smtp-bind")
|
||
|
}
|
||
|
if app.context.Uint("smtp-port") != 0 {
|
||
|
smtpPort = app.context.Uint("smtp-port")
|
||
|
}
|
||
|
if app.context.String("smtp-domain") != "" {
|
||
|
smtpDomain = app.context.String("smtp-domain")
|
||
|
}
|
||
|
|
||
|
// Create the SMTP server with our custom backend.
|
||
|
smtpBackend := &SMTPBackend{}
|
||
|
smtpServer := smtp.NewServer(smtpBackend)
|
||
|
app.smtpServer = smtpServer
|
||
|
|
||
|
// Configure the SMTP server.
|
||
|
smtpServer.Addr = fmt.Sprintf("%s:%d", smtpBindAddr, smtpPort)
|
||
|
smtpServer.Domain = smtpDomain
|
||
|
smtpServer.ReadTimeout = 10 * time.Second
|
||
|
smtpServer.WriteTimeout = 10 * time.Second
|
||
|
smtpServer.MaxMessageBytes = app.config.MaxMessageSize
|
||
|
smtpServer.MaxRecipients = 50
|
||
|
smtpServer.AllowInsecureAuth = true
|
||
|
|
||
|
// Start the server.
|
||
|
log.Println("Starting smtp server on port", smtpPort)
|
||
|
if err := smtpServer.ListenAndServe(); err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
}
|