You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
2.8 KiB
Go
131 lines
2.8 KiB
Go
package smtpserver
|
|
|
|
import (
|
|
"b612.me/starlog"
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/spf13/cobra"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/mail"
|
|
"os"
|
|
|
|
"github.com/emersion/go-smtp"
|
|
)
|
|
|
|
var addr string
|
|
var user, pass string
|
|
var allowAnyuser bool
|
|
var output string
|
|
var domain string
|
|
|
|
var Cmd = &cobra.Command{
|
|
Use: "smtp",
|
|
Short: "smtp server",
|
|
Long: "smtp server",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
run()
|
|
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
Cmd.Flags().StringVarP(&addr, "addr", "a", "0.0.0.0:25", "smtp server listen address")
|
|
Cmd.Flags().StringVarP(&user, "user", "u", "admin", "smtp server username")
|
|
Cmd.Flags().StringVarP(&pass, "pass", "p", "admin", "smtp server password")
|
|
Cmd.Flags().BoolVarP(&allowAnyuser, "allow-anyuser", "A", false, "allow any user")
|
|
Cmd.Flags().StringVarP(&output, "output", "o", "", "output mail to html")
|
|
Cmd.Flags().StringVarP(&domain, "domain", "d", "localhost", "smtp server domain")
|
|
}
|
|
|
|
type backend struct{}
|
|
|
|
func (bkd *backend) NewSession(c *smtp.Conn) (smtp.Session, error) {
|
|
return &session{}, nil
|
|
}
|
|
|
|
type session struct {
|
|
username string
|
|
password string
|
|
to string
|
|
}
|
|
|
|
func (s *session) AuthPlain(username, password string) error {
|
|
s.username = username
|
|
s.password = password
|
|
starlog.Printf("username:%s,password:%s\n", username, password)
|
|
if allowAnyuser {
|
|
return nil
|
|
} else {
|
|
if username != user || password != pass {
|
|
return smtp.ErrAuthFailed
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *session) Mail(from string, opts *smtp.MailOptions) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *session) Rcpt(to string, opts *smtp.RcptOptions) error {
|
|
s.to += to + ";"
|
|
return nil
|
|
}
|
|
|
|
func (s *session) Data(r io.Reader) error {
|
|
mailData, err := ioutil.ReadAll(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
msg, err := mail.ReadMessage(bytes.NewReader(mailData))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
header := msg.Header
|
|
subject := header.Get("Subject")
|
|
cc := header.Get("Cc")
|
|
bcc := header.Get("Bcc")
|
|
from := header.Get("From") // 获取发件人
|
|
starlog.Println("From:", from)
|
|
starlog.Println("Subject:", subject)
|
|
starlog.Println("Cc:", cc)
|
|
starlog.Println("Bcc:", bcc)
|
|
|
|
// Read the body
|
|
body, err := ioutil.ReadAll(msg.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
starlog.Println("Body:", string(body))
|
|
if output != "" {
|
|
path := output + "/" + subject + ".html"
|
|
html := fmt.Sprintf(`<html><head><title>%s</title></head><body><h2>subject: %s</p><p>mali from: %s</p<p>mail to:%s</p>
|
|
<p>cc:%s</p><p>bcc:%s</p><br /><p>%s</p></body></html>`, subject, subject, from, s.to, cc, bcc, string(body))
|
|
os.WriteFile(path, []byte(html), 0644)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *session) Reset() {}
|
|
|
|
func (s *session) Logout() error {
|
|
return nil
|
|
}
|
|
|
|
func run() {
|
|
flag.Parse()
|
|
|
|
s := smtp.NewServer(&backend{})
|
|
|
|
s.Addr = addr
|
|
s.Domain = domain
|
|
s.AllowInsecureAuth = true
|
|
s.Debug = os.Stdout
|
|
|
|
starlog.Infoln("Starting SMTP server at", addr)
|
|
starlog.Errorln(s.ListenAndServe())
|
|
}
|