#include "smtpio.h"
static char *smtp_errlist[] = { "",
": prepare mail and server fail",
": Hostname failed to resolve",
": Socket failed to open",
": No route to host?",
": Server failed to acknowledge",
": HELO send()",
": HELO recv()",
": AUTH LOGIN auth()",
": AUTH USER auth()",
": AUTH PASSWORD auth()",
": MAIL FROM send()",
": MAIL FROM recv()",
": RCPT TO send()",
": RCPT TO recv()",
": DATA send()",
": DATA recv()",
": BODY recv()",
": RSET send()",
": RSET recv()",
": QUIT send()",
": QUIT recv()",
": Sender invalid",
": Recipient invalid"
};
extern int errno;
SMTPError smtperrno;
extern Server smtpserver;
extern Email mymail;
char *smtpArror(void)
{
return smtp_errlist[smtperrno];
}
int format_date(char *date, size_t date_size)
{
time_t t;
time(&t);
if (strftime(date, date_size, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t))
== 0)
return ERROR;
else
return SUCCESS;
}
int format_header(Email * msg)
{
// format the header information
char date[64], *hdrend;
format_date(date, 64);
// Create the header.
memset(msg->header, '\0', 320);
hdrend = msg->header;
hdrend += snprintf(msg->header, 64, "Date: %s\n", date);
hdrend += snprintf(hdrend, 32, "From: %s\n", msg->from_addr);
hdrend += snprintf(hdrend, 80, "To: %s\n", msg->to_addr);
hdrend += snprintf(hdrend, 64, "Subject: %s\n", msg->subject);
return SUCCESS;
}
int eml_smtp_helo(int sock)
{
// say hello to the server
char buffer[256];
char command[40];
char localhost[MAXHOSTNAMELEN];
int len, ok = 0;
// get the localhost name
gethostname(localhost, MAXHOSTNAMELEN);
// hiya server! how are you today?
snprintf(command, 39, "EHLO %s\r\n", localhost);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_HELO_SEND;
return ERROR;
}
if ((len = recv(sock, buffer, 255, 0)) < 0)
{
smtperrno = S_ERR_HELO_RECV;
if (ok < 0 && len > 0) // if we got a response, even tho it didn't
{ // like it, lets ignore it and continue anyway
fprintf(stderr,
"Warning: smtp server did not like our HELO.\n");
return SUCCESS;
}
return ERROR; // it failed to respond at all, so fuck it
}
printf("HELO 'OK'\n");
return SUCCESS;
}
int eml_smtp_auth(int sock, char *username, char *password)
{
char buffer[256];
char buffer1[256];
char command[30];
int n = 0;
int len = 0;
strncpy(command, "AUTH LOGIN\r\n", 14);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_LOGIN;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_AUTH_LOGIN;
return ERROR;
}
printf("AUTH LOGIN 'OK'\n");
n = strlen(username);
strcpy(buffer1, eml_mime_encode_base64(username, &n, 1));
len = strlen(buffer1);
*(buffer1 + len - 1) = 0;
len = strlen(buffer1);
snprintf(command, 30, "%s\r\n", buffer1);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_USER;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_AUTH_USER;
return ERROR;
}
n = strlen(password);
strcpy(buffer1, eml_mime_encode_base64(password, &n, 1));
len = strlen(buffer1);
*(buffer1 + len - 1) = 0;
len = strlen(buffer1);
snprintf(command, 30, "%s\r\n", buffer1);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_PASSWORD;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_AUTH_PASSWORD;
return ERROR;
}
return SUCCESS;
}
int eml_smtp_mail(int sock, const char *sender)
{
int reply, iffind;
// we gotta tell the smtp server who we are. (our email addy)
char buffer[256];
char command[46];
snprintf(command, 40, "MAIL FROM:%s\r\n", sender);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_MAIL_SEND;
return ERROR;
}
if ((reply = recv(sock, buffer, 255, 0)) < 0)
{
// we should have gotten a message from the smtp server saying:
// 250 user@host.com... Sender ok
smtperrno = S_ERR_MAIL_RECV;
return ERROR;
}
printf("MAIL FROM 'OK'\n");
return SUCCESS;
}
int eml_smtp_rcpt(int sock, char *recipient)
{
char buffer[256];
char command[102];
snprintf(command, 90, "RCPT TO: %s\r\n", recipient);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_RCPT_SEND;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_RCPT_RECV;
return ERROR;
}
printf("RCPT TO 'OK'\n");
return SUCCESS;
}
int eml_smtp_data(int sock, char *header, char *body)
{
// now we can actually send what's important :p
char buffer[256];
char command[8];
char data[6];
int i;
strncpy(command, "DATA\r\n", 8);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_DATA_SEND;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
// we should have gotten instructions on how to use the DATA command:
// 354 Enter mail, end with "." on a line by itself
smtperrno = S_ERR_DATA_RECV;
return ERROR;
}
// now to send the actual data
// send the header information
// for (i = 0; i < strlen(header); i++)
for (i = 0; i < 320; i++) {
if (header[i] == '\n' && header[i + 1] == '\0')
break;
if (header[i] == '\n')
strncpy(data, "\r\n", 3);
else
snprintf(data, 3, "%c", header[i]);
send(sock, data, strlen(data), 0);
}
send(sock, "\r\n\r\n", 4, 0);
// send the body of the message
for (i = 0; i < strlen(body); i++) {
if (body[i] == '.' && body[i - 1] == '\n' && body[i + 1] == '\n') {
// if we have a lone period on a line...
strcpy(data, "..");
} else if (body[i] == '\n' && body[i - 1] != '\r') {
strcpy(data, "\r\n");
} else {
data[0] = body[i];
data[1] = '\0';
}
send(sock, data, strlen(data), 0);
}
// terminate the message body
send(sock, "\r\n.\r\n", 5, 0);
if (recv(sock, buffer, 255, 0) < 0)
{
// Should've gotten a respose saying our message is ready for delivery
smtperrno = S_ERR_BODY_RECV;
return ERROR;
}
printf("DATA 'OK'\n");
return SUCCESS;
}
int eml_smtp_rset(int sock)
{
// we are going to reset the smtp server (just to be nice)
char buffer[256];
char command[8];
strncpy(command, "RSET\r\n", 8);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_RSET_SEND;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_RSET_RECV;
return ERROR;
}
printf("RSET 'OK'\n");
return SUCCESS;
}
int eml_smtp_quit(const int sock)
{
// lets tell the server we want to quit now
char buffer[256];
char command[8];
strncpy(command, "QUIT\r\n", 8);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_QUIT_SEND;
return ERROR;
}
if (recv(sock, buffer, 255, 0) < 0)
{
smtperrno = S_ERR_QUIT_RECV;
return ERROR;
}
printf("QUIT 'OK'\n");
return SUCCESS;
}
int eml_smtp_close(int sock)
{
close(sock);
return SUCCESS;
}
int eml_smtp_open(Server * server)
{
char buffer[513];
int sock = -1;
smtperrno = S_NO_ERROR;
if (!Resolve(server)) {
smtperrno = S_ERR_RESOLVE;
return -1;
}
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
smtperrno = S_ERR_SOCKET;
return -1;
}
server->sin.sin_family = AF_INET;
server->sin.sin_port = htons(server->port);
//server->sin.sin_addr.s_addr = inet_ad