// getpop.cpp
//
// Gets e-mail from the server and stores it in a mbox file.
//

#include <string>
#include <iostream>
#include <sstream>
#include <winsock>

#include <stdio.h>

using namespace std;

//=== Error procedure ===//
void Error (int ErrorNumber) {
        switch (ErrorNumber) {
                case -1:
                        cerr << "Unexpected error sending data." << endl; break;
                case -2:
                        cerr << "Unexpected error getting data." << endl; break;
                case 1:
                        cerr << "Couldn't strat winsock." << endl; break;
                case 2:
                        cerr << "Winsock version not supported." << endl; break;
                case 3:
                        cerr << "Couldn't resolve hostname." << endl; break;
                case 4:
                        cerr << "Couldn't create socket." << endl; break;
                case 5:
                        cerr << "Couldn't connect socket." << endl; break;
                case 6:
                        cerr << "Error connecting to server." << endl; break;
                case 7:
                        cerr << "Error sending username." << endl; break;
                case 8:
                        cerr << "Error sending password." << endl; break;
                case 9:
                        cerr << "Error getting number of mails." << endl; break;
                case 10:
                        cerr << "Error asking for message." << endl; break;
                case 11:
                        cerr << "Error deleting message." << endl; break;
                case 12:
                        cerr << "Error quitting from server." << endl; break;
        }
        cerr << "Error: " << WSAGetLastError() << endl;
        exit(1);
};

//=== Get connected socket ===//
SOCKET Connect (string PopServer) {

        SOCKET      Socket;
        IN_ADDR     iaHost;
        LPHOSTENT   lpHostEntry;
        LPSERVENT   lpServEnt;
        SOCKADDR_IN saServer;
        WSADATA wsaData;
        WORD wVersionRequested = MAKEWORD(1,1);

        // Start winsock
        int nRet = WSAStartup(wVersionRequested, &wsaData);
        if (nRet)
                Error(1);

        // Check version
        if (wsaData.wVersion != wVersionRequested)
                Error(2);

        // resolve hostname
        iaHost.s_addr = inet_addr(PopServer.c_str());
        if (iaHost.s_addr == INADDR_NONE)
                lpHostEntry = gethostbyname(PopServer.c_str());
        else
                lpHostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);
        if (lpHostEntry == NULL)
                Error(3);

        // Create socket
        Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (Socket == INVALID_SOCKET)
                Error(4);

        // set port
        lpServEnt = getservbyname("pop3", "tcp");
        if (lpServEnt == NULL)
                saServer.sin_port = htons(110);
        else
                saServer.sin_port = lpServEnt->s_port;

        // fill the rest of the server address structure
        saServer.sin_family = AF_INET;
        saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);

        // connect socket
        nRet = connect(Socket, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN));
        if (nRet == SOCKET_ERROR) {
                closesocket(Socket);
                Error(5);
        }

        return Socket;

};

//=== Send data ===//
bool SendData (SOCKET Socket, string data) {

        data += "\15\12"; // 13+10
        int nRet = send(Socket, data.c_str(), data.length(), 0);
        if (nRet == SOCKET_ERROR)
                return false;
        else
                return true;

};

//=== Recieve data ===//
bool RecieveData (SOCKET Socket, string *data) {

        int nRet;
        string Buffer = "";
        char szBuffer[1024];
        for (int i=0;i<1024;i++)
                szBuffer[i] = '\0';

        for (;;) {
                nRet = recv(Socket, szBuffer, sizeof(szBuffer), 0);
                if (nRet == SOCKET_ERROR)
                        return false;
                Buffer += szBuffer;
                /* if (Buffer.find("\n") != string::npos)
                        break; */
                /* if (Buffer != "") 
                        break; */
                if (nRet != 0)
                        break;
        }
        *data = Buffer;

        return true;

};

//=== Get number of messages ===//
int NumberMessages (SOCKET Socket, string UserName, string Passwd) {

        string data;

        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (6);
        if (!SendData (Socket, "USER " + UserName)) Error(-2);
        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (7);
        if (!SendData (Socket, "PASS " + Passwd)) Error(-2);
        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (8);
        if (!SendData (Socket, "STAT")) Error(-2);
        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (9);

        data.erase(0, data.find(" ")+1);
        data.erase(data.find(" ")+1, data.length() - data.find(" "));

        return atoi(data.c_str());
};

