Init mime struct
[rmail.git] / src / utils / test_view_mail.c
blobaaca87daba789b4d1f28da8ccd9b9b3037a97114
1 #define _BSD_SOURCE
3 #include <stdio.h>
4 #include <string.h>
5 #include <limits.h>
6 #include <unistd.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <time.h>
10 #include <ctype.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
15 #include "string_utils.h"
16 #include "file_utils.h"
17 #include "rfc5322.h"
18 #include "rfc2047.h"
19 #include "rfc822.h"
20 #include "mime.h"
21 #include "mail.h"
23 static int hdr_only = 0;
24 static int mime_only = 0;
26 static void plain_body(char *line)
28 printf("%s", line);
32 static void qp_body(char *line)
34 char buf[1024];
36 rfc2047_decode_quoted_printable(buf, line, sizeof(buf) - 1);
37 printf("%s", buf);
40 static void parse_mail_body(FILE *fh, struct mail_header *hdr)
42 char buf[1024];
43 void (*decode_body)(char *line);
45 switch (hdr->mime.transfer_encoding) {
46 case MIME_ENCODING_QUOTED_PRINTABLE:
47 decode_body = qp_body;
48 break;
49 default:
50 decode_body = plain_body;
51 break;
54 (void) fseek(fh, hdr->body_offset, SEEK_SET);
56 while (fgets(buf, sizeof(buf), fh)) {
57 decode_body(buf);
61 static void parse_mail_header(FILE *fh, struct mail_header *hdr)
63 char *crlf = NULL;
64 char buf[1024];
66 /* Scan all lines */
67 while (fgets(buf, sizeof(buf), fh)) {
68 if (!strncasecmp(buf, "From:", 5)) {
69 rfc5322_extract_address(hdr->from, buf, sizeof(hdr->from));
70 crlf = strrchr(buf, '\n');
71 if (crlf)
72 *crlf = '\0';
73 } else if (!strncasecmp(buf, "Subject:", 8)) {
74 rfc5322_extract_subject(hdr->subject, buf, sizeof(hdr->subject));
75 } else if (!strncasecmp(buf, "Date:", 5)) {
76 hdr->date = rfc822_parsedt(buf);
77 } else if (!strncasecmp(buf, "Content-Type:", 13)) {
78 mime_content_type(buf, &hdr->mime);
79 } else if (!strncasecmp(buf, "Content-Disposition:", 20)) {
80 mime_content_disposition(buf, &hdr->mime);
81 } else if (!strncasecmp(buf, "Content-Transfer-Encoding:", 26)) {
82 mime_content_transfer_encoding(buf, &hdr->mime);
83 } else {
84 if (rfc822_check_header_end(buf)) {
85 break;
87 /*printf("[SKIP] ------- %s", buf); */
91 hdr->body_offset = ftell(fh);
94 static void init_mail_header(struct mail_header *hdr)
96 memset(hdr->from, 0, sizeof(hdr->from));
97 memset(hdr->subject, 0, sizeof(hdr->subject));
99 hdr->body_offset = 0L;
101 /* MIME */
102 /* [RFC2045]
103 * If no Content-Type header field is specified, default to:
104 * Content-type: text/plain; charset=us-ascii
106 hdr->mime.type = MIME_TYPE_TEXT;
107 hdr->mime.subtype = MIME_SUBTYPE_PLAIN;
108 hdr->mime.disposition = MIME_DISPOSITION_UNKNOWN;
110 /* [RFC2045] "Content-Transfer-Encoding: 7BIT" is assumed if the
111 * Content-Transfer-Encoding header field is not present.
112 * ... If a Content-Transfer-Encoding header field appears as part
113 * of a message header, it applies to the entire body of that message.
114 * If a Content-Transfer-Encoding header field appears as part of an
115 * entity's headers, it applies only to the body of that entity.
116 * If an entity is of type "multipart" the Content-Transfer-Encoding
117 * is not permitted to have any value other than "7bit", "8bit" or
118 * "binary".
120 hdr->mime.transfer_encoding = MIME_ENCODING_7BIT;
123 void usage(const char *appname)
125 fprintf(stderr, "Usage:\n%s options\n", appname);
126 fprintf(stderr, "Options:\n");
127 fprintf(stderr, " -h Parse header only\n"
128 " -m Parse MIMI only\n"
129 " -f <file> Parse file\n"
130 " -d <maildir> Parse maildir\n");
133 static void parse_file(const char *file)
135 FILE *fh;
136 struct mail_header mail_hdr;
138 if (file_type(file))
139 return;
141 fh = fopen(file, "r");
142 if (!fh) {
143 return;
146 init_mail_header(&mail_hdr);
148 parse_mail_header(fh, &mail_hdr);
150 fprintf(stderr, "-------------------------------------------\n");
151 fprintf(stderr, "Test file: %s\n", file);
152 fprintf(stderr, "-------------------------------------------\n");
153 if (!mime_only) {
154 fprintf(stderr, "Date : %s\n", rfc822_mkdt(mail_hdr.date));
155 fprintf(stderr, "From : %s\n", mail_hdr.from);
156 fprintf(stderr, "Subject: %s\n", mail_hdr.subject);
159 debug_mime_header(&mail_hdr.mime);
161 fprintf(stderr, "-------------------------------------------\n");
163 if (!hdr_only) {
164 /* Message Body */
165 parse_mail_body(fh, &mail_hdr);
168 fclose(fh);
172 int main(int argc, char **argv)
174 int opt;
176 char *file = NULL;
177 char *maildir_path = NULL;
179 char old_path[PATH_MAX];
180 int rc;
182 while ((opt = getopt(argc, argv, "d:f:hm")) != -1) {
183 switch (opt) {
184 case 'd':
185 maildir_path = optarg;
186 break;
187 case 'f':
188 file = optarg;
189 break;
190 case 'h':
191 hdr_only = 1;
192 break;
193 case 'm':
194 mime_only = 1;
195 break;
196 default:
197 fprintf(stderr, "Unknown parameter.\n");
198 usage(argv[0]);
199 return -1;
203 if ((file == NULL) && (maildir_path == NULL)) {
204 usage(argv[0]);
205 return -1;
207 if ((file != NULL) && (maildir_path != NULL)) {
208 fprintf(stderr, "-f and -d are mutually esclusive!.\n");
209 usage(argv[0]);
212 if (file != NULL) {
213 parse_file(file);
214 return 0;
217 /* Parse all maildir */
218 if (!getcwd(old_path, PATH_MAX)) {
219 fprintf(stderr, "%s - GETCWD: %s\n", __func__, strerror(errno));
220 return -1;
223 if (chdir(maildir_path) < 0) {
224 fprintf(stderr, "%s - CHDIR: %s\n", __func__, strerror(errno));
225 return -1;
228 rc = scan_dir(maildir_path, parse_file);
230 if (chdir(old_path) < 0) {
231 fprintf(stderr, "%s - Cannot restore path %s!\n", __func__, strerror(errno));
234 return rc;