Last active
December 9, 2017 23:30
-
-
Save ljesparis/70cf0d1d8e0d99c481a44648f348a3ea to your computer and use it in GitHub Desktop.
basic smtp client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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