2 * Copyright 2011-2013, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
17 void (*func
)(int argc
, char **argv
);
22 static void do_help(int argc
, char** argv
);
25 extern const char* __progname
;
26 static const char* kProgramName
= __progname
;
28 static IMAP::Protocol sProtocol
;
32 error(const char* context
, status_t status
)
34 fprintf(stderr
, "Error during %s: %s\n", context
, strerror(status
));
41 printf("Usage: %s <server> <username> <password>\n", kProgramName
);
50 do_select(int argc
, char** argv
)
52 const char* folder
= "INBOX";
56 IMAP::SelectCommand
command(folder
);
57 status_t status
= sProtocol
.ProcessCommand(command
);
59 printf("Next UID: %" B_PRIu32
", UID validity: %" B_PRIu32
"\n",
60 command
.NextUID(), command
.UIDValidity());
62 error("select", status
);
67 do_folders(int argc
, char** argv
)
69 IMAP::FolderList folders
;
72 status_t status
= sProtocol
.GetFolders(folders
, separator
);
74 error("folders", status
);
78 for (size_t i
= 0; i
< folders
.size(); i
++) {
79 printf(" %s %s\n", folders
[i
].subscribed
? "*" : " ",
80 folders
[i
].folder
.String());
86 do_fetch(int argc
, char** argv
)
90 uint32 flags
= IMAP::kFetchAll
;
92 printf("usage: %s [<from>] [<to>] [header|body]\n", argv
[0]);
96 if (!strcasecmp(argv
[argc
- 1], "header")) {
97 flags
= IMAP::kFetchHeader
;
99 } else if (!strcasecmp(argv
[argc
- 1], "body")) {
100 flags
= IMAP::kFetchBody
;
105 from
= atoul(argv
[1]);
108 from
= to
= atoul(argv
[1]);
110 IMAP::FetchCommand
command(from
, to
, flags
| IMAP::kFetchFlags
);
112 // A fetch listener that dumps everything to stdout
113 class Listener
: public IMAP::FetchListener
{
119 virtual bool FetchData(uint32 fetchFlags
, BDataIO
& stream
,
126 ssize_t bytesRead
= stream
.Read(buffer
,
127 min_c(sizeof(buffer
), length
));
131 fBuffer
.Write(buffer
, bytesRead
);
135 // Null terminate the buffer
137 fBuffer
.Write(&null
, 1);
142 virtual void FetchedData(uint32 fetchFlags
, uint32 uid
, uint32 flags
)
144 printf("================= UID %ld, flags %lx =================\n",
146 puts((const char*)fBuffer
.Buffer());
153 command
.SetListener(&listener
);
155 status_t status
= sProtocol
.ProcessCommand(command
);
156 if (status
!= B_OK
) {
157 error("fetch", status
);
164 do_flags(int argc
, char** argv
)
169 printf("usage: %s [<from>] [<to>]\n", argv
[0]);
173 from
= atoul(argv
[1]);
178 IMAP::MessageEntryList entries
;
179 IMAP::FetchMessageEntriesCommand
command(entries
, from
, to
, true);
180 status_t status
= sProtocol
.ProcessCommand(command
);
181 if (status
!= B_OK
) {
182 error("flags", status
);
186 for (size_t i
= 0; i
< entries
.size(); i
++) {
187 printf("%10lu %8lu bytes, flags: %#lx\n", entries
[i
].uid
,
188 entries
[i
].size
, entries
[i
].flags
);
194 do_noop(int argc
, char** argv
)
196 IMAP::RawCommand
command("NOOP");
197 status_t status
= sProtocol
.ProcessCommand(command
);
199 error("noop", status
);
204 do_raw(int argc
, char** argv
)
206 // build command back again
210 for (int i
= 1; i
< argc
; i
++) {
212 strlcat(command
, " ", sizeof(command
));
213 strlcat(command
, argv
[i
], sizeof(command
));
216 class RawCommand
: public IMAP::Command
, public IMAP::Handler
{
218 RawCommand(const char* command
)
224 BString
CommandString()
229 bool HandleUntagged(IMAP::Response
& response
)
231 if (response
.IsCommand(fCommand
)) {
232 printf("-> %s\n", response
.ToString().String());
240 const char* fCommand
;
242 RawCommand
rawCommand(command
);
243 status_t status
= sProtocol
.ProcessCommand(rawCommand
);
245 error("raw", status
);
249 static cmd_entry sBuiltinCommands
[] = {
250 {"select", do_select
, "Selects a mailbox, defaults to INBOX"},
251 {"folders", do_folders
, "List of existing folders"},
253 "List of all mail UIDs in the mailbox with their flags"},
255 "Fetch mails via UIDs"},
256 {"noop", do_noop
, "Issue a NOOP command (will report new messages)"},
257 {"raw", do_raw
, "Issue a raw command to the server"},
258 {"help", do_help
, "prints this help text"},
259 {"quit", NULL
, "exits the application"},
265 do_help(int argc
, char** argv
)
267 printf("Available commands:\n");
269 for (cmd_entry
* command
= sBuiltinCommands
; command
->name
!= NULL
;
271 printf("%8s - %s\n", command
->name
, command
->help
);
280 main(int argc
, char** argv
)
285 const char* server
= argv
[1];
286 const char* user
= argv
[2];
287 const char* password
= argv
[3];
288 bool useSSL
= argc
> 4;
289 uint16 port
= useSSL
? 993 : 143;
291 BNetworkAddress
address(AF_INET
, server
, port
);
292 printf("Connecting to \"%s\" as %s%s, port %u\n", server
, user
,
293 useSSL
? " with SSL" : "", address
.Port());
295 status_t status
= sProtocol
.Connect(address
, user
, password
, useSSL
);
296 if (status
!= B_OK
) {
297 error("connect", status
);
306 if (fgets(line
, sizeof(line
), stdin
) == NULL
)
310 argv
= build_argv(line
, &argc
);
311 if (argv
== NULL
|| argc
== 0)
314 if (!strcmp(argv
[0], "quit")
315 || !strcmp(argv
[0], "exit")
316 || !strcmp(argv
[0], "q"))
319 int length
= strlen(argv
[0]);
322 for (cmd_entry
* command
= sBuiltinCommands
; command
->name
!= NULL
;
324 if (!strncmp(command
->name
, argv
[0], length
)) {
325 command
->func(argc
, argv
);
332 fprintf(stderr
, "Unknown command \"%s\". Type \"help\" for a "
333 "list of commands.\n", argv
[0]);