//=== Save message ===//
void SaveMessage (string Filename, string Buffer, long size) {

        unsigned int i = 0;
        string Buffer2;
        string Buffer3 = "";
        double c = 0;

        // Adds mbox header
        Buffer2 = "From ???@??? Thu Feb 13 14:52:52 2003\n";
        // Jumps +OK response from server
        while (!(Buffer.at(i)==13 && Buffer.at(i+1)==10)) i++;
        i+=2;
        cout << "Processing 0k of " << size << "k..." << endl;
        // Rebuilds broken ENTERs from C++ (FIXME)

        for ( ; i<Buffer.length(); i++) {
                c++;
                if (c/131072 == (long)c/131072)
                        cout << "Processing " << c/1024 << "k of " << size << "k..." << endl;
                if (!(Buffer.at(i)==13 && Buffer.at(i+1)==10)) {
                        if (Buffer.at(i)!=1) { // FIXME - why does it throw 0x01 chars in the file???
                                Buffer3 += Buffer.at(i);
                        }
                } else {
                        if (Buffer3 != ".") {
                                // Transform ".." in "."
                                if (Buffer3 == "..")
                                        Buffer3 = ".";
                                // Add ">" before any "From" (mbox demand)
                                if (Buffer3.substr(0,4) == "From ")
                                        Buffer3 = ">" + Buffer3;
                                Buffer2 = Buffer2 + Buffer3 + "\n";
                                Buffer3 = "";
                                i += 1;
                        } else
                                break;
                }
        }

        cout << "Completed." << endl;

        Buffer = Buffer2;

        // Appends message in the file (FIXME: use streams)
        const char *buf = Buffer.c_str();
        FILE *f = fopen (Filename.c_str(), "a");
        fprintf(f, "%s", buf);
        fclose (f);

}

//=== Delete message ===//
void DeleteMessage (SOCKET Socket, int Message) {

        string ss;
        stringstream s;
        string data;

        s << Message;
        s >> ss;

        if (!SendData (Socket, "DELE " + ss)) Error(-2);
        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (11);

}

//=== Download messages ===//
void DownloadMessages (SOCKET Socket, int Messages, string Filename, bool Del) {
        string data;
        string Buffer;
        stringstream s;
        string ss;
        unsigned int len;
        int TotalMessages = Messages;

        if (TotalMessages == 0) {
                cout << "No messages on the server." << endl;
                return;
        }

        while (Messages != 0) {
                cout << "Recieving message " << (TotalMessages-Messages+1) << " of " << TotalMessages << endl;
                Buffer.erase();
                s.clear();
                s << (TotalMessages-Messages+1);
                s >> ss;
                double c = 0;
                if(!SendData(Socket, "RETR " + ss)) Error (-1);
                while (1) {
                        cout << ".";
                        c++;
                        if (c/64 == (long)c/64)
                                cout << " " << (int)c << "k" << endl;
                        data.erase();
                        RecieveData(Socket, &data);
                        Buffer += data;
                        len = Buffer.length();
                        if (len >= 4) {
                                if (Buffer.at(len-5) == 13
                                &&  Buffer.at(len-4) == 10
                                &&  Buffer.at(len-3) == 46
                                &&  Buffer.at(len-2) == 13
                                &&  Buffer.at(len-1) == 10)
                                        break;
                        }
                }
                cout << " " << (long)c << "k - completed" << endl;
                SaveMessage (Filename, Buffer, (long)c);

                if (Del)
                        DeleteMessage (Socket, (TotalMessages-Messages+1));

                Messages--;
        }
};

//=== Quit connection ===//
void QuitConnection (SOCKET Socket) {

        string data;

        if (!SendData (Socket, "QUIT")) Error(-2);
        if (!RecieveData (Socket, &data)) Error(-1);
        if (data.at(0) != '+') Error (12);

}

//=== Close connection ===//
void CloseConnection(SOCKET Socket) {
        closesocket(Socket);
};

//=== Main procedure ===//
int main(int argc, char **argv) {

        SOCKET Socket;
        string PopServer;
        string UserName;
        string Passwd;
        string Filename;
        string temp;
        bool Del;
        int Messages;

        // check args
        if (argc < 4 || argc > 6) {
                cout << "Usage: getpop pop3.server.com username pass*d [filename] [-d]" << endl;
                exit(1);
        }
        PopServer = argv[1];
        UserName  = argv[2];
        Passwd    = argv[3];
        Del = false;
        if (argc >= 5)
                Filename = argv[4];
        if (Filename == "-d" && argc == 5) {
                Filename = "inbox.mbx";
                Del = true;
        }
        if (argc == 6) {
                temp = argv[5];
                if (temp == "-d")
                        Del = true;
                else {
                        cout << "Usage: getpop pop3.server.com username pass*d [filename] [-d]" << endl;
                        exit(1);
                }
        }

        // Get connected socket
        Socket = Connect(PopServer);

        // Get number of messages
        Messages = NumberMessages(Socket, UserName, Passwd);

        // Download messages
        DownloadMessages(Socket, Messages, Filename, Del);

        // Close connection
        CloseConnection(Socket);

        return 0;

}
Hosted by www.Geocities.ws

1