Skip to content

Instantly share code, notes, and snippets.

@anoldguy
Last active December 21, 2015 20:17
Show Gist options
  • Save anoldguy/f5304db2f7d950aa0023 to your computer and use it in GitHub Desktop.
Save anoldguy/f5304db2f7d950aa0023 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"errors"
"fmt"
"log"
"net"
"strings"
)
type Job struct {
Command string
Key string
}
const KeyNotFound string = "500"
const KeyError string = "400"
const KeyFound string = "200"
func getDomain(email string) (string, error) {
domain := ""
var err error
if !strings.Contains(email, "@") {
err = errors.New(fmt.Sprintf("Malformed email address: %s", email))
return domain, err
}
results := strings.Split(email, "@")
domain = results[1]
return domain, err
}
func lookupKey(key string) (bool, error) {
found := false
mxs, err := net.LookupMX(key)
// Hat tip @noahhl
found = err == nil && (strings.Contains(mxs[0].Host, "google") || strings.Contains(mxs[0].Host, "gmail"))
return found, err
}
func formatError(s string) string {
return fmt.Sprintf("%s %s\n", KeyError, s)
}
func processJob(job Job) (string, error) {
exists := false
result := ""
var err error
switch job.Command {
case "get":
exists, err = lookupKey(job.Key)
if err != nil {
result = formatError(err.Error())
return result, err
}
if exists {
result = fmt.Sprintf("%s %s\n", KeyFound, "gmail:")
} else {
result = fmt.Sprintf("%s %s\n", KeyNotFound, "Domain not hosted by google")
}
default:
err = errors.New(fmt.Sprintf("Command Unimplemented: %s", job.Command))
}
return result, err
}
func parseCommand(line string) (Job, error) {
// Based on http://www.postfix.org/transport.5.html, we will get the
// entire recipient email for this lookup, so we can split on @ to get
// the domain as per https://tools.ietf.org/html/rfc5321#section-4.1.2
job := Job{}
var err error
fields := strings.Fields(strings.Replace(strings.TrimRight(line, "\n"), "%20", " ", -1))
if len(fields) > 1 {
job.Command = fields[0]
domain, err := getDomain(fields[1])
if err != nil {
return job, err
}
job.Key = domain
} else {
err = errors.New("Command Parsing failed; missing command or key")
}
return job, err
}
func requestHandler(conn net.Conn) {
for {
// Read the line off the wire
line, err := bufio.NewReader(conn).ReadBytes('\n')
if err != nil {
return
}
// Parse the line into a job
job, err := parseCommand(string(line))
if err != nil {
// If it's not a valid job, bail
log.Println(err)
conn.Write([]byte(formatError(err.Error())))
} else {
// if it is a valid job, let's process it
log.Printf("Command: %s, Key: %s", job.Command, job.Key)
result, procErr := processJob(job)
if procErr != nil {
log.Printf("Error processing job %s: %s", job.Command, procErr)
}
conn.Write([]byte(result))
}
}
}
func main() {
psock, err := net.Listen("tcp", ":5000")
if err != nil {
return
}
for {
conn, err := psock.Accept()
if err != nil {
return
}
go requestHandler(conn)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment