Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <resolv.h>
#include <string.h>
#include <qstringlist.h>
#include <fcntl.h>
#include "mail.h"
NMail::NMail()
{
smtp_port = 25;
pop_port = 110;
pop_sd = -1;
smtp_sd = -1;
msg_size = 10;
msgs = (void **)malloc(sizeof(NMessage *)*msg_size);
msg_count = 0;
buffer_size = 1024;
buffer = (char *)malloc(buffer_size);
}
void NMail::setParams(QString psmtp_server, QString ppop_server,
QString pusername, QString ppassword)
{
username = pusername;
password = ppassword;
smtp_server = psmtp_server;
pop_server = ppop_server;
}
void NMail::insertMessage(NMessage *nmsg)
{
if (msg_count >= msg_size){
msg_size += 20;
msgs = (void **)realloc(msgs,
sizeof(void *)*msg_size);
}
msgs[msg_count] = nmsg;
msg_count++;
}
void NMail::removeMessage(size_t ps_index, int folder)
{
size_t index;
size_t count = 0;
for (index = 0; index < msg_count; index++){
if (((NMessage *)msgs[index])->folder == folder)
count++;
if (count == ps_index + 1)
break;
}
if (index == msg_count)
return;
NMessage *nmsg = ((NMessage *)msgs[index]);
for (size_t i=index; i < msg_count-1; i++){
msgs[i] = msgs[i+1];
}
msg_count--;
delete nmsg;
}
size_t NMail::getCount(int folder)
{
size_t count = 0;
for (size_t index = 0; index < msg_count; index++)
if (((NMessage *)msgs[index])->folder == folder)
count++;
return count;
}
NMessage *NMail::getMessage(size_t ps_index, int folder)
{
size_t index;
size_t count = 0;
for (index = 0; index < msg_count; index++){
if (((NMessage *)msgs[index])->folder == folder){
count++;
}
if (count == ps_index + 1)
break;
}
if (index == msg_count)
return NULL;
else
return (NMessage *)msgs[index];
}
int NMail::find_msg(QString msg_id)
{
for (size_t i=0; i < msg_count; i++){
if (msg_id == ((NMessage *)msgs[i])->msg_id){
return i;
}
}
return -1;
}
int NMail::should_wait(const char *cmd, const char *params, char *reply, size_t count)
{
if (!cmd)
return false;
int have_dot = false, have_eol = false;
for (size_t i = 0; i < count; i++)
if ( reply[i] == '.' ){
if ( (count != i+1) && (reply[i+1] == '\n' || reply[i+1] == '\r') ){
if ( i == 0 || reply[i-1] == '\n' ){
have_dot = true;
}
}
}
else if (reply[i] == '\n'){
have_eol = true;
}
if ( ( (strcmp(cmd, CMD_LIST) == 0) && (params == NULL) ) ||
(strcmp(cmd, CMD_RETR) == 0) ){
if ( have_eol && have_dot )
return false;
else
return true;
}
/* wait for end_of_line? */
if ( have_eol )
return false;
else
return true;
}
int NMail::exec_pop_cmd(const char *cmd, const char *params, char **reply)
{
int count;
int res = -1;
int n_read;
if (cmd){
if (params)
sprintf(buffer, "%s %s\r\n", cmd, params);
else
sprintf(buffer, "%s\r\n", cmd);
send(pop_sd, buffer, strlen(buffer), 0);
}
count = 0;
printf("recv:\n");
while ( 1 ){
usleep(1000);
n_read = recv(pop_sd, buffer+count, buffer_size-count, 0);
if (n_read <= 0)
continue;
count += n_read;
buffer[count] = '\0';
printf("%s", buffer);
fsync(STDOUT_FILENO);
if ( should_wait(cmd, params, buffer, count)){
continue;
}
break;
}
printf(":::end\n");
if ( strncasecmp(buffer, "+OK", 3) == 0 ){
res = 0;
}
if (reply){
char *str = (char *)malloc(count+1);
memmove(str, buffer, count+1);
*reply = str;
}
return res;
}
int NMail::connectPServer()
{
printf( "Connecting to server:%s\n", pop_server.ascii());
if (pop_sd >= 0){
close(pop_sd);
pop_sd = -1;
}
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_port = htons(pop_port);
struct hostent *hent = gethostbyname(pop_server.ascii());
if (hent == NULL){
return -1;
}
memmove(&r_addr.sin_addr, *hent->h_addr_list, sizeof(r_addr.sin_addr));
if ( (pop_sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
return -1;
if (connect(pop_sd,(struct sockaddr *)&r_addr,
sizeof(r_addr)) == -1){
/* error! */
return -1;
}
fcntl(pop_sd, F_SETFL, O_NONBLOCK);
printf( "Connecting:\n");
if (exec_pop_cmd(NULL, NULL, NULL) < 0){
return -1;
}
return 0;
}
int NMail::authPServer()
{
if (connectPServer() < 0)
return -1;
printf( "Check user:\n");
if (exec_pop_cmd(CMD_USER, username.ascii(), NULL) < 0){
return -1;
}
printf( "Check password:\n");
if (exec_pop_cmd(CMD_PASS, password.ascii(), NULL) < 0){
return -1;
}
return 0;
}
int NMail::closePServer()
{
printf( "Quiting:\n");
if (exec_pop_cmd(CMD_QUIT, NULL, NULL) < 0){
return -1;
}
return 0;
}
int NMail::recvMessages()
{
char params[128];
printf( "Message status:\n");
char *str;
if (exec_pop_cmd(CMD_STAT, NULL, &str) < 0){
return -1;
}
size_t count = 0, size = 0, msg_num = 0;
sscanf(str, "+OK %d %d", &count, &size);
free(str);
size_t i;
QString plain_data;
QStringList data;
QStringList::Iterator it;
for (i = 1; i <= count; i++){
printf( "list:\n");
sprintf(params, "%u", i);
if (exec_pop_cmd(CMD_LIST, params, &str) < 0){
return -1;
}
sscanf(str, "+OK %d %d", &msg_num, &size);
printf("num=%d size=%d\n", msg_num, size);
free(str);
if (size + 1024 > buffer_size){
buffer_size = size + 1024;
buffer = (char *)realloc(buffer, buffer_size);
}
printf( "retr:\n");
sprintf(params, "%u", msg_num);
if (exec_pop_cmd(CMD_RETR, params, &str) < 0){
return -1;
}
plain_data = str;
free(str);
NMessage *nmsg = new NMessage();
nmsg->time = time(NULL);
data = QStringList::split( "\r\n", plain_data, true );
nmsg->header = "";
nmsg->content = "";
for (it = data.begin() ; it != data.end(); it++ ) {
if ((*it).isEmpty()){
it++;
break;
}
if ((*it).find("From", 0, 0) == 0){
nmsg->from = (*it).right((*it).length()-(*it).find(":",0,0)-2);
}
else if ((*it).find("To", 0, 0) == 0){
nmsg->to = (*it).right((*it).length()-(*it).find(":",0,0)-2);
}
else if ((*it).find("Subject", 0, 0) == 0){
nmsg->subject = (*it).right((*it).length()-(*it).find(":",0,0)-2);
}
else if ((*it).find("Date", 0, 0) == 0){
nmsg->date = (*it).right((*it).length()-(*it).find(":",0,0)-2);
}
else if ((*it).find("Message-Id", 0, 0) == 0){
nmsg->msg_id = (*it).right((*it).length()-(*it).find(":",0,0)-2);
}
nmsg->header = (*it) + "\n";
}
for ( ; it != data.end(); ++it ){
if ((*it) == ".")
break;
nmsg->content += (*it) + "\n";
}
nmsg->folder = FLDR_INBOX;
if (find_msg(nmsg->msg_id) >= 0)
delete nmsg;
else
insertMessage(nmsg);
}
return 0;
}
int NMail::exec_smtp_cmd(const char *cmd)
{
int count;
int res = -1;
int n_read;
if (cmd)
send(smtp_sd, cmd, strlen(cmd), 0);
count = 0;
printf("recv:\n");
while ( 1 ){
usleep(1000);
n_read = recv(smtp_sd, buffer+count, buffer_size-count, 0);
if (n_read <= 0)
continue;
count += n_read;
buffer[count] = '\0';
printf("%s", buffer);
fsync(STDOUT_FILENO);
break;
}
printf(":::end\n");
sscanf(buffer, "%d", &res);
if ( res < 400 ) return 0;
else return -1;
}
int NMail::connectSServer()
{
printf( "Connecting to server:%s\n", smtp_server.ascii());
if (smtp_sd >= 0){
close(smtp_sd);
smtp_sd = -1;
}
struct sockaddr_in r_addr;
r_addr.sin_family = AF_INET;
r_addr.sin_port = htons(smtp_port);
struct hostent *hent = gethostbyname(smtp_server.ascii());
if (hent == NULL){
return -1;
}
memmove(&r_addr.sin_addr, *hent->h_addr_list, sizeof(r_addr.sin_addr));
if ( (smtp_sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
return -1;
if (connect(smtp_sd,(struct sockaddr *)&r_addr,
sizeof(r_addr)) == -1){
/* error! */
return -1;
}
fcntl(smtp_sd, F_SETFL, O_NONBLOCK);
printf( "Connecting:\n");
if (exec_smtp_cmd(NULL) < 0){
return -1;
}
return 0;
}
int NMail::sendMessages()
{
sprintf(buffer, "HELO %s\r\n", smtp_server.ascii());
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
NMessage *nmsg;
while (getCount(FLDR_OUTBOX) > 0){
nmsg = getMessage(0, FLDR_OUTBOX);
sprintf(buffer, "MAIL FROM: %s\r\n", nmsg->from.ascii());
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
sprintf(buffer, "RCPT TO: %s\r\n", nmsg->to.ascii());
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
sprintf(buffer, "DATA\r\n");
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
size_t full_size = nmsg->content.length() + nmsg->subject.length() +
nmsg->from.length() + nmsg->to.length() + 100;
if ( full_size > buffer_size){
buffer_size = full_size;
buffer = (char *)realloc(buffer, buffer_size);
}
sprintf(buffer, "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s\r\n.\r\n",
nmsg->from.ascii(), nmsg->to.ascii(), nmsg->subject.ascii(),
nmsg->content.ascii());
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
nmsg->folder = FLDR_SENT;
}
return 0;
}
int NMail::closeSServer()
{
sprintf(buffer, "QUIT\r\n");
//printf("%s\n", buffer);
if (exec_smtp_cmd(buffer) < 0)
return -1;
return 0;
}
void NMail::checkMail()
{
if (authPServer() < 0)
return;
if (recvMessages() < 0)
return;
if (closePServer() < 0)
return;
}
void NMail::sendMail()
{
if (connectSServer() < 0)
return;
if (sendMessages() < 0)
return;
if (closeSServer() < 0)
return;
}
Соседние файлы в папке net_mail