You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
2.9 KiB

package smtpd
import (
"encoding/base64"
"fmt"
"log"
"strings"
"time"
"git.watsonserve.com/maild/base"
)
// helo命令
func helo(ctx *smtp_context_t) {
ctx.Module = mod_COMMAND
addr := ctx.Address
name := ctx.Msg[5:]
ctx.Send(fmt.Sprintf("250 %s Hello %s (%s[%s])\r\n", ctx.conf.Domain, name, addr, addr))
}
// ehlo命令
func ehlo(ctx *smtp_context_t) {
ctx.Module = mod_COMMAND
addr := ctx.Address
name := ctx.Msg[5:]
msg := fmt.Sprintf(
"250-%s Hello %s (%s[%s])\r\n%s\r\n%s\r\n%s\r\n%s\r\n",
ctx.conf.Domain, name, addr, addr,
"250-AUTH LOGIN PLAIN",
"250-AUTH=LOGIN PLAIN",
"250-PIPELINING",
"250 ENHANCEDSTATUSCODES",
)
ctx.Send(msg)
}
// 授权
func auth(ctx *smtp_context_t) {
content, err := base64.StdEncoding.DecodeString(ctx.Msg[11:])
if nil != err {
log.Printf("error: %s\n", err.Error())
return
}
for i := 0; i < len(content); i++ {
if 0 == content[i] {
content[i] = '\n'
}
}
Auth := ctx.handlers.Auth
userPassword := strings.Split(string(content), "\n")
userId := Auth(userPassword[0], userPassword[1])
buf := "535 Authentication Failed\r\n"
if "" != userId {
ctx.User = userPassword[0]
buf = "235 Authentication Successful\r\n"
ctx.Login = true
log.Println("auth by self")
}
ctx.Send(buf)
}
func quit(ctx *smtp_context_t) {
ctx.End("221 2.0.0 " + ctx.conf.Domain + " Service closing transmission channel\r\n")
}
func xclient(ctx *smtp_context_t) {
log.Println("auth by agency")
ctx.Login = true
ctx.hola()
}
func starttls(ctx *smtp_context_t) {
ctx.Send("502 5.3.3 STARTTLS is not supported\r\n")
log.Println("startTTS")
}
func help(ctx *smtp_context_t) {
ctx.Send("502 5.3.3 HELP is not supported\r\n")
}
func noop(ctx *smtp_context_t) {
ctx.Send("250 2.0.0 OK\r\n")
log.Println("noop")
}
func rset(ctx *smtp_context_t) {
ctx.Send("250 2.0.0 OK\r\n")
log.Println("rset")
}
func mail(ctx *smtp_context_t) {
ctx.Email.Sender = ctx.re.FindStringSubmatch(ctx.Msg)[1]
clientDomain := strings.Split(ctx.Email.Sender, "@")[1]
if (clientDomain == ctx.conf.Domain) != (!ctx.Login) { // 本域已登录 or 外域未登录
ctx.Send("250 2.1.0 Sender <" + ctx.Email.Sender + "> OK\r\n")
return
}
ctx.Send("530 5.7.1 Authentication Required\r\n")
}
func rcpt(ctx *smtp_context_t) {
recver := ctx.re.FindStringSubmatch(ctx.Msg)[1]
if strings.Split(recver, "@")[1] != ctx.conf.Domain && !ctx.Login { // 非登录用户 to 外域
ctx.Send("530 5.7.1 Authentication Required\r\n")
return
}
ctx.Email.Recver.PushBack(recver)
ctx.Send("250 2.1.5 Recipient <" + recver + "> OK\r\n")
}
func data(ctx *smtp_context_t) {
format := "from %s ([%s]) by %s over TLS secured channel with %s(%s)\r\n\t%d"
ctx.Module = mod_HEAD
config := ctx.conf
ele := &base.KV{
Name: "Received",
Value: fmt.Sprintf(format, config.Domain, config.Ip, config.Domain, config.Name, config.Version, time.Now().Unix()),
}
ctx.Email.Head = append(ctx.Email.Head, *ele)
ctx.Send("354 Ok Send data ending with <CRLF>.<CRLF>\r\n")
}