1 /*
2 ** Copyright 2002-2008, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #ifndef libmail_smtp_H
7 #define libmail_smtp_H
8 
9 #include "libmail_config.h"
10 #if HAVE_FCNTL_H
11 #include <fcntl.h>
12 #endif
13 #include	"mail.H"
14 #include	<sys/types.h>
15 
16 #include	"smtpinfo.H"
17 #include	"logininfo.H"
18 #include	"fd.H"
19 #include	<stdio.h>
20 #include	<time.h>
21 #include	<list>
22 #include	<string>
23 #include	<set>
24 #include	<queue>
25 #include	<vector>
26 
27 LIBMAIL_START
28 
29 ///////////////////////////////////////////////////////////////////////////
30 //
31 // An SMTP implementation
32 //
33 
34 class smtp : public fd, public loginInfo::callbackTarget {
35 
36 private:
37 	void resumed();
38 	void handler(std::vector<pollfd> &fds, int &timeout);
39 
40 	std::set<std::string> capabilities;
41 
42 	bool orderlyShutdown;
43 
44 	loginInfo smtpLoginInfo;
45 
46 	int socketRead(const std::string &readbuffer);
47 
48 	void disconnect(const char *reason);
49 
50 	std::list<std::string> smtpResponse;
51 	// SMTP server response being accumulated.
52 
53 	void (smtp::*responseHandler)(int numCode,
54 					    std::string multilineResponse);
55 	// Handler called when an SMTP response is received in entirety
56 
57 	void installHandler(void (smtp::*)(int numCode,
58 						 std::string multilineResponse));
59 	// Install next handler.
60 
61 	time_t responseTimeout;
62 	// SMTP timeout
63 
64 	void error(std::string);	/* Login failed */
65 	void success(std::string);	/* Login succeeded */
66 
67 	void howdy(const char *); /* send ehlo/helo */
68 
69 	void greetingResponse(int, std::string);
70 	void ehloResponse(int, std::string);
71 	void heloResponse(int, std::string);
72 	void auth_external_response(int, std::string);
73 	void quitResponse(int, std::string);
74 
75 	int hmac_method_index;
76 	/* Next HMAC authentication hash function to try */
77 
78 	void authenticate_hmac();
79 	void hmacResponse(int, std::string);
80 
81 	void starttls();
82 	void starttlsResponse(int, std::string);
83 
84 	void authenticate_login();
85 
86 	void begin_auth();
87 	void begin_auth_nonexternal();
88 
89 	void loginInfoCallback(std::string str);
90 	void loginInfoCallbackCancel();
91 
92 
93 	void loginUseridResponse(int, std::string);
94 	void loginPasswdResponse(int, std::string);
95 	void loginResponse(int, std::string);
96 
97 	void authenticated();
98 
99 	bool ready2send;	/* Fully logged in */
100 
101 	struct messageQueueInfo {
102 		FILE *message;
103 		mail::smtpInfo messageInfo;
104 		mail::callback *callback;
105 		bool flag8bit;
106 	};
107 
108 	std::queue<messageQueueInfo> sendQueue;
109 	/* Queue of messages waiting to go out */
110 
111 	bool fatalError;	// Fatal connection error occured
112 	time_t pingTimeout;	// When idling, ping occasionally
113 
114 	// Custom WriteBuffer that spits out the whole message
115 
116 	class Blast : public fd::WriteBuffer {
117 
118 		bool eofSent;
119 	public:
120 		smtp *mySmtp;
121 
122 		char lastChar;
123 
124 		size_t bytesTotal;
125 		size_t bytesDone;
126 
127 		Blast(smtp *smtpArg);
128 		~Blast();
129 
130 		bool fillWriteBuffer();
131 	};
132 
133 	Blast *myBlaster;
134 
135 public:
136 	friend class Blast;
137 
138 	smtp(std::string url, std::string passwd,
139 	     std::vector<std::string> &certificates,
140 	     mail::callback &callback,
141 	     mail::callback::disconnect &disconnectCallback,
142 	     loginCallback *loginCallbackFunc);
143 
144 	smtp(const smtp &); // UNDEFINED
145 	smtp &operator=(const smtp &); // UNDEFINED
146 
147 	~smtp();
148 
149 	void logout(mail::callback &callback);
150 	void checkNewMail(mail::callback &callback);
151 	bool hasCapability(std::string capability);
152 	std::string getCapability(std::string capability);
153 
154 	mail::folder *folderFromString(std::string);
155 
156 	void readTopLevelFolders(mail::callback::folderList &callback1,
157 				 mail::callback &callback2);
158 
159 	void findFolder(std::string folder,
160 			class mail::callback::folderList &callback1,
161 			class mail::callback &callback2);
162 	std::string translatePath(std::string path);
163 
164 	mail::folder *getSendFolder(const mail::smtpInfo &info,
165 				    const mail::folder *folder,
166 				    std::string &errmsg);
167 
168 
169 	void readMessageAttributes(const std::vector<size_t> &messages,
170 				   MessageAttributes attributes,
171 				   mail::callback::message &callback);
172 
173 	void readMessageContent(const std::vector<size_t> &messages,
174 				bool peek,
175 				enum mail::readMode readType,
176 				mail::callback::message &callback);
177 
178 	void readMessageContent(size_t messageNum,
179 				bool peek,
180 				const mimestruct &msginfo,
181 				enum mail::readMode readType,
182 				mail::callback::message &callback);
183 
184 	void readMessageContentDecoded(size_t messageNum,
185 				       bool peek,
186 				       const mimestruct &msginfo,
187 				       mail::callback::message &callback);
188 
189 	size_t getFolderIndexSize();
190 	mail::messageInfo getFolderIndexInfo(size_t);
191 
192 	void saveFolderIndexInfo(size_t,
193 				 const mail::messageInfo &,
194 				 mail::callback &);
195 
196 	void updateFolderIndexFlags(const std::vector<size_t> &messages,
197 				    bool doFlip,
198 				    bool enableDisable,
199 				    const mail::messageInfo &flags,
200 				    mail::callback &callback);
201 
202 	void updateFolderIndexInfo(mail::callback &);
203 	void removeMessages(const std::vector<size_t> &messages,
204 			    callback &cb);
205 
206 	void copyMessagesTo(const std::vector<size_t> &messages,
207 			    mail::folder *copyTo,
208 			    mail::callback &callback);
209 
210 	void searchMessages(const searchParams &searchInfo,
211 			    searchCallback &callback);
212 
213 
214 	void send(FILE *tmpfile, mail::smtpInfo &info,
215 		  mail::callback *callback,
216 		  bool flag8bit);
217 
218 private:
219 	void startNextMessage();
220 	void messageProcessed(int, std::string);
221 
222 	void rsetResponse(int, std::string);
223 	bool validString(std::string s);
224 
225 	std::string pipelineError;
226 	unsigned pipelineCount; // Count pipelined replies received
227 	unsigned rcptCount; // RCPT TO count.
228 	std::string pipelineCmd; // Command that got rejected.
229 
230 	void pipelinedResponse(int, std::string);
231 	void mailfromResponse(int, std::string);
232 
233 	void dataResponse(int, std::string);
234 	void data2Response(int, std::string);
235 };
236 
237 LIBMAIL_END
238 
239 #endif
240