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:
Fri Feb 18 13:57:55 2011 +0000
Revision:
6:3e29a3a6f3bb
Parent:
5:3182b4eda69b
added license

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hlipka 6:3e29a3a6f3bb 1 /*
hlipka 6:3e29a3a6f3bb 2 * POP3 library
hlipka 6:3e29a3a6f3bb 3 * Copyright (c) 2010 Hendrik Lipka
hlipka 6:3e29a3a6f3bb 4 *
hlipka 6:3e29a3a6f3bb 5 * Permission is hereby granted, free of charge, to any person obtaining a copy
hlipka 6:3e29a3a6f3bb 6 * of this software and associated documentation files (the "Software"), to deal
hlipka 6:3e29a3a6f3bb 7 * in the Software without restriction, including without limitation the rights
hlipka 6:3e29a3a6f3bb 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
hlipka 6:3e29a3a6f3bb 9 * copies of the Software, and to permit persons to whom the Software is
hlipka 6:3e29a3a6f3bb 10 * furnished to do so, subject to the following conditions:
hlipka 6:3e29a3a6f3bb 11 *
hlipka 6:3e29a3a6f3bb 12 * The above copyright notice and this permission notice shall be included in
hlipka 6:3e29a3a6f3bb 13 * all copies or substantial portions of the Software.
hlipka 6:3e29a3a6f3bb 14 *
hlipka 6:3e29a3a6f3bb 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
hlipka 6:3e29a3a6f3bb 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
hlipka 6:3e29a3a6f3bb 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
hlipka 6:3e29a3a6f3bb 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
hlipka 6:3e29a3a6f3bb 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
hlipka 6:3e29a3a6f3bb 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
hlipka 6:3e29a3a6f3bb 21 * THE SOFTWARE.
hlipka 6:3e29a3a6f3bb 22 */
hlipka 6:3e29a3a6f3bb 23
hlipka 3:37570217ae90 24 #include "Timer.h"
hlipka 3:37570217ae90 25
hlipka 3:37570217ae90 26 #include "pop3.h"
hlipka 3:37570217ae90 27 #include "dnsresolve.h"
hlipka 3:37570217ae90 28
hlipka 3:37570217ae90 29 using namespace mbed;
hlipka 3:37570217ae90 30
hlipka 3:37570217ae90 31 class Pop3CommandResponse
hlipka 3:37570217ae90 32 {
hlipka 3:37570217ae90 33 public:
hlipka 3:37570217ae90 34 Pop3CommandResponse(string line);
hlipka 3:37570217ae90 35 bool addLine(string line);
hlipka 3:37570217ae90 36
hlipka 3:37570217ae90 37 bool success;
hlipka 3:37570217ae90 38 string responseLine;
hlipka 3:37570217ae90 39 list<string> responseLines;
hlipka 3:37570217ae90 40 };
hlipka 3:37570217ae90 41
hlipka 3:37570217ae90 42 Pop3::Pop3(const char* servername, const char* username, const char* password) {
hlipka 3:37570217ae90 43 _username=username;
hlipka 3:37570217ae90 44 _password=password;
hlipka 3:37570217ae90 45 _servername=servername;
hlipka 3:37570217ae90 46 }
hlipka 3:37570217ae90 47
hlipka 3:37570217ae90 48 Pop3::~Pop3() {
hlipka 3:37570217ae90 49 close();
hlipka 3:37570217ae90 50 }
hlipka 3:37570217ae90 51
hlipka 3:37570217ae90 52 list<string> *Pop3::getMessages() {
hlipka 3:37570217ae90 53 Pop3CommandResponse* pcr=sendCommandMultiResponse("LIST");
hlipka 3:37570217ae90 54 if (!pcr->success) {
hlipka 3:37570217ae90 55 delete pcr;
hlipka 3:37570217ae90 56 return NULL;
hlipka 3:37570217ae90 57 }
hlipka 3:37570217ae90 58 list<string> *ids=new list<string>();
hlipka 3:37570217ae90 59 list<string> lines=pcr->responseLines;
hlipka 3:37570217ae90 60 list<string>::iterator it;
hlipka 3:37570217ae90 61 for ( it=lines.begin() ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 62 string line=*it;
hlipka 3:37570217ae90 63 string id=line.substr(0,line.find(' '));
hlipka 3:37570217ae90 64 ids->push_back(id);
hlipka 3:37570217ae90 65 }
hlipka 3:37570217ae90 66 delete pcr;
hlipka 3:37570217ae90 67 return ids;
hlipka 3:37570217ae90 68 }
hlipka 3:37570217ae90 69
hlipka 3:37570217ae90 70 Pop3Message* Pop3::getMessage(string id, bool getSig, bool deleteOnReceive) {
hlipka 3:37570217ae90 71 Pop3CommandResponse* pcr=sendCommand(string("UIDL ").append(id));
hlipka 3:37570217ae90 72 if (!pcr->success)
hlipka 3:37570217ae90 73 {
hlipka 3:37570217ae90 74 delete pcr;
hlipka 3:37570217ae90 75 return NULL;
hlipka 3:37570217ae90 76 }
hlipka 3:37570217ae90 77
hlipka 3:37570217ae90 78 char buf[74];
hlipka 3:37570217ae90 79 int r=sscanf(pcr->responseLine.c_str(),"%*d %s",buf);
hlipka 4:850d9e9884fd 80 if (1!=r)
hlipka 3:37570217ae90 81 {
hlipka 3:37570217ae90 82 printf("can't recognize UIDL response: [%s]\n",pcr->responseLine.c_str());
hlipka 3:37570217ae90 83 delete pcr;
hlipka 3:37570217ae90 84 return NULL;
hlipka 3:37570217ae90 85 }
hlipka 3:37570217ae90 86 string uid(buf);
hlipka 3:37570217ae90 87 delete pcr;
hlipka 3:37570217ae90 88
hlipka 3:37570217ae90 89 pcr=sendCommandMultiResponse(string("RETR ").append(id));
hlipka 3:37570217ae90 90 if (!pcr->success) {
hlipka 3:37570217ae90 91 delete pcr;
hlipka 3:37570217ae90 92 return NULL;
hlipka 3:37570217ae90 93 }
hlipka 3:37570217ae90 94 Pop3Message *msg=new Pop3Message();
hlipka 3:37570217ae90 95 msg->id=uid;
hlipka 3:37570217ae90 96 list<string> lines=pcr->responseLines;
hlipka 3:37570217ae90 97 list<string>::iterator it;
hlipka 3:37570217ae90 98 for ( it=lines.begin() ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 99 string line=*it;
hlipka 3:37570217ae90 100 if (0==line.find("From: ")) {
hlipka 3:37570217ae90 101 msg->from=line.substr(6);
hlipka 3:37570217ae90 102 } else if (0==line.find("Subject: ")) {
hlipka 3:37570217ae90 103 msg->subject=line.substr(9);
hlipka 3:37570217ae90 104 } else if (0==line.length()) {
hlipka 3:37570217ae90 105 break;
hlipka 3:37570217ae90 106 }
hlipka 3:37570217ae90 107 }
hlipka 3:37570217ae90 108 for (/* use iterator from above - it start right at the content */ ; it != lines.end(); it++ ) {
hlipka 3:37570217ae90 109 string line=*it;
hlipka 3:37570217ae90 110 if (!getSig && 0==line.compare("-- "))
hlipka 3:37570217ae90 111 break;
hlipka 3:37570217ae90 112 msg->content.push_back(line);
hlipka 3:37570217ae90 113 }
hlipka 3:37570217ae90 114 delete pcr;
hlipka 3:37570217ae90 115 if (deleteOnReceive)
hlipka 3:37570217ae90 116 {
hlipka 3:37570217ae90 117 deleteMessage(id);
hlipka 3:37570217ae90 118 }
hlipka 3:37570217ae90 119 return msg;
hlipka 3:37570217ae90 120 }
hlipka 3:37570217ae90 121
hlipka 3:37570217ae90 122 bool Pop3::deleteMessage(string id) {
hlipka 3:37570217ae90 123 Pop3CommandResponse* pcr=sendCommand(string("DELE ").append(id));
hlipka 3:37570217ae90 124 // printf("r=%s\n",pcr->responseLine.c_str());
hlipka 3:37570217ae90 125 if (!pcr->success) {
hlipka 3:37570217ae90 126 delete pcr;
hlipka 3:37570217ae90 127 return false;
hlipka 3:37570217ae90 128 }
hlipka 3:37570217ae90 129 delete pcr;
hlipka 3:37570217ae90 130 return true;
hlipka 3:37570217ae90 131 }
hlipka 3:37570217ae90 132
hlipka 3:37570217ae90 133
hlipka 3:37570217ae90 134 Pop3CommandResponse* Pop3::sendCommand(string cmd) {
hlipka 3:37570217ae90 135 // printf("send [%s]\n",cmd.c_str());
hlipka 3:37570217ae90 136 _stream->sendLine(cmd);
hlipka 3:37570217ae90 137 string r=_stream->readLine();
hlipka 3:37570217ae90 138 return new Pop3CommandResponse(r);
hlipka 3:37570217ae90 139 }
hlipka 3:37570217ae90 140
hlipka 3:37570217ae90 141 Pop3CommandResponse* Pop3::sendCommandMultiResponse(string cmd) {
hlipka 3:37570217ae90 142 // first, send command
hlipka 3:37570217ae90 143 // printf("send [%s]\n",cmd.c_str());
hlipka 3:37570217ae90 144 _stream->sendLine(cmd);
hlipka 3:37570217ae90 145 // read first response line -> contains status
hlipka 3:37570217ae90 146 string r=_stream->readLine();
hlipka 3:37570217ae90 147 // printf("response=[%s]\n",r.c_str());
hlipka 3:37570217ae90 148 // create response object to collect remaining lines
hlipka 3:37570217ae90 149 Pop3CommandResponse *pcr=new Pop3CommandResponse(r);
hlipka 3:37570217ae90 150 if (!pcr->success)
hlipka 3:37570217ae90 151 return pcr;
hlipka 3:37570217ae90 152 // read other lines, stop when marker reached
hlipka 3:37570217ae90 153 while (true) {
hlipka 3:37570217ae90 154 r=_stream->readLine();
hlipka 3:37570217ae90 155 if (pcr->addLine(r))
hlipka 3:37570217ae90 156 break;
hlipka 3:37570217ae90 157 }
hlipka 3:37570217ae90 158 return pcr;
hlipka 3:37570217ae90 159 }
hlipka 3:37570217ae90 160
hlipka 3:37570217ae90 161 bool Pop3::init() {
hlipka 5:3182b4eda69b 162 _closed=false;
hlipka 6:3e29a3a6f3bb 163 _stream=new TCPLineStream(_servername,110,"\r\n");
hlipka 5:3182b4eda69b 164
hlipka 3:37570217ae90 165 if (!_stream->open())
hlipka 3:37570217ae90 166 return NULL;
hlipka 3:37570217ae90 167
hlipka 3:37570217ae90 168 // read server banner
hlipka 3:37570217ae90 169 string banner=_stream->readLine();
hlipka 3:37570217ae90 170 // printf("banner=[%s]\n",banner.c_str());
hlipka 3:37570217ae90 171
hlipka 3:37570217ae90 172 Pop3CommandResponse pcr(banner);
hlipka 3:37570217ae90 173 if (!pcr.success)
hlipka 3:37570217ae90 174 return false;
hlipka 3:37570217ae90 175
hlipka 3:37570217ae90 176 // send username
hlipka 3:37570217ae90 177 string cmd=string("user ").append(_username);
hlipka 3:37570217ae90 178 Pop3CommandResponse *response=sendCommand(cmd);
hlipka 3:37570217ae90 179
hlipka 3:37570217ae90 180 if (!response->success) {
hlipka 3:37570217ae90 181 delete response;
hlipka 3:37570217ae90 182 return false;
hlipka 3:37570217ae90 183 }
hlipka 3:37570217ae90 184
hlipka 3:37570217ae90 185 delete response;
hlipka 3:37570217ae90 186
hlipka 3:37570217ae90 187 // send password
hlipka 3:37570217ae90 188 cmd=string("pass ").append(_password);
hlipka 3:37570217ae90 189 response=sendCommand(cmd);
hlipka 3:37570217ae90 190
hlipka 3:37570217ae90 191 if (!response->success) {
hlipka 3:37570217ae90 192 delete response;
hlipka 3:37570217ae90 193 return false;
hlipka 3:37570217ae90 194 }
hlipka 3:37570217ae90 195
hlipka 3:37570217ae90 196 delete response;
hlipka 3:37570217ae90 197
hlipka 3:37570217ae90 198 return true;
hlipka 3:37570217ae90 199 }
hlipka 3:37570217ae90 200
hlipka 3:37570217ae90 201 void Pop3::close() {
hlipka 3:37570217ae90 202 if (_closed)
hlipka 3:37570217ae90 203 return;
hlipka 3:37570217ae90 204
hlipka 3:37570217ae90 205 Pop3CommandResponse *pcr=sendCommand("QUIT");
hlipka 3:37570217ae90 206 delete pcr;
hlipka 3:37570217ae90 207
hlipka 3:37570217ae90 208 if (NULL!=_stream) {
hlipka 3:37570217ae90 209 _stream->close();
hlipka 3:37570217ae90 210 delete _stream;
hlipka 3:37570217ae90 211 _stream=NULL;
hlipka 3:37570217ae90 212 }
hlipka 3:37570217ae90 213
hlipka 3:37570217ae90 214 _closed=true;
hlipka 3:37570217ae90 215 }
hlipka 3:37570217ae90 216
hlipka 3:37570217ae90 217 Pop3CommandResponse::Pop3CommandResponse(string line) {
hlipka 3:37570217ae90 218 if (0==line.find("+OK")) {
hlipka 3:37570217ae90 219 success=true;
hlipka 3:37570217ae90 220 responseLine=line.substr(4);
hlipka 3:37570217ae90 221 } else if (0==line.find("-ERR")) {
hlipka 3:37570217ae90 222 success=false;
hlipka 3:37570217ae90 223 responseLine=line.substr(5);
hlipka 3:37570217ae90 224 } else {
hlipka 3:37570217ae90 225 success=false;
hlipka 3:37570217ae90 226 }
hlipka 3:37570217ae90 227
hlipka 3:37570217ae90 228 }
hlipka 3:37570217ae90 229
hlipka 3:37570217ae90 230 bool Pop3CommandResponse::addLine(string line) {
hlipka 3:37570217ae90 231 // last line is single dot only
hlipka 3:37570217ae90 232 if (line.length()==1 && line.at(0)=='.')
hlipka 3:37570217ae90 233 return true;
hlipka 3:37570217ae90 234 // remove leading dot if any
hlipka 3:37570217ae90 235 if (line.length()>0 && line.at(0)=='.')
hlipka 3:37570217ae90 236 line=line.substr(1);
hlipka 3:37570217ae90 237 responseLines.push_back(line);
hlipka 3:37570217ae90 238 return false;
hlipka 0:ec8a3cef200d 239 }