mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-18 14:47:03 +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:
53
chasquid.go
53
chasquid.go
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user