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

Dependents:   mmain pop3demo

Committer:
hlipka
Date:
Mon Feb 14 20:22:21 2011 +0000
Revision:
5:3182b4eda69b
Parent:
4:850d9e9884fd
Child:
6:3e29a3a6f3bb

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hlipka 3:37570217ae90 1 #include "Timer.h"
hlipka 3:37570217ae90 2
hlipka 3:37570217ae90 3 #include "pop3.h"
hlipka 3:37570217ae90 4 #include "dnsresolve.h"
hlipka 3:37570217ae90 5
hlipka 3:37570217ae90 6 using namespace mbed;
hlipka 3:37570217ae90 7
hlipka 3:37570217ae90 8 class Pop3CommandResponse
hlipka 3:37570217ae90 9 {
hlipka 3:37570217ae90 10 public:
hlipka 3:37570217ae90 11 Pop3CommandResponse(string line);
hlipka 3:37570217ae90 12 bool addLine(string line);
hlipka 3:37570217ae90 13
hlipka 3:37570217ae90 14 bool success;
hlipka 3:37570217ae90 15 string responseLine;
hlipka 3:37570217ae90 16 list<string> responseLines;
hlipka 3:37570217ae90 17 };
hlipka 3:37570217ae90 18
hlipka 3:37570217ae90 19 Pop3::Pop3(const char* servername, const char* username, const char* password) {
hlipka 3:37570217ae90 20 _username=username;
hlipka 3:37570217ae90 21 _password=password;
hlipka 3:37570217ae90 22 _servername=servername;
hlipka 3:37570217ae90 23 }
hlipka 3:37570217ae90 24
hlipka 3:37570217ae90 25 Pop3::~Pop3() {
hlipka 3:37570217ae90 26 close();
hlipka 3:37570217ae90 27 }
hlipka 3:37570217ae90 28
hlipka 3:37570217ae90 29 list<string> *Pop3::getMessages() {
hlipka 3:37570217ae90 30 Pop3CommandResponse* pcr=sendCommandMultiResponse("LIST");
hlipka 3:37570217ae90 31 if (!pcr->success) {
hlipka 3:37570217ae90 32 delete pcr;
hlipka 3:37570217ae90 33 return NULL;
hlipka 3:37570217ae90 34 }
hlipka 3:37570217ae90 35 list<string> *ids=new list<string>();
hlipka 3:37570217ae90 36 list<string> lines=pcr->responseLines;
hlipka 3:37570217ae90 37 list<string>::iterator it;
hlipka 3:37570217ae90 38 for ( it=lines.begin() ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 39 string line=*it;
hlipka 3:37570217ae90 40 string id=line.substr(0,line.find(' '));
hlipka 3:37570217ae90 41 ids->push_back(id);
hlipka 3:37570217ae90 42 }
hlipka 3:37570217ae90 43 delete pcr;
hlipka 3:37570217ae90 44 return ids;
hlipka 3:37570217ae90 45 }
hlipka 3:37570217ae90 46
hlipka 3:37570217ae90 47 Pop3Message* Pop3::getMessage(string id, bool getSig, bool deleteOnReceive) {
hlipka 3:37570217ae90 48 Pop3CommandResponse* pcr=sendCommand(string("UIDL ").append(id));
hlipka 3:37570217ae90 49 if (!pcr->success)
hlipka 3:37570217ae90 50 {
hlipka 3:37570217ae90 51 delete pcr;
hlipka 3:37570217ae90 52 return NULL;
hlipka 3:37570217ae90 53 }
hlipka 3:37570217ae90 54
hlipka 3:37570217ae90 55 char buf[74];
hlipka 3:37570217ae90 56 int r=sscanf(pcr->responseLine.c_str(),"%*d %s",buf);
hlipka 4:850d9e9884fd 57 if (1!=r)
hlipka 3:37570217ae90 58 {
hlipka 3:37570217ae90 59 printf("can't recognize UIDL response: [%s]\n",pcr->responseLine.c_str());
hlipka 3:37570217ae90 60 delete pcr;
hlipka 3:37570217ae90 61 return NULL;
hlipka 3:37570217ae90 62 }
hlipka 3:37570217ae90 63 string uid(buf);
hlipka 3:37570217ae90 64 delete pcr;
hlipka 3:37570217ae90 65
hlipka 3:37570217ae90 66 pcr=sendCommandMultiResponse(string("RETR ").append(id));
hlipka 3:37570217ae90 67 if (!pcr->success) {
hlipka 3:37570217ae90 68 delete pcr;
hlipka 3:37570217ae90 69 return NULL;
hlipka 3:37570217ae90 70 }
hlipka 3:37570217ae90 71 Pop3Message *msg=new Pop3Message();
hlipka 3:37570217ae90 72 msg->id=uid;
hlipka 3:37570217ae90 73 list<string> lines=pcr->responseLines;
hlipka 3:37570217ae90 74 list<string>::iterator it;
hlipka 3:37570217ae90 75 for ( it=lines.begin() ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 76 string line=*it;
hlipka 3:37570217ae90 77 if (0==line.find("From: ")) {
hlipka 3:37570217ae90 78 msg->from=line.substr(6);
hlipka 3:37570217ae90 79 } else if (0==line.find("Subject: ")) {
hlipka 3:37570217ae90 80 msg->subject=line.substr(9);
hlipka 3:37570217ae90 81 } else if (0==line.length()) {
hlipka 3:37570217ae90 82 break;
hlipka 3:37570217ae90 83 }
hlipka 3:37570217ae90 84 }
hlipka 3:37570217ae90 85 for (/* use iterator from above - it start right at the content */ ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 86 string line=*it;
hlipka 3:37570217ae90 87 if (!getSig && 0==line.compare("-- "))
hlipka 3:37570217ae90 88 break;
hlipka 3:37570217ae90 89 msg->content.push_back(line);
hlipka 3:37570217ae90 90 }
hlipka 3:37570217ae90 91 delete pcr;
hlipka 3:37570217ae90 92 if (deleteOnReceive)
hlipka 3:37570217ae90 93 {
hlipka 3:37570217ae90 94 deleteMessage(id);
hlipka 3:37570217ae90 95 }
hlipka 3:37570217ae90 96 return msg;
hlipka 3:37570217ae90 97 }
hlipka 3:37570217ae90 98
hlipka 3:37570217ae90 99 bool Pop3::deleteMessage(string id) {
hlipka 3:37570217ae90 100 Pop3CommandResponse* pcr=sendCommand(string("DELE ").append(id));
hlipka 3:37570217ae90 101 // printf("r=%s\n",pcr->responseLine.c_str());
hlipka 3:37570217ae90 102 if (!pcr->success) {
hlipka 3:37570217ae90 103 delete pcr;
hlipka 3:37570217ae90 104 return false;
hlipka 3:37570217ae90 105 }
hlipka 3:37570217ae90 106 delete pcr;
hlipka 3:37570217ae90 107 return true;
hlipka 3:37570217ae90 108 }
hlipka 3:37570217ae90 109
hlipka 3:37570217ae90 110
hlipka 3:37570217ae90 111 Pop3CommandResponse* Pop3::sendCommand(string cmd) {
hlipka 3:37570217ae90 112 // printf("send [%s]\n",cmd.c_str());
hlipka 3:37570217ae90 113 _stream->sendLine(cmd);
hlipka 3:37570217ae90 114 string r=_stream->readLine();
hlipka 3:37570217ae90 115 return new Pop3CommandResponse(r);
hlipka 3:37570217ae90 116 }
hlipka 3:37570217ae90 117
hlipka 3:37570217ae90 118 Pop3CommandResponse* Pop3::sendCommandMultiResponse(string cmd) {
hlipka 3:37570217ae90 119 // first, send command
hlipka 3:37570217ae90 120 // printf("send [%s]\n",cmd.c_str());
hlipka 3:37570217ae90 121 _stream->sendLine(cmd);
hlipka 3:37570217ae90 122 // read first response line -> contains status
hlipka 3:37570217ae90 123 string r=_stream->readLine();
hlipka 3:37570217ae90 124 // printf("response=[%s]\n",r.c_str());
hlipka 3:37570217ae90 125 // create response object to collect remaining lines
hlipka 3:37570217ae90 126 Pop3CommandResponse *pcr=new Pop3CommandResponse(r);
hlipka 3:37570217ae90 127 if (!pcr->success)
hlipka 3:37570217ae90 128 return pcr;
hlipka 3:37570217ae90 129 // read other lines, stop when marker reached
hlipka 3:37570217ae90 130 while (true) {
hlipka 3:37570217ae90 131 r=_stream->readLine();
hlipka 3:37570217ae90 132 if (pcr->addLine(r))
hlipka 3:37570217ae90 133 break;
hlipka 3:37570217ae90 134 }
hlipka 3:37570217ae90 135 return pcr;
hlipka 3:37570217ae90 136 }
hlipka 3:37570217ae90 137
hlipka 3:37570217ae90 138 bool Pop3::init() {
hlipka 5:3182b4eda69b 139 _closed=false;
hlipka 5:3182b4eda69b 140 _stream=new TCPLineStream(servername,110,"\r\n");
hlipka 5:3182b4eda69b 141
hlipka 3:37570217ae90 142 if (!_stream->open())
hlipka 3:37570217ae90 143 return NULL;
hlipka 3:37570217ae90 144
hlipka 3:37570217ae90 145 // read server banner
hlipka 3:37570217ae90 146 string banner=_stream->readLine();
hlipka 3:37570217ae90 147 // printf("banner=[%s]\n",banner.c_str());
hlipka 3:37570217ae90 148
hlipka 3:37570217ae90 149 Pop3CommandResponse pcr(banner);
hlipka 3:37570217ae90 150 if (!pcr.success)
hlipka 3:37570217ae90 151 return false;
hlipka 3:37570217ae90 152
hlipka 3:37570217ae90 153 // send username
hlipka 3:37570217ae90 154 string cmd=string("user ").append(_username);
hlipka 3:37570217ae90 155 Pop3CommandResponse *response=sendCommand(cmd);
hlipka 3:37570217ae90 156
hlipka 3:37570217ae90 157 if (!response->success) {
hlipka 3:37570217ae90 158 delete response;
hlipka 3:37570217ae90 159 return false;
hlipka 3:37570217ae90 160 }
hlipka 3:37570217ae90 161
hlipka 3:37570217ae90 162 delete response;
hlipka 3:37570217ae90 163
hlipka 3:37570217ae90 164 // send password
hlipka 3:37570217ae90 165 cmd=string("pass ").append(_password);
hlipka 3:37570217ae90 166 response=sendCommand(cmd);
hlipka 3:37570217ae90 167
hlipka 3:37570217ae90 168 if (!response->success) {
hlipka 3:37570217ae90 169 delete response;
hlipka 3:37570217ae90 170 return false;
hlipka 3:37570217ae90 171 }
hlipka 3:37570217ae90 172
hlipka 3:37570217ae90 173 delete response;
hlipka 3:37570217ae90 174
hlipka 3:37570217ae90 175 return true;
hlipka 3:37570217ae90 176 }
hlipka 3:37570217ae90 177
hlipka 3:37570217ae90 178 void Pop3::close() {
hlipka 3:37570217ae90 179 if (_closed)
hlipka 3:37570217ae90 180 return;
hlipka 3:37570217ae90 181
hlipka 3:37570217ae90 182 Pop3CommandResponse *pcr=sendCommand("QUIT");
hlipka 3:37570217ae90 183 delete pcr;
hlipka 3:37570217ae90 184
hlipka 3:37570217ae90 185 if (NULL!=_stream) {
hlipka 3:37570217ae90 186 _stream->close();
hlipka 3:37570217ae90 187 delete _stream;
hlipka 3:37570217ae90 188 _stream=NULL;
hlipka 3:37570217ae90 189 }
hlipka 3:37570217ae90 190
hlipka 3:37570217ae90 191 _closed=true;
hlipka 3:37570217ae90 192 }
hlipka 3:37570217ae90 193
hlipka 3:37570217ae90 194 Pop3CommandResponse::Pop3CommandResponse(string line) {
hlipka 3:37570217ae90 195 if (0==line.find("+OK")) {
hlipka 3:37570217ae90 196 success=true;
hlipka 3:37570217ae90 197 responseLine=line.substr(4);
hlipka 3:37570217ae90 198 } else if (0==line.find("-ERR")) {
hlipka 3:37570217ae90 199 success=false;
hlipka 3:37570217ae90 200 responseLine=line.substr(5);
hlipka 3:37570217ae90 201 } else {
hlipka 3:37570217ae90 202 success=false;
hlipka 3:37570217ae90 203 }
hlipka 3:37570217ae90 204
hlipka 3:37570217ae90 205 }
hlipka 3:37570217ae90 206
hlipka 3:37570217ae90 207 bool Pop3CommandResponse::addLine(string line) {
hlipka 3:37570217ae90 208 // last line is single dot only
hlipka 3:37570217ae90 209 if (line.length()==1 && line.at(0)=='.')
hlipka 3:37570217ae90 210 return true;
hlipka 3:37570217ae90 211 // remove leading dot if any
hlipka 3:37570217ae90 212 if (line.length()>0 && line.at(0)=='.')
hlipka 3:37570217ae90 213 line=line.substr(1);
hlipka 3:37570217ae90 214 responseLines.push_back(line);
hlipka 3:37570217ae90 215 return false;
hlipka 0:ec8a3cef200d 216 }