#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

// maximum length of an email address according to IETF
// https://tools.ietf.org/html/rfc3696

// 64 characters for the "local part" (before the "@"),
// a maximum of 255 characters for the domain part and 1 for the at sign
// totalling 320 characters
#define MAX_EMAIL_LENGTH    320

// the email server has a maximum of 255 characters
#define MAX_HOSTNAME_LENGTH 255

#define EMAIL_SERVICE_PORT  25
#define MAX_TEXT_LENGTH     4096

int sendEx(int socket, const char* data);

int main(int argc, char** argv)
{
    if (argc != 4)
    {
        fprintf(stderr, "-USAGE- %s <email server> <sender's email address> <receiver's email address> <text>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    char* email_server = malloc(sizeof(char) * MAX_HOSTNAME_LENGTH);
    char* email_sender = malloc(sizeof(char) * MAX_EMAIL_LENGTH);
    char* email_receiver = malloc(sizeof(char) * MAX_EMAIL_LENGTH);
    char* email_text = malloc(sizeof(char) * MAX_TEXT_LENGTH);

    char reply[1024 * 5];
    struct sockaddr_in server;
    struct hostent *hostinfo;
    int server_sock;

    if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket()");
        exit(EXIT_FAILURE);
    }

    hostinfo = gethostbyname(argv[1]);

    server.sin_family = AF_INET;
    server.sin_port = htons(EMAIL_SERVICE_PORT);
    memcpy((char*) &server.sin_addr, hostinfo->h_addr, hostinfo->h_length);

    if (connect(server_sock, (struct sockaddr*) &server, sizeof server) < 0)
    {
        perror("connect()");
        exit(EXIT_FAILURE);
    }

    sprintf(email_server, "HELO %s\r\n", argv[1]);
    sendEx(server_sock, email_server);
    recv(server_sock, reply, sizeof reply, 0);
    printf("%s\n", reply);

    sprintf(email_sender, "MAIL FROM: %s\r\n", argv[2]);
    sendEx(server_sock, email_sender);
    recv(server_sock, reply, sizeof reply, 0);
    printf("%s\n", reply);

    sprintf(email_receiver, "RCPT TO: %s\r\n", argv[3]);
    sendEx(server_sock, email_receiver);
    recv(server_sock, reply, sizeof reply, 0);
    printf("%s\n", reply);

    sprintf(email_text, "DATA\r\n %s.\r\n", argv[4]); 
    sendEx(server_sock, email_text);
    printf("%s\n", reply);

    free(email_text);
    free(email_receiver);
    free(email_sender);
    close(server_sock);

    return 0;
}

int sendEx(int socket, const char* data)
{
    int iRet;
    iRet = send(socket, data, strlen(data), 0);
    if (iRet == -1)
    {
        perror("send()");
        exit(EXIT_FAILURE);
    }
    return iRet;
}