diff options
author | June McEnroe <june@causal.agency> | 2020-01-26 17:44:01 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2020-01-26 17:44:01 -0500 |
commit | c6b5de5e278e38bddc927f9801b0266f94b4f144 (patch) | |
tree | 93befd1bbfb7c62118acfc95e728bb4a34aff102 | |
parent | Implement IMAP flow outline (diff) | |
download | notemap-c6b5de5e278e38bddc927f9801b0266f94b4f144.tar.gz notemap-c6b5de5e278e38bddc927f9801b0266f94b4f144.zip |
Implement append
-rw-r--r-- | notemap.1 | 4 | ||||
-rw-r--r-- | notemap.c | 82 |
2 files changed, 83 insertions, 3 deletions
diff --git a/notemap.1 b/notemap.1 index 8c66490..d2c7587 100644 --- a/notemap.1 +++ b/notemap.1 @@ -139,6 +139,10 @@ notemap -a -u june@causal.agency note.txt .Sh AUTHORS .An June Bug Aq Mt june@causal.agency . +.Sh CAVEATS +Notes are assumed to be plain UTF-8 text +with LF line endings. +. .Sh BUGS Send mail to .Aq Mt june@causal.agency diff --git a/notemap.c b/notemap.c index d05f9c0..963cd0a 100644 --- a/notemap.c +++ b/notemap.c @@ -198,8 +198,82 @@ static enum Atom atom(const char *str) { return Unknown; } -static void -append(FILE *imap, const char *from, const char *uuid, const char *path) { +static void append( + FILE *imap, const char *mailbox, + const char *from, const char *uuid, const char *path +) { + FILE *note = fopen(path, "r"); + if (!note) err(EX_NOINPUT, "%s", path); + + struct stat status; + int error = fstat(fileno(note), &status); + if (error) err(EX_IOERR, "%s", path); + + char date[sizeof("Mon, 00 Jan 0000 00:00:00 -0000")]; + strftime( + date, sizeof(date), "%a, %e %b %Y %H:%M:%S %z", + localtime(&status.st_mtime) + ); + +#define HEADERS \ + "From: <%s>\r\n" \ + "Subject: %s\r\n" \ + "Date: %s\r\n" \ + "X-Universally-Unique-Identifier: %s\r\n" \ + "X-Uniform-Type-Identifier: com.apple.mail-note\r\n" \ + "X-Mailer: notemap\r\n" \ + "MIME-Version: 1.0\r\n" \ + "Content-Type: text/plain; charset=\"utf-8\"\r\n" \ + "Content-Transfer-Encoding: quoted-printable\r\n" \ + "\r\n" + + size_t max = sizeof(HEADERS) + + strlen(from) + + strlen(path) + + strlen(date) + + strlen(uuid) + + 3 * status.st_size + + 3 * status.st_size / 76; + char *buf = malloc(max); + if (!buf) err(EX_OSERR, "malloc"); + + FILE *msg = fmemopen(buf, max, "w"); + if (!msg) err(EX_OSERR, "fmemopen"); + fprintf(msg, HEADERS, from, path, date, uuid); +#undef HEADERS + + int ch; + int len = 0; + while (EOF != (ch = fgetc(note))) { + if (len == 76 && ch != '\n') { + fprintf(msg, "=\r\n"); + len = 0; + } + if (ch == '\n') { + fprintf(msg, "\r\n"); + len = 0; + } else if (ch == '\t' || (ch >= ' ' && ch <= '~' && ch != '=')) { + fprintf(msg, "%c", ch); + len++; + } else { + fprintf(msg, "=%02X", ch); + len += 3; + } + } + if (ferror(note)) err(EX_IOERR, "%s", path); + fclose(note); + fclose(msg); + + buf[max - 1] = '\0'; + fprintf( + imap, "%s APPEND %s (\\Seen) {%zu}\r\n", + Atoms[Append], mailbox, strlen(buf) + ); + if (fgetc(imap) == '+') { + ungetc('+', imap); + fprintf(imap, "%s\r\n", buf); + } + free(buf); } int main(int argc, char *argv[]) { @@ -320,6 +394,7 @@ int main(int argc, char *argv[]) { break; case Next: { ssize_t len; next: + // FIXME: Handle EOF. len = getline(&entry, &entryCap, map); if (len < 0) err(EX_IOERR, "%s", path); if (entry[len - 1] == '\n') entry[len - 1] = '\0'; @@ -345,11 +420,12 @@ next: break; case Fetch: { append: - append(imap, user, uuid, note); + append(imap, mailbox, user, uuid, note); } break; case Append: { if (!seq) goto next; + // FIXME: Apparently we still get new flags back... fprintf( imap, "%s STORE %d +FLAGS.SILENT (\\Deleted)\r\n", Atoms[Next], seq |