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:
Tue Feb 01 21:17:03 2011 +0000
Revision:
3:37570217ae90
Parent:
2:3893c1aaee8d
Child:
4:850d9e9884fd
Now using UIDL as message ID, since the normal ID is not unique (between sessions). Also, now closes the session properly.

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