Small library for reading mail messages via POP3. Currently doesn\'t return all header fields, and does only plain text authorization.

Dependents:   mmain pop3demo

pop3.cpp

Committer:
hlipka
Date:
2011-02-18
Revision:
6:3e29a3a6f3bb
Parent:
5:3182b4eda69b

File content as of revision 6:3e29a3a6f3bb:

/*
* POP3 library
* Copyright (c) 2010 Hendrik Lipka
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "Timer.h"

#include "pop3.h"
#include "dnsresolve.h"

using namespace mbed;

class Pop3CommandResponse
{
    public:
        Pop3CommandResponse(string line);
        bool addLine(string line);

        bool success;
        string responseLine;
        list<string> responseLines;
};

Pop3::Pop3(const char* servername, const char* username, const char* password) {
    _username=username;
    _password=password;
    _servername=servername;
}

Pop3::~Pop3() {
    close();
}

list<string> *Pop3::getMessages() {
    Pop3CommandResponse* pcr=sendCommandMultiResponse("LIST");
    if (!pcr->success) {
        delete pcr;
        return NULL;
    }
    list<string> *ids=new list<string>();
    list<string> lines=pcr->responseLines;
    list<string>::iterator it;
    for ( it=lines.begin() ; it != lines.end(); it++ ) {
        string line=*it;
        string id=line.substr(0,line.find(' '));
        ids->push_back(id);
    }
    delete pcr;
    return ids;
}

Pop3Message* Pop3::getMessage(string id, bool getSig, bool deleteOnReceive) {
    Pop3CommandResponse* pcr=sendCommand(string("UIDL ").append(id));
    if (!pcr->success)
    {
        delete pcr;
        return NULL;
    }
    
    char buf[74];
    int r=sscanf(pcr->responseLine.c_str(),"%*d %s",buf);
    if (1!=r)
    {
        printf("can't recognize UIDL response: [%s]\n",pcr->responseLine.c_str());
        delete pcr;
        return NULL;
    }
    string uid(buf);    
    delete pcr;
    
    pcr=sendCommandMultiResponse(string("RETR ").append(id));
    if (!pcr->success) {
        delete pcr;
        return NULL;
    }
    Pop3Message *msg=new Pop3Message();
    msg->id=uid;
    list<string> lines=pcr->responseLines;
    list<string>::iterator it;
    for ( it=lines.begin() ; it != lines.end(); it++ ) {
        string line=*it;
        if (0==line.find("From: ")) {
            msg->from=line.substr(6);
        } else if (0==line.find("Subject: ")) {
            msg->subject=line.substr(9);
        } else if (0==line.length()) {
            break;
        }
    }
    for (/* use iterator from above - it start right at the content */ ; it != lines.end(); it++ ) {
        string line=*it;
        if (!getSig && 0==line.compare("-- "))
            break;
        msg->content.push_back(line);
    }
    delete pcr;
    if (deleteOnReceive)
    {
        deleteMessage(id);
    }
    return msg;
}

bool Pop3::deleteMessage(string id) {
    Pop3CommandResponse* pcr=sendCommand(string("DELE ").append(id));
//    printf("r=%s\n",pcr->responseLine.c_str());
    if (!pcr->success) {
        delete pcr;
        return false;
    }
    delete pcr;
    return true;
}


Pop3CommandResponse* Pop3::sendCommand(string cmd) {
//    printf("send [%s]\n",cmd.c_str());
    _stream->sendLine(cmd);
    string r=_stream->readLine();
    return new Pop3CommandResponse(r);
}

Pop3CommandResponse* Pop3::sendCommandMultiResponse(string cmd) {
    // first, send command
//    printf("send [%s]\n",cmd.c_str());
    _stream->sendLine(cmd);
    // read first response line -> contains status
    string r=_stream->readLine();
//    printf("response=[%s]\n",r.c_str());
    // create response object to collect remaining lines
    Pop3CommandResponse *pcr=new Pop3CommandResponse(r);
    if (!pcr->success)
        return pcr;
    // read other lines, stop when marker reached
    while (true) {
        r=_stream->readLine();
        if (pcr->addLine(r))
            break;
    }
    return pcr;
}

bool Pop3::init() {
    _closed=false;
    _stream=new TCPLineStream(_servername,110,"\r\n");

    if (!_stream->open())
        return NULL;

    // read server banner
    string banner=_stream->readLine();
//    printf("banner=[%s]\n",banner.c_str());

    Pop3CommandResponse pcr(banner);
    if (!pcr.success)
        return false;

    // send username
    string cmd=string("user ").append(_username);
    Pop3CommandResponse *response=sendCommand(cmd);

    if (!response->success) {
        delete response;
        return false;
    }

    delete response;

    // send password
    cmd=string("pass ").append(_password);
    response=sendCommand(cmd);

    if (!response->success) {
        delete response;
        return false;
    }

    delete response;

    return true;
}

void Pop3::close() {
    if (_closed)
        return;

    Pop3CommandResponse *pcr=sendCommand("QUIT");
    delete pcr;

    if (NULL!=_stream) {
        _stream->close();
        delete _stream;
        _stream=NULL;
    }

    _closed=true;
}

Pop3CommandResponse::Pop3CommandResponse(string line) {
    if (0==line.find("+OK")) {
        success=true;
        responseLine=line.substr(4);
    } else if (0==line.find("-ERR")) {
        success=false;
        responseLine=line.substr(5);
    } else {
        success=false;
    }

}

bool Pop3CommandResponse::addLine(string line) {
    // last line is single dot only
    if (line.length()==1 && line.at(0)=='.')
        return true;
    // remove leading dot if any
    if (line.length()>0 && line.at(0)=='.')
        line=line.substr(1);
    responseLines.push_back(line);
    return false;
}