Hendrik Lipka / pop3

Dependents:   mmain pop3demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pop3.cpp Source File

pop3.cpp

00001 /*
00002 * POP3 library
00003 * Copyright (c) 2010 Hendrik Lipka
00004 * 
00005 * Permission is hereby granted, free of charge, to any person obtaining a copy
00006 * of this software and associated documentation files (the "Software"), to deal
00007 * in the Software without restriction, including without limitation the rights
00008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 * copies of the Software, and to permit persons to whom the Software is
00010 * furnished to do so, subject to the following conditions:
00011 * 
00012 * The above copyright notice and this permission notice shall be included in
00013 * all copies or substantial portions of the Software.
00014 * 
00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 * THE SOFTWARE.
00022 */
00023 
00024 #include "Timer.h"
00025 
00026 #include "pop3.h"
00027 #include "dnsresolve.h"
00028 
00029 using namespace mbed;
00030 
00031 class Pop3CommandResponse
00032 {
00033     public:
00034         Pop3CommandResponse(string line);
00035         bool addLine(string line);
00036 
00037         bool success;
00038         string responseLine;
00039         list<string> responseLines;
00040 };
00041 
00042 Pop3::Pop3(const char* servername, const char* username, const char* password) {
00043     _username=username;
00044     _password=password;
00045     _servername=servername;
00046 }
00047 
00048 Pop3::~Pop3() {
00049     close();
00050 }
00051 
00052 list<string> *Pop3::getMessages() {
00053     Pop3CommandResponse* pcr=sendCommandMultiResponse("LIST");
00054     if (!pcr->success) {
00055         delete pcr;
00056         return NULL;
00057     }
00058     list<string> *ids=new list<string>();
00059     list<string> lines=pcr->responseLines;
00060     list<string>::iterator it;
00061     for ( it=lines.begin() ; it != lines.end(); it++ ) {
00062         string line=*it;
00063         string id=line.substr(0,line.find(' '));
00064         ids->push_back(id);
00065     }
00066     delete pcr;
00067     return ids;
00068 }
00069 
00070 Pop3Message* Pop3::getMessage(string id, bool getSig, bool deleteOnReceive) {
00071     Pop3CommandResponse* pcr=sendCommand(string("UIDL ").append(id));
00072     if (!pcr->success)
00073     {
00074         delete pcr;
00075         return NULL;
00076     }
00077     
00078     char buf[74];
00079     int r=sscanf(pcr->responseLine.c_str(),"%*d %s",buf);
00080     if (1!=r)
00081     {
00082         printf("can't recognize UIDL response: [%s]\n",pcr->responseLine.c_str());
00083         delete pcr;
00084         return NULL;
00085     }
00086     string uid(buf);    
00087     delete pcr;
00088     
00089     pcr=sendCommandMultiResponse(string("RETR ").append(id));
00090     if (!pcr->success) {
00091         delete pcr;
00092         return NULL;
00093     }
00094     Pop3Message *msg=new Pop3Message();
00095     msg->id=uid;
00096     list<string> lines=pcr->responseLines;
00097     list<string>::iterator it;
00098     for ( it=lines.begin() ; it != lines.end(); it++ ) {
00099         string line=*it;
00100         if (0==line.find("From: ")) {
00101             msg->from=line.substr(6);
00102         } else if (0==line.find("Subject: ")) {
00103             msg->subject=line.substr(9);
00104         } else if (0==line.length()) {
00105             break;
00106         }
00107     }
00108     for (/* use iterator from above - it start right at the content */ ; it != lines.end(); it++ ) {
00109         string line=*it;
00110         if (!getSig && 0==line.compare("-- "))
00111             break;
00112         msg->content.push_back(line);
00113     }
00114     delete pcr;
00115     if (deleteOnReceive)
00116     {
00117         deleteMessage(id);
00118     }
00119     return msg;
00120 }
00121 
00122 bool Pop3::deleteMessage (string id) {
00123     Pop3CommandResponse* pcr=sendCommand(string("DELE ").append(id));
00124 //    printf("r=%s\n",pcr->responseLine.c_str());
00125     if (!pcr->success) {
00126         delete pcr;
00127         return false;
00128     }
00129     delete pcr;
00130     return true;
00131 }
00132 
00133 
00134 Pop3CommandResponse* Pop3::sendCommand(string cmd) {
00135 //    printf("send [%s]\n",cmd.c_str());
00136     _stream->sendLine(cmd);
00137     string r=_stream->readLine();
00138     return new Pop3CommandResponse(r);
00139 }
00140 
00141 Pop3CommandResponse* Pop3::sendCommandMultiResponse(string cmd) {
00142     // first, send command
00143 //    printf("send [%s]\n",cmd.c_str());
00144     _stream->sendLine(cmd);
00145     // read first response line -> contains status
00146     string r=_stream->readLine();
00147 //    printf("response=[%s]\n",r.c_str());
00148     // create response object to collect remaining lines
00149     Pop3CommandResponse *pcr=new Pop3CommandResponse(r);
00150     if (!pcr->success)
00151         return pcr;
00152     // read other lines, stop when marker reached
00153     while (true) {
00154         r=_stream->readLine();
00155         if (pcr->addLine(r))
00156             break;
00157     }
00158     return pcr;
00159 }
00160 
00161 bool Pop3::init() {
00162     _closed=false;
00163     _stream=new TCPLineStream(_servername,110,"\r\n");
00164 
00165     if (!_stream->open())
00166         return NULL;
00167 
00168     // read server banner
00169     string banner=_stream->readLine();
00170 //    printf("banner=[%s]\n",banner.c_str());
00171 
00172     Pop3CommandResponse pcr(banner);
00173     if (!pcr.success)
00174         return false;
00175 
00176     // send username
00177     string cmd=string("user ").append(_username);
00178     Pop3CommandResponse *response=sendCommand(cmd);
00179 
00180     if (!response->success) {
00181         delete response;
00182         return false;
00183     }
00184 
00185     delete response;
00186 
00187     // send password
00188     cmd=string("pass ").append(_password);
00189     response=sendCommand(cmd);
00190 
00191     if (!response->success) {
00192         delete response;
00193         return false;
00194     }
00195 
00196     delete response;
00197 
00198     return true;
00199 }
00200 
00201 void Pop3::close() {
00202     if (_closed)
00203         return;
00204 
00205     Pop3CommandResponse *pcr=sendCommand("QUIT");
00206     delete pcr;
00207 
00208     if (NULL!=_stream) {
00209         _stream->close();
00210         delete _stream;
00211         _stream=NULL;
00212     }
00213 
00214     _closed=true;
00215 }
00216 
00217 Pop3CommandResponse::Pop3CommandResponse(string line) {
00218     if (0==line.find("+OK")) {
00219         success=true;
00220         responseLine=line.substr(4);
00221     } else if (0==line.find("-ERR")) {
00222         success=false;
00223         responseLine=line.substr(5);
00224     } else {
00225         success=false;
00226     }
00227 
00228 }
00229 
00230 bool Pop3CommandResponse::addLine(string line) {
00231     // last line is single dot only
00232     if (line.length()==1 && line.at(0)=='.')
00233         return true;
00234     // remove leading dot if any
00235     if (line.length()>0 && line.at(0)=='.')
00236         line=line.substr(1);
00237     responseLines.push_back(line);
00238     return false;
00239 }