X("queue", 0, QUEUESW) \
X("noqueue", 0, NOQUEUESW) \
X("append filename", 0, APPENDSW) \
+ X("afolder foldername", 0, AFOLDERSW) \
X("timestamp", 0, TIMESTAMPSW) \
X("notimestamp", 0, NOTIMESTAMPSW) \
X("version", 0, VERSIONSW) \
struct imap_msg {
char *command; /* Command to send */
+ const char *folder; /* Folder (for append) */
bool queue; /* If true, queue for later delivery */
+ bool append; /* If true, append "command" to mbox */
+ size_t msgsize; /* RFC822 size of message */
struct imap_msg *next; /* Next pointer */
};
CHECK_PRINTF(2, 3);
static void imap_negotiate_tls(netsec_context *);
-static void add_msg(bool queue, const char *fmt, ...) CHECK_PRINTF(2, 3);
+static void add_msg(bool queue, struct imap_msg **, const char *fmt, ...)
+ CHECK_PRINTF(3, 4);
+static void add_append(const char *filename, const char *folder);
+
+static size_t rfc822size(const char *filename);
static bool timestamp = false;
int fd;
char *saslmech = NULL, *host = NULL, *port = "143", *user = NULL;
char *cp, **argp, buf[BUFSIZ], *oauth_svc = NULL, *errstr, **arguments, *p;
+ char *afolder = NULL;
netsec_context *nsc = NULL;
struct imap_msg *imsg;
size_t len;
die("missing argument to %s", argp[-2]);
continue;
+ case AFOLDERSW:
+ if (!(afolder = *argp++) || *afolder == '-')
+ die("missing argument to %s", argp[-2]);
+ continue;
+ case APPENDSW:
+ if (!*argp || (**argp == '-'))
+ die("missing argument to %s", argp[-2]);
+ if (! afolder)
+ die("Append folder must be set with -afolder first");
+ add_append(*argp++, afolder);
+ continue;
+
case SNOOPSW:
snoop = true;
continue;
} else if (*cp == '+') {
if (*(cp + 1) == '\0')
die("Invalid null folder name");
- add_msg(0, "SELECT \"%s\"", cp + 1);
+ add_msg(0, NULL, "SELECT \"%s\"", cp + 1);
} else {
- add_msg(queue, "%s", cp);
+ add_msg(queue, NULL, "%s", cp);
}
}
*/
static void
-add_msg(bool queue, const char *fmt, ...)
+add_msg(bool queue, struct imap_msg **ret_imsg, const char *fmt, ...)
{
struct imap_msg *imsg;
va_list ap;
imsg = mh_xmalloc(sizeof(*imsg));
imsg->command = msg;
+ imsg->folder = NULL;
+ imsg->append = false;
imsg->queue = queue;
imsg->next = NULL;
msgqueue_tail->next = imsg;
msgqueue_tail = imsg;
}
+
+ if (ret_imsg)
+ *ret_imsg = imsg;
+}
+
+/*
+ * Add an APPEND command to the queue
+ */
+
+static void
+add_append(const char *filename, const char *folder)
+{
+ size_t filesize = rfc822size(filename);
+ struct imap_msg *imsg;
+
+ add_msg(false, &imsg, "%s", filename);
+
+ imsg->folder = folder;
+ imsg->append = true;
+ imsg->msgsize = filesize;
}
/*
printf(": %f sec\n", delta);
}
+
+/*
+ * Calculate the RFC 822 size of file.
+ */
+
+static size_t
+rfc822size(const char *filename)
+{
+ FILE *f;
+ size_t total = 0, linecap = 0;
+ ssize_t rc;
+ char *line = NULL;
+
+ if (! (f = fopen(filename, "r")))
+ die("Unable to open %s: %s", filename, strerror(errno));
+
+ while ((rc = getline(&line, &linecap, f)) > 0) {
+ total += rc;
+ if (line[rc - 1] == '\n' && (rc == 1 || line[rc - 2] != '\r'))
+ total++;
+ if (line[rc - 1] != '\n')
+ total += 2;
+ }
+
+ free(line);
+
+ if (! feof(f))
+ die("Error while reading %s: %s", filename, strerror(errno));
+
+ fclose(f);
+
+ return total;
+}