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 22:07:24 2011 +0000
Revision:
4:850d9e9884fd
Parent:
3:37570217ae90
Child:
5:3182b4eda69b
bugfix - did not read UIDL

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 4:850d9e9884fd 62 if (1!=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 delete pcr;
hlipka 3:37570217ae90 186
hlipka 3:37570217ae90 187 if (NULL!=_stream) {
hlipka 3:37570217ae90 188 _stream->close();
hlipka 3:37570217ae90 189 delete _stream;
hlipka 3:37570217ae90 190 _stream=NULL;
hlipka 3:37570217ae90 191 }
hlipka 3:37570217ae90 192
hlipka 3:37570217ae90 193 _closed=true;
hlipka 3:37570217ae90 194 }
hlipka 3:37570217ae90 195
hlipka 3:37570217ae90 196 Pop3CommandResponse::Pop3CommandResponse(string line) {
hlipka 3:37570217ae90 197 if (0==line.find("+OK")) {
hlipka 3:37570217ae90 198 success=true;
hlipka 3:37570217ae90 199 responseLine=line.substr(4);
hlipka 3:37570217ae90 200 } else if (0==line.find("-ERR")) {
hlipka 3:37570217ae90 201 success=false;
hlipka 3:37570217ae90 202 responseLine=line.substr(5);
hlipka 3:37570217ae90 203 } else {
hlipka 3:37570217ae90 204 success=false;
hlipka 3:37570217ae90 205 }
hlipka 3:37570217ae90 206
hlipka 3:37570217ae90 207 }
hlipka 3:37570217ae90 208
hlipka 3:37570217ae90 209 bool Pop3CommandResponse::addLine(string line) {
hlipka 3:37570217ae90 210 // last line is single dot only
hlipka 3:37570217ae90 211 if (line.length()==1 && line.at(0)=='.')
hlipka 3:37570217ae90 212 return true;
hlipka 3:37570217ae90 213 // remove leading dot if any
hlipka 3:37570217ae90 214 if (line.length()>0 && line.at(0)=='.')
hlipka 3:37570217ae90 215 line=line.substr(1);
hlipka 3:37570217ae90 216 responseLines.push_back(line);
hlipka 3:37570217ae90 217 return false;
hlipka 0:ec8a3cef200d 218 }