about summary refs log tree commit diff
path: root/archive.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-04-09 16:37:28 -0400
committerJune McEnroe <june@causal.agency>2020-04-09 16:37:28 -0400
commit1e302b4e07d5229869821aa6240520420304d3f1 (patch)
tree6396fb032cf925bee630152c0b927520ad465617 /archive.c
parentParse envelopes (diff)
downloadbubger-1e302b4e07d5229869821aa6240520420304d3f1.tar.gz
bubger-1e302b4e07d5229869821aa6240520420304d3f1.zip
Export mbox files
Diffstat (limited to 'archive.c')
-rw-r--r--archive.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/archive.c b/archive.c
index cdfd982..497b5a6 100644
--- a/archive.c
+++ b/archive.c
@@ -75,7 +75,13 @@ static enum Atom fetchNew(FILE *imap, struct List threads) {
 	for (size_t i = 0; i < uids.len; ++i) {
 		fprintf(imap, "%s%" PRIu32, (i ? "," : ""), uids.ptr[i].number);
 	}
-	fprintf(imap, " (UID ENVELOPE)\r\n");
+	fprintf(
+		imap,
+		" ("
+		"UID ENVELOPE "
+		"BODY[HEADER.FIELDS (" MBOX_HEADERS ")] BODY[TEXT]"
+		")\r\n"
+	);
 
 done:
 	listFree(uids);
@@ -167,19 +173,37 @@ static struct Envelope parseEnvelope(struct List list) {
 }
 
 static void exportMessage(struct List items) {
-	static enum Atom AtomUID;
-	static enum Atom AtomEnvelope;
+	static enum Atom AtomUID, AtomEnvelope, AtomBody;
+	static enum Atom AtomHeaderFields, AtomText;
 	if (!AtomUID) AtomUID = atom("UID");
 	if (!AtomEnvelope) AtomEnvelope = atom("ENVELOPE");
+	if (!AtomBody) AtomBody = atom("BODY");
+	if (!AtomHeaderFields) AtomHeaderFields = atom("HEADER.FIELDS");
+	if (!AtomText) AtomText = atom("TEXT");
 
 	uint32_t uid = 0;
 	struct Envelope envelope = {0};
+	char *header = NULL;
+	char *body = NULL;
+
 	for (size_t i = 0; i + 1 < items.len; i += 2) {
-		if (items.ptr[i].type != Atom) {
+		enum Atom name;
+		if (items.ptr[i].type == Atom) {
+			name = items.ptr[i].atom;
+		} else if (
+			items.ptr[i].type == List &&
+			items.ptr[i].list.len &&
+			items.ptr[i].list.ptr[0].type == Atom
+		) {
+			name = items.ptr[i].list.ptr[0].atom;
+		} else {
 			errx(EX_PROTOCOL, "invalid data item name");
 		}
-		enum Atom name = items.ptr[i].atom;
-		if (name == AtomUID) {
+
+		if (name == AtomBody) {
+			i--;
+			continue;
+		} else if (name == AtomUID) {
 			if (items.ptr[i + 1].type != Number) {
 				errx(EX_PROTOCOL, "invalid UID data item value");
 			}
@@ -189,10 +213,33 @@ static void exportMessage(struct List items) {
 				errx(EX_PROTOCOL, "invalid ENVELOPE data item value");
 			}
 			envelope = parseEnvelope(items.ptr[i + 1].list);
+		} else if (name == AtomHeaderFields) {
+			if (items.ptr[i + 1].type != String) {
+				errx(EX_PROTOCOL, "invalid BODY[HEADER.FIELDS] data item value");
+			}
+			header = items.ptr[i + 1].string;
+		} else if (name == AtomText) {
+			if (items.ptr[i + 1].type != String) {
+				errx(EX_PROTOCOL, "invalid BODY[TEXT] data item value");
+			}
+			body = items.ptr[i + 1].string;
 		}
 	}
+
 	if (!uid) errx(EX_PROTOCOL, "missing UID data item");
 	if (!envelope.subject) errx(EX_PROTOCOL, "missing ENVELOPE data item");
+	if (!header) errx(EX_PROTOCOL, "missing BODY[HEADER.FIELDS] data item");
+	if (!body) errx(EX_PROTOCOL, "missing BODY[TEXT] data item");
+
+	const char *path = uidPath(uid, "mbox");
+	FILE *file = fopen(path, "w");
+	if (!file) err(EX_CANTCREAT, "%s", path);
+
+	int error = mboxFrom(file)
+		|| mboxHeader(file, header)
+		|| mboxBody(file, body)
+		|| fclose(file);
+	if (error) err(EX_IOERR, "%s", path);
 
 	envelopeFree(envelope);
 }