1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-17 14:37:02 +00:00

Implement DATA receiving

This patch implements the receiving of DATA from the client.
We still don't do anything with it, though.
This commit is contained in:
Alberto Bertogli
2015-10-25 23:59:59 +00:00
parent d92860c1de
commit 2c612002a9

View File

@@ -5,6 +5,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"math/rand" "math/rand"
"net" "net"
"net/http" "net/http"
@@ -27,7 +28,11 @@ func main() {
} }
const ( const (
// TODO: get this via config/dynamically. It's only used for show.
hostname = "charqui.com.ar" hostname = "charqui.com.ar"
// Maximum data size, in bytes.
maxDataSize = 52428800
) )
func ListenAndServe() { func ListenAndServe() {
@@ -61,7 +66,7 @@ type Conn struct {
// Message data. // Message data.
mail_from string mail_from string
rcpt_to []string rcpt_to []string
data string data []byte
} }
func (c *Conn) Handle() { func (c *Conn) Handle() {
@@ -104,11 +109,8 @@ loop:
case "RCPT": case "RCPT":
code, msg = c.RCPT(params) code, msg = c.RCPT(params)
case "DATA": case "DATA":
code, msg = c.DATA(params) // DATA handles the whole sequence.
if code == 354 { code, msg = c.DATA(params, tr)
// TODO: write response, read until dot, store in data, send
// reply.
}
case "QUIT": case "QUIT":
c.writeResponse(221, "Be seeing you...") c.writeResponse(221, "Be seeing you...")
break loop break loop
@@ -117,7 +119,7 @@ loop:
msg = "unknown command" msg = "unknown command"
} }
tr.LazyPrintf("<- %d", code) tr.LazyPrintf("<- %d %s", code, msg)
err = c.writeResponse(code, msg) err = c.writeResponse(code, msg)
if err != nil { if err != nil {
@@ -147,7 +149,7 @@ func (c *Conn) EHLO(params string) (code int, msg string) {
fmt.Fprintf(buf, hostname+" - Your hour of destiny has come.\n") fmt.Fprintf(buf, hostname+" - Your hour of destiny has come.\n")
fmt.Fprintf(buf, "8BITMIME\n") fmt.Fprintf(buf, "8BITMIME\n")
fmt.Fprintf(buf, "PIPELINING\n") fmt.Fprintf(buf, "PIPELINING\n")
fmt.Fprintf(buf, "SIZE 52428800\n") fmt.Fprintf(buf, "SIZE %d\n", maxDataSize)
fmt.Fprintf(buf, "STARTTLS\n") fmt.Fprintf(buf, "STARTTLS\n")
fmt.Fprintf(buf, "HELP\n") fmt.Fprintf(buf, "HELP\n")
return 250, buf.String() return 250, buf.String()
@@ -226,7 +228,7 @@ func (c *Conn) RCPT(params string) (code int, msg string) {
return 250, "You have an eerie feeling..." return 250, "You have an eerie feeling..."
} }
func (c *Conn) DATA(params string) (code int, msg string) { func (c *Conn) DATA(params string, tr trace.Trace) (code int, msg string) {
if c.mail_from == "" { if c.mail_from == "" {
return 503, "sender not yet given" return 503, "sender not yet given"
} }
@@ -235,13 +237,42 @@ func (c *Conn) DATA(params string) (code int, msg string) {
return 503, "need an address to send to" return 503, "need an address to send to"
} }
return 354, "You experience a strange sense of peace" // We're going ahead.
err := c.writeResponse(354, "You experience a strange sense of peace")
if err != nil {
return 554, fmt.Sprintf("error writing DATA response: %v", err)
}
tr.LazyPrintf("<- 354 You experience a strange sense of peace")
dotr := io.LimitReader(c.tc.DotReader(), maxDataSize)
c.data, err = ioutil.ReadAll(dotr)
if err != nil {
return 554, fmt.Sprintf("error reading DATA: %v", err)
}
tr.LazyPrintf("-> ... %d bytes of data", len(c.data))
// TODO: here is where we queue/send/process the message!
// It is very important that we reset the envelope before returning,
// so clients can send other emails right away without needing to RSET.
c.resetMessageData()
msgs := []string{
"You offer the Amulet of Yendor to Anhur...",
"An invisible choir sings, and you are bathed in radiance...",
"The voice of Anhur booms out: Congratulations, mortal!",
"In return to thy service, I grant thee the gift of Immortality!",
"You ascend to the status of Demigod(dess)...",
}
return 250, msgs[rand.Int()%len(msgs)]
} }
func (c *Conn) resetMessageData() { func (c *Conn) resetMessageData() {
c.mail_from = "" c.mail_from = ""
c.rcpt_to = nil c.rcpt_to = nil
c.data = "" c.data = nil
} }
func (c *Conn) readCommand() (cmd, params string, err error) { func (c *Conn) readCommand() (cmd, params string, err error) {