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