Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/src/pop3.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 115 - (show annotations) (download) (as text)
Fri Dec 7 07:17:41 2012 UTC (11 years, 5 months ago) by z0rac
File MIME type: text/x-c++src
File size: 4181 byte(s)


1 /*
2 * Copyright (C) 2009-2011 TSUBAKIMOTO Hiroya <z0rac@users.sourceforge.jp>
3 *
4 * This software comes with ABSOLUTELY NO WARRANTY; for details of
5 * the license terms, see the LICENSE.txt file included with the program.
6 */
7 #include "mailbox.h"
8 #include <algorithm>
9
10 #if _DEBUG >= 2
11 #include <iostream>
12 #define DBG(s) s
13 #define LOG(s) (cout << s)
14 #else
15 #define DBG(s)
16 #define LOG(s)
17 #endif
18
19 /** pop3 - pop3 protocol backend
20 * This class is a mailbox::backend for POP3 protocol.
21 */
22 class pop3 : public mailbox::backend {
23 bool _command(const string& cmd, bool ok = true);
24 bool _ok(bool ok = true);
25 typedef list< pair<string, string> > plist;
26 plist _plist(bool upper = false);
27 string _headers();
28 #ifdef _DEBUG
29 using backend::read;
30 string read()
31 {
32 string line = backend::read();
33 LOG("R: " << line << endl);
34 return line;
35 }
36 #endif
37 public:
38 void login(const uri& uri, const string& passwd);
39 void logout();
40 size_t fetch(mailbox& mbox, const uri& uri);
41 };
42
43 void
44 pop3::login(const uri& uri, const string& passwd)
45 {
46 _ok();
47 if (_command("CAPA", false)) {
48 bool uidl = false, stls = false;
49 plist cap(_plist(true));
50 plist::iterator p = cap.begin();
51 for (; p != cap.end(); ++p) {
52 if (p->first == "UIDL") uidl = true;
53 else if (p->first == "STLS") stls = true;
54 }
55 if (!uidl) throw mailbox::error("server not support UIDL command");
56 if (stls && !tls()) {
57 _command("STLS");
58 starttls(uri[uri::host]);
59 _command("CAPA");
60 cap = _plist(true);
61 }
62 for (p = cap.begin(); p != cap.end(); ++p) {
63 if (p->first == "USER") break;
64 }
65 if (p == cap.end()) throw mailbox::error("login disabled");
66 }
67 _command("USER " + uri[uri::user]);
68 _command("PASS " + passwd);
69 }
70
71 void
72 pop3::logout()
73 {
74 _command("QUIT");
75 }
76
77 size_t
78 pop3::fetch(mailbox& mbox, const uri& uri)
79 {
80 const list<string>& ignore = mbox.ignore();
81 list<string> ignored;
82 list<mail> mails;
83 list<mail> recents;
84 bool recent = uri[uri::fragment] == "recent";
85 _command("UIDL");
86 plist uidl(_plist());
87 plist::iterator uidp = uidl.begin();
88 for (; uidp != uidl.end(); ++uidp) {
89 string uid = uidp->second;
90 if (find(ignore.begin(), ignore.end(), uid) != ignore.end()) {
91 ignored.push_back(uid);
92 continue;
93 }
94 LOG("Fetch mail: " << uid << endl);
95 _command("TOP " + uidp->first + " 0");
96 mail m(uid);
97 if (m.header(_headers())) {
98 ignored.push_back(uid);
99 continue;
100 }
101 if (recent) {
102 ignored.push_back(uid);
103 recents.push_back(m);
104 } else {
105 (mbox.find(uid) ? &mails : &recents)->push_back(m);
106 }
107 }
108 size_t count = recents.size();
109 mails.splice(mails.end(), recents);
110 mbox.mails(mails);
111 mbox.ignore(ignored);
112 return count;
113 }
114
115 bool
116 pop3::_command(const string& cmd, bool ok)
117 {
118 write(cmd);
119 LOG("S: " << cmd << endl);
120 return _ok(ok);
121 }
122
123 bool
124 pop3::_ok(bool ok)
125 {
126 string line = read();
127 bool resp = line.substr(0, line.find_first_of(' ')) == "+OK";
128 if (ok && !resp) throw mailbox::error(line);
129 return resp;
130 }
131
132 pop3::plist
133 pop3::_plist(bool upper)
134 {
135 plist result;
136 for (;;) {
137 string line = read();
138 if (!line.empty() && line[0] == '.') {
139 line.assign(line, 1, line.size() - 1);
140 if (line.empty()) break;
141 }
142 if (upper) line = tokenizer::uppercase(line);
143 pair<string, string> ps;
144 string::size_type i = line.find_first_of(' ');
145 ps.first.assign(line, 0, i);
146 if (i != string::npos) {
147 i = line.find_first_not_of(' ', i);
148 if (i != string::npos) ps.second.assign(line, i, line.size() - i);
149 }
150 result.push_back(ps);
151 }
152 return result;
153 }
154
155 string
156 pop3::_headers()
157 {
158 string result;
159 string line = read();
160 for (; !line.empty(); line = read()) {
161 if (line[0] == '.') {
162 if (line.size() == 1) break;
163 line.erase(0, 1);
164 }
165 result += line + "\015\012";
166 }
167 while (line.size() != 1 || line[0] != '.') line = read();
168 return result;
169 }
170
171 mailbox::backend* backendPOP3() { return new pop3; }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26