我写这个程序只是练习利用libuv库写程序,怎样连接服务器,怎样处理读写。
这只是一个demo,离真正的发送邮件程序还有一些距离。
附上源代码:
#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define FATAL(msg) \
do { \
fprintf(stderr, \
"Fatal error in %s on line %d: %s\n", \
__FILE__, \
__LINE__, \
msg); \
fflush(stderr); \
abort(); \
} while (0)
typedef struct smtp_s {
char *helo;
char *from;
char *rcpt_to;
char *data;
char *subject;
} smtp_t;
typedef enum {
START = 0,
HELO,
FROM,
RCPT_TO,
DATA,
SUBJECT,
MAX_STATE
} smtp_states;
static char *smtp_code[] = {
"220",
"250",
"250",
"250",
"354",
"250"
};
static char *smtp_name[] = {
"start",
"helo",
"from",
"rcpt_to",
"data",
"subject"
};
static char *smtp_msg[] = {
"helo vrm\r\n",
"mail from:<engine@vrm.com\r\n",
"rcpt to:<1348104823@qq.com>\r\n", // 改成你自己的QQ邮箱帐号
"data\r\n",
"this is a test\r\n.\r\n"
};
static smtp_t smtp;
static smtp_states state = START;
static uv_loop_t *loop;
static void connect_cb(uv_connect_t *req, int status);
static void read_server_cb(uv_stream_t *stream, ssize_t nread, uv_buf_t buf);
static void write_server_cb(uv_write_t *req, int status);
static uv_buf_t alloc_cb(uv_handle_t *handle, size_t suggested_size);
static void connect_cb(uv_connect_t *req, int status)
{
int r;
uv_read_start(req->handle, alloc_cb, read_server_cb);
}
static uv_buf_t alloc_cb(uv_handle_t *handle, size_t suggested_size)
{
return uv_buf_init(malloc(suggested_size), suggested_size);
}
static void write_server_cb(uv_write_t *req, int status)
{
uv_err_t err;
free(req);
state += 1;
if (status == 0) {
return;
}
err = uv_last_error(loop);
fprintf(stderr, "uv_write error: %s\n", uv_strerror(err));
if (err.code == UV_ECANCELED) {
return;
}
}
static void read_server_cb(uv_stream_t *stream, ssize_t nread, uv_buf_t buf)
{
uv_write_t *wr;
size_t len;
int flag = 0;
if (state == MAX_STATE) {
uv_close((uv_handle_t *) stream, NULL);
printf("smtp end\r\n");
return;
}
if (strncmp(smtp_code[state], buf.base, 3) != 0) {
uv_close((uv_handle_t *) stream, NULL);
fprintf(stderr, "stmp state %s error: %s\n",
smtp_name[state],
buf.base);
return;
}
free(buf.base);
wr = (uv_write_t *) malloc(sizeof(uv_write_t));
len = strlen(smtp_msg[state]);
buf = uv_buf_init(smtp_msg[state], len);
if (uv_write(wr, stream, &buf, 1, write_server_cb)) {
FATAL("uv_write failed");
}
}
int main()
{
uv_tcp_t tcp;
uv_connect_t req;
struct sockaddr_in client_addr, server_addr;
int r;
loop = uv_default_loop();
client_addr = uv_ip4_addr("0.0.0.0", 0);
server_addr = uv_ip4_addr("119.147.192.101", 25);
r = uv_tcp_init(loop, &tcp);
assert(!r);
uv_tcp_bind(&tcp, client_addr);
r = uv_tcp_connect(&req, &tcp, server_addr, connect_cb);
assert(!r);
uv_run(loop, UV_RUN_DEFAULT);
return 0;
}