Skip to content

Instantly share code, notes, and snippets.

@ljesparis
Last active December 9, 2017 23:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljesparis/70cf0d1d8e0d99c481a44648f348a3ea to your computer and use it in GitHub Desktop.
Save ljesparis/70cf0d1d8e0d99c481a44648f348a3ea to your computer and use it in GitHub Desktop.
basic smtp client
package main
import (
"bufio"
"fmt"
"log"
"net"
"strconv"
"strings"
)
var (
// connection metadata
PORT = 1025
HOST = "127.0.0.1"
// sender mail
SENDER = "putin@gmail.com"
RECIPIENTS = []string{
"trump@gmail.com",
"obama@gmail.com",
}
CRLF = "\r\n"
// commands
EHLO = "EHLO %s" + CRLF
HELO = "HELO %s" + CRLF
MAIL = "MAIL FROM:<%s>" + CRLF
RCPT = "RCPT TO:<%s>" + CRLF
DATA = "DATA" + CRLF
QUIT = "QUIT" + CRLF
)
func panicErr(err error) {
if err != nil {
log.Panicln(err)
}
}
func generateMailMessage() (msg string) {
msg = "Content-Type: text/plain; charset=\"us-ascii\"" + CRLF + "MIME-Version: 1.0"
msg += CRLF + "Content-Transfer-Encoding: 7bit" + CRLF
msg += "To: "
for i, rcpt := range RECIPIENTS {
// agregando los recipientes al mensaje
if i == len(RECIPIENTS)-1 {
msg += fmt.Sprintf("%s", rcpt)
} else {
msg += fmt.Sprintf("%s,", rcpt)
}
}
msg += CRLF + fmt.Sprintf("From: %s", SENDER) + CRLF
msg += "Subject: Simple test message"
msg += CRLF + CRLF + "Hello world." + CRLF + "." + CRLF
return
}
// recibe datos del servidor smtp
func recv(conn net.Conn) (int, string, error) {
msg, err := bufio.NewReader(conn).ReadString(byte('\n'))
if err != nil {
return -1, "", err
}
log.Println(msg)
d := strings.SplitN(msg, " ", 2)
code := d[0]
msg = d[1]
i, _ := strconv.ParseInt(code, 10, 0)
return int(i), msg, nil
}
// envia datos al servidor smtp
func send(msg string, conn net.Conn) error {
n, err := conn.Write([]byte(msg))
if n != len(msg) {
return fmt.Errorf("error al enviar los datos")
}
if err != nil {
return err
}
log.Println("message ", msg)
return nil
}
func main() {
var code int
var err error
// creando la conexion con el servidor smtp
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", HOST, PORT))
panicErr(err)
defer conn.Close()
// recibiendo el primer mensaje del servidor smtp
// siempre es el mensaje de bienvenida
code, _, err = recv(conn)
panicErr(err)
// ahora si, vamos a abrir los canales de comunicacion
err = send(fmt.Sprintf(EHLO, HOST), conn)
panicErr(err)
code, _, err = recv(conn)
if code == 502 {
// si no funciona el comando EHLO,
// se puede enviar otro comando que tiene
// la misma funcion, llamado HELO.
err = send(fmt.Sprintf(HELO, HOST), conn)
panicErr(err)
code, _, err = recv(conn)
}
if code == 250 {
// enviando correo transmisor
err = send(fmt.Sprintf(MAIL, SENDER), conn)
panicErr(err)
code, _, err = recv(conn)
panicErr(err)
if code == 250 {
// enviando recipientes o receptores del mail
for _, rcpt := range RECIPIENTS {
err = send(fmt.Sprintf(RCPT, rcpt), conn)
panicErr(err)
code, _, err = recv(conn)
panicErr(err)
if code == 550 {
log.Printf("recipiente '%s' desconocido", rcpt)
}
}
// avisandole al servidor que voy a empezar
// a enviarle el mensaje.
err = send(DATA, conn)
panicErr(err)
code, _, err = recv(conn)
panicErr(err)
if code == 354 {
// enviando el mensaje
err := send(generateMailMessage(), conn)
panicErr(err)
code, _, err = recv(conn)
panicErr(err)
if code == 250 {
log.Println("mensaje enviado =)")
// si el mensaje se envio bien,
// le voy a decir al servidor que voy
// a terminar la conexion
err = send(QUIT, conn)
panicErr(err)
code, _, err = recv(conn)
panicErr(err)
// si el servidor me responde con el codigo 221,
// es que se ha cerrado la conexion de forma exitosa,
// si no, ocurrio un error.
if code == 221 {
log.Println("todo salio bien")
} else {
log.Panicln("error al cerrar la conexion con el servidor smtp")
}
} else {
log.Panicln("a ocurrido un error al intentar enviar el mensaje")
}
} else {
log.Panicln("ha ocurrido un error desconocido")
}
} else {
log.Panicln("Email Sender incorrecto")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment