📄 smtpio.c
字号:
#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;
extern unsigned int emlTimeout;
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;
int hdrsize = 0, len;
static Version smtpio_ver;
smtpio_ver.part.major = VER_MAJOR;
smtpio_ver.part.delim1 = '.';
smtpio_ver.part.minor = VER_MINOR;
smtpio_ver.part.delim2 = '.';
smtpio_ver.part.release = VER_REL;
smtpio_ver.part.null = '\0';
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, 80, "Cc: %s\n", msg->cc_addr);
hdrend += snprintf(hdrend, 64, "Subject: %s\n", msg->subject);
if (msg->xmailer != NULL) {
hdrend += snprintf(hdrend, 32, "X-Mailer: %s \n", msg->xmailer);
}
if (msg->mime_version != NULL) {
hdrend +=
snprintf(hdrend, 32, "Mime-Version: %s\n", msg->mime_version);
}
if (msg->content_type != NULL) {
hdrend +=
snprintf(hdrend, 64, "Content-Type: %s\n", msg->content_type);
}
if (msg->content_transfer_encoding != NULL) {
hdrend +=
snprintf(hdrend, 64, "Content-Transfer-Encoding: %s\n",
msg->content_transfer_encoding);
}
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, 255, "HELO %s\r\n", localhost);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_HELO_SEND;
return ERROR;
}
if (((len = recvline(sock, buffer, 255)) < 0)
|| ((ok = find_string(buffer, ReqMlActOK)) == -1)) {
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
}
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", 255);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_LOGIN;
return ERROR;
}
if ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, AuthLoginCon) == -1)) {
smtperrno = S_ERR_AUTH_LOGIN;
return ERROR;
}
n = strlen(username);
strcpy(buffer1, eml_mime_encode_base64(username, &n, 1));
len = strlen(buffer1);
*(buffer1 + len - 1) = 0;
len = strlen(buffer1);
snprintf(command, n + 3, "%s\r\n", buffer1);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_USER;
return ERROR;
}
if ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, AuthLoginCon) == -1)) {
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, n + 3, "%s\r\n", buffer1);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_AUTH_PASSWORD;
return ERROR;
}
if ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, AuthLoginOK) == -1)) {
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, 255, "MAIL FROM:%s\r\n", sender);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_MAIL_SEND;
return ERROR;
}
if (((reply = recvline(sock, buffer, 255)) < 0)
|| (iffind = (find_string(buffer, ReqMlActOK)) == -1)) {
// we should have gotten a message from the smtp server saying:
// 250 user@host.com... Sender ok
smtperrno = S_ERR_MAIL_RECV;
return ERROR;
}
return SUCCESS;
}
int eml_smtp_rcpt(int sock, char *recipient, char *orig_rcpt)
{
// we gotta tell the smtp server who we are going to be sending
// our email to
static char buffer[256];
static char command[102];
#undef I_KNOW_WHAT_ORCPT_IS_FOR
#ifdef I_KNOW_WHAT_ORCPT_IS_FOR
if (orig_rcpt == (gchar *) NULL || strcmp(recipient, orig_rcpt) == 0)
// No original recipient specified or same as recipient.
snprintf(command, 511, "RCPT TO: %s\r\n", recipient);
else
snprintf(command, 511, "RCPT TO: %s ORCPT=%s\r\n", recipient,
orig_rcpt);
#else
snprintf(command, 511, "RCPT TO: %s\r\n", recipient);
#endif
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_RCPT_SEND;
return ERROR;
}
if ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, ReqMlActOK) == -1)) {
// we should have gotten a message from the smtp server saying:
// 250 user@host.com... Recipient ok
smtperrno = S_ERR_RCPT_RECV;
return ERROR;
}
//printf("RCPT TO SUCCESS\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", 255);
if (send(sock, command, strlen(command), 0) < 0) {
smtperrno = S_ERR_DATA_SEND;
return ERROR;
}
if ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, StrtMailInpt) == -1)) {
// 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 ((recvline(sock, buffer, 255) < 0)
|| (find_string(buffer, ReqMlActOK) == -1)) {
// Should've gotten a respose saying our message is ready for delivery
smtperrno = S_ERR_BODY_RECV;
return ERROR;
}
return SUCCESS;
}
int eml_smtp_rset(int sock)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -