1 #include <unistd.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6
7 #include <libetpan/libetpan.h>
8
9 #include "option-parser.h"
10 #include "readmsg-common.h"
11
12 /* write content to the given filename */
13
etpan_write_data(char * filename,char * data,size_t len)14 static int etpan_write_data(char * filename, char * data, size_t len)
15 {
16 size_t write_len;
17 FILE * f;
18 int res;
19 mode_t old_umask;
20
21 old_umask = umask(0077);
22 f = fopen(filename, "wb");
23 umask(old_umask);
24 if (f == NULL) {
25 res = ERROR_FILE;
26 goto err;
27 }
28
29 write_len = fwrite(data, 1, len, f);
30 if (write_len < len) {
31 res = ERROR_FILE;
32 goto close;
33 }
34
35 fclose(f);
36
37 return NO_ERROR;
38
39 close:
40 fclose(f);
41 err:
42 return res;
43 }
44
45
46 /* save attachment */
47
save_mime_content(mailmessage * msg_info,struct mailmime * mime_part)48 static int save_mime_content(mailmessage * msg_info,
49 struct mailmime * mime_part)
50 {
51 char * body;
52 size_t body_len;
53 int r;
54 char * filename;
55 struct mailmime_single_fields fields;
56 int res;
57
58 memset(&fields, 0, sizeof(struct mailmime_single_fields));
59 if (mime_part->mm_mime_fields != NULL)
60 mailmime_single_fields_init(&fields, mime_part->mm_mime_fields,
61 mime_part->mm_content_type);
62
63 filename = fields.fld_disposition_filename;
64
65 if (filename == NULL)
66 filename = fields.fld_content_name;
67
68 if (filename == NULL)
69 return ERROR_INVAL;
70
71 r = etpan_fetch_message(msg_info, mime_part, &fields, &body, &body_len);
72 if (r != NO_ERROR) {
73 res = r;
74 goto err;
75 }
76
77 printf("writing %s, %lu bytes\n", filename, (unsigned long) body_len);
78
79 r = etpan_write_data(filename, body, body_len);
80 if (r != NO_ERROR) {
81 res = r;
82 goto free;
83 }
84
85 mailmime_decoded_part_free(body);
86
87 return NO_ERROR;
88
89 free:
90 mailmime_decoded_part_free(body);
91 err:
92 return res;
93 }
94
95
96
97 /* fetch attachments */
98
etpan_fetch_mime(FILE * f,mailmessage * msg_info,struct mailmime * mime)99 static int etpan_fetch_mime(FILE * f, mailmessage * msg_info,
100 struct mailmime * mime)
101 {
102 int r;
103 clistiter * cur;
104 struct mailmime_single_fields fields;
105 int res;
106
107 memset(&fields, 0, sizeof(struct mailmime_single_fields));
108 if (mime->mm_mime_fields != NULL)
109 mailmime_single_fields_init(&fields, mime->mm_mime_fields,
110 mime->mm_content_type);
111
112 switch(mime->mm_type) {
113 case MAILMIME_SINGLE:
114 save_mime_content(msg_info, mime);
115
116 break;
117
118 case MAILMIME_MULTIPLE:
119
120 for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ;
121 cur != NULL ; cur = clist_next(cur)) {
122
123 r = etpan_fetch_mime(f, msg_info, clist_content(cur));
124 if (r != NO_ERROR) {
125 res = r;
126 goto err;
127 }
128 }
129
130 break;
131
132 case MAILMIME_MESSAGE:
133
134 if (mime->mm_data.mm_message.mm_msg_mime != NULL) {
135 r = etpan_fetch_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime);
136 if (r != NO_ERROR) {
137 res = r;
138 goto err;
139 }
140 }
141
142 break;
143 }
144
145 return NO_ERROR;
146
147 err:
148 return res;
149 }
150
151
main(int argc,char ** argv)152 int main(int argc, char ** argv)
153 {
154 int r;
155 int driver;
156 char * server;
157 int port;
158 int connection_type;
159 char * user;
160 char * password;
161 int auth_type;
162 bool xoauth2;
163 char * path;
164 char * cache_directory;
165 char * flags_directory;
166 struct mailstorage * storage;
167 struct mailfolder * folder;
168
169 /* get options */
170
171 r = parse_options(argc, argv,
172 &driver, &server, &port, &connection_type,
173 &user, &password, &auth_type, &xoauth2,
174 &path, &cache_directory, &flags_directory);
175
176 /* build the storage structure */
177
178 storage = mailstorage_new(NULL);
179 if (storage == NULL) {
180 printf("error initializing storage\n");
181 goto free_opt;
182 }
183
184 r = init_storage(storage, driver, server, port, connection_type,
185 user, password, auth_type, xoauth2, path, cache_directory, flags_directory);
186 if (r != MAIL_NO_ERROR) {
187 printf("error initializing storage\n");
188 goto free_opt;
189 }
190
191 /* get the folder structure */
192
193 folder = mailfolder_new(storage, path, NULL);
194 if (folder == NULL) {
195 printf("error initializing folder\n");
196 goto free_storage;
197 }
198
199 r = mailfolder_connect(folder);
200 if (r != MAIL_NO_ERROR) {
201 printf("error initializing folder\n");
202 goto free_folder;
203 }
204
205 while (optind < argc) {
206 mailmessage * msg;
207 uint32_t msg_num;
208 struct mailmime * mime;
209
210 msg_num = strtoul(argv[optind], NULL, 10);
211
212 r = mailsession_get_message(folder->fld_session, msg_num, &msg);
213 if (r != MAIL_NO_ERROR) {
214 printf("** message %i not found ** - %s\n", msg_num,
215 maildriver_strerror(r));
216 optind ++;
217 continue;
218 }
219
220 r = mailmessage_get_bodystructure(msg, &mime);
221 if (r != MAIL_NO_ERROR) {
222 printf("** message %i not found - %s **\n", msg_num,
223 maildriver_strerror(r));
224 mailmessage_free(msg);
225 optind ++;
226 continue;
227 }
228
229 r = etpan_fetch_mime(stdout, msg, mime);
230
231 mailmessage_free(msg);
232
233 optind ++;
234 }
235
236 mailfolder_free(folder);
237 mailstorage_free(storage);
238
239 if (server != NULL)
240 free(server);
241 if (user != NULL)
242 free(user);
243 if (password != NULL)
244 free(password);
245 if (path != NULL)
246 free(path);
247 if (cache_directory != NULL)
248 free(cache_directory);
249 if (flags_directory != NULL)
250 free(flags_directory);
251
252 return 0;
253
254 free_folder:
255 mailfolder_free(folder);
256 free_storage:
257 mailstorage_free(storage);
258 free_opt:
259 if (server != NULL)
260 free(server);
261 if (user != NULL)
262 free(user);
263 if (password != NULL)
264 free(password);
265 if (path != NULL)
266 free(path);
267 if (cache_directory != NULL)
268 free(cache_directory);
269 if (flags_directory != NULL)
270 free(flags_directory);
271 return -1;
272 }
273