mirror of
https://github.com/bobbimanners/emailler.git
synced 2025-02-21 01:28:59 +00:00
Improved reply and forward functionality
This commit is contained in:
parent
be340f0c1c
commit
72d5177e98
190
apps/email.c
190
apps/email.c
@ -567,7 +567,7 @@ uint16_t decode_quoted_printable(char *p) {
|
||||
/*
|
||||
* Base64 decode table
|
||||
*/
|
||||
static const int8_t b64dec[] =
|
||||
const int8_t b64dec[] =
|
||||
{62,-1,-1,-1,63,52,53,54,55,56,
|
||||
57,58,59,60,61,-1,-1,-1,-2,-1,
|
||||
-1,-1, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
@ -619,11 +619,13 @@ void putline(FILE *fp, char *s) {
|
||||
* s - Pointer to pointer to input buffer. If all text is consumed, this is
|
||||
* set to NULL. If there is text left in the buffer to be consumed then
|
||||
* the pointer will be advanced to point to the next text to process.
|
||||
* cols - Number of columns to break at
|
||||
* mode - 'R' for reply, 'F' for forward, otherwise ' '
|
||||
* Returns 1 if the caller should invoke the routine again before obtaining
|
||||
* more input, or 0 if there is nothing more to do or caller needs to get more
|
||||
* input before next call.
|
||||
*/
|
||||
uint8_t word_wrap_line(FILE *fp, char **s) {
|
||||
uint8_t word_wrap_line(FILE *fp, char **s, uint8_t cols, char mode) {
|
||||
static uint8_t col = 0; // Keeps track of screen column
|
||||
char *ss = *s;
|
||||
char *ret = strchr(ss, '\r');
|
||||
@ -638,33 +640,43 @@ uint8_t word_wrap_line(FILE *fp, char **s) {
|
||||
l = ret - ss;
|
||||
}
|
||||
if (ret) {
|
||||
if ((col + l) <= 80) { // Fits on this line
|
||||
if ((col + l) <= cols) { // Fits on this line
|
||||
col += l;
|
||||
putline(fp, ss);
|
||||
if (ret) {
|
||||
col = 0;
|
||||
if (col + l != 80)
|
||||
if (col + l != cols) {
|
||||
fputc('\r', fp);
|
||||
if (mode == 'R') {
|
||||
fputc('>', fp);
|
||||
++col;
|
||||
}
|
||||
}
|
||||
}
|
||||
*s = nextline;
|
||||
return (*s ? 1 : 0); // Caller should invoke again
|
||||
}
|
||||
i = 80 - col; // Doesn't fit, need to break
|
||||
i = cols - col; // Doesn't fit, need to break
|
||||
if (i > l)
|
||||
i = l;
|
||||
while ((ss[--i] != ' ') && (i > 0));
|
||||
if (i == 0) { // No space character found
|
||||
if (col == 0) // Doesn't fit on full line
|
||||
for (i = 0; i < 80; ++i) { // Truncate @80 chars
|
||||
for (i = 0; i < cols; ++i) { // Truncate @cols chars
|
||||
fputc(ss[i], fp);
|
||||
*s = ss + l + 1;
|
||||
} else // There is stuff on this line already
|
||||
} else { // There is stuff on this line already
|
||||
col = 0;
|
||||
fputc('\r', fp); // Try a blank line
|
||||
col = 0;
|
||||
if (mode == 'R') {
|
||||
fputc('>', fp);
|
||||
++col;
|
||||
}
|
||||
}
|
||||
return (ret ? (*s ? 0 : 1) : 0); // If EOL, caller should invoke again
|
||||
}
|
||||
} else { // No ret
|
||||
i = 80 - col; // Space left on line
|
||||
i = cols - col; // Space left on line
|
||||
if (i > l)
|
||||
return 0; // Need more input to proceed
|
||||
while ((ss[--i] != ' ') && (i > 0));
|
||||
@ -675,6 +687,10 @@ uint8_t word_wrap_line(FILE *fp, char **s) {
|
||||
putline(fp, ss);
|
||||
fputc('\r', fp);
|
||||
col = 0;
|
||||
if (mode == 'R') {
|
||||
fputc('>', fp);
|
||||
++col;
|
||||
}
|
||||
*s = ss + i + 1;
|
||||
return (*s ? 1 : 0); // Caller should invoke again
|
||||
}
|
||||
@ -953,7 +969,7 @@ restart:
|
||||
if (readp) {
|
||||
if ((mime == 0) || ((mime == 4) && !mime_binary)) {
|
||||
do {
|
||||
c = word_wrap_line(stdout, &readp);
|
||||
c = word_wrap_line(stdout, &readp, 80, 0);
|
||||
if (*cursorrow == 22)
|
||||
break;
|
||||
} while (c == 1);
|
||||
@ -1395,6 +1411,141 @@ char prompt_okay(char *msg) {
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain the body of an email to include in a reply or forwarded message
|
||||
* For a plain text email, the body is everything after the headers
|
||||
* For a MIME multipart email, we take the first Text/Plain section
|
||||
* Email file to read is expected to be already open using fp
|
||||
* f - File handle for destination file (also already open)
|
||||
* mode - 'R' if reply, 'F' if forward
|
||||
*/
|
||||
void get_email_body(struct emailhdrs *h, FILE *f, char mode) {
|
||||
uint32_t pos = 0;
|
||||
uint8_t mime = 0;
|
||||
const int8_t *b = b64dec - 43;
|
||||
uint16_t chars;
|
||||
uint8_t mime_enc, mime_binary;
|
||||
char c, *readp, *writep;
|
||||
mime = 0;
|
||||
pos = 0;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
get_line(fp, 1, linebuf, &pos); // Reset buffer
|
||||
do {
|
||||
spinner();
|
||||
get_line(fp, 0, linebuf, &pos);
|
||||
if (!strncasecmp(linebuf, "MIME-Version: 1.0", 17))
|
||||
mime = 1;
|
||||
if (!strncasecmp(linebuf, "Content-Transfer-Encoding: ", 27)) {
|
||||
mime = 4;
|
||||
if (!strncmp(linebuf + 27, "7bit", 4))
|
||||
mime_enc = ENC_7BIT;
|
||||
else if (!strncmp(linebuf + 27, "quoted-printable", 16))
|
||||
mime_enc = ENC_QP;
|
||||
else if (!strncmp(linebuf + 27, "base64", 6))
|
||||
mime_enc = ENC_B64;
|
||||
else {
|
||||
error(ERR_NONFATAL, "Unsupp encoding %s\n", linebuf + 27);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (linebuf[0] != '\r');
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
readp = linebuf;
|
||||
writep = linebuf;
|
||||
get_line(fp, 1, linebuf, &pos); // Reset buffer
|
||||
while (1) {
|
||||
if (!readp)
|
||||
readp = linebuf;
|
||||
if (!writep)
|
||||
writep = linebuf;
|
||||
if (get_line(fp, 0, writep, &pos) == -1)
|
||||
break;
|
||||
if ((mime >= 1) && (!strncmp(writep, "--", 2))) {
|
||||
if ((mime == 4) && !mime_binary) // End of Text/Plain MIME section
|
||||
break;
|
||||
mime = 2;
|
||||
mime_enc = ENC_7BIT;
|
||||
mime_binary = 0;
|
||||
readp = writep = NULL;
|
||||
} else if ((mime < 4) && (mime >= 2)) {
|
||||
if (!strncasecmp(writep, "Content-Type: ", 14)) {
|
||||
if (!strncmp(writep + 14, "text/plain", 10)) {
|
||||
mime = 3;
|
||||
} else if (!strncmp(writep + 14, "text/html", 9)) {
|
||||
printf("\n<Not showing HTML>\n");
|
||||
mime = 1;
|
||||
} else {
|
||||
mime_binary = 1;
|
||||
mime = 3;
|
||||
}
|
||||
} else if (!strncasecmp(writep, "Content-Transfer-Encoding: ", 27)) {
|
||||
mime = 3;
|
||||
if (!strncmp(writep + 27, "7bit", 4))
|
||||
mime_enc = ENC_7BIT;
|
||||
else if (!strncmp(writep + 27, "quoted-printable", 16))
|
||||
mime_enc = ENC_QP;
|
||||
else if (!strncmp(writep + 27, "base64", 6))
|
||||
mime_enc = ENC_B64;
|
||||
else {
|
||||
printf("** Unsupp encoding %s\n", writep + 27);
|
||||
mime = 1;
|
||||
}
|
||||
} else if ((mime == 3) && (!strncmp(writep, "\r", 1))) {
|
||||
mime = 4;
|
||||
if (mime_binary)
|
||||
mime_enc = ENC_SKIP; // Skip over binary MIME parts
|
||||
}
|
||||
readp = writep = NULL;
|
||||
} else if (mime == 4) {
|
||||
switch (mime_enc) {
|
||||
case ENC_QP:
|
||||
chars = decode_quoted_printable(writep);
|
||||
break;
|
||||
case ENC_B64:
|
||||
//chars = decode_base64(writep);
|
||||
{
|
||||
uint8_t i = 0, j = 0;
|
||||
while (writep[i] != '\r') {
|
||||
writep[j++] = b[writep[i]] << 2 | b[writep[i + 1]] >> 4;
|
||||
if (writep[i + 2] != '=')
|
||||
writep[j++] = b[writep[i + 1]] << 4 | b[writep[i + 2]] >> 2;
|
||||
if (linebuf[i + 3] != '=')
|
||||
writep[j++] = b[writep[i + 2]] << 6 | b[writep[i + 3]];
|
||||
i += 4;
|
||||
}
|
||||
chars = j;
|
||||
}
|
||||
break;
|
||||
case ENC_SKIP:
|
||||
readp = writep = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (readp) {
|
||||
if ((mime == 0) || ((mime == 4) && !mime_binary)) {
|
||||
do {
|
||||
c = word_wrap_line(f, &readp, 78, mode);
|
||||
} while (c == 1);
|
||||
if (readp) {
|
||||
chars = strlen(readp);
|
||||
memmove(linebuf, readp, strlen(readp));
|
||||
readp = linebuf;
|
||||
writep = linebuf + chars;
|
||||
} else
|
||||
writep = NULL;
|
||||
}
|
||||
if ((mime == 4) && mime_binary) {
|
||||
readp = writep = NULL;
|
||||
}
|
||||
if (mime == 1) {
|
||||
readp = writep = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies the current message to mailbox mbox.
|
||||
* h is a pointer to the emailheaders for the message to copy
|
||||
@ -1450,21 +1601,12 @@ void copy_to_mailbox(struct emailhdrs *h, uint16_t idx,
|
||||
if ((mode == 'R') || (mode == 'F'))
|
||||
goto_prompt_row();
|
||||
|
||||
// Copy email
|
||||
// Copy email body
|
||||
putchar(' '); // For spinner
|
||||
while (1) {
|
||||
buflen = fread(buf, 1, READSZ, fp);
|
||||
spinner();
|
||||
if (buflen == 0)
|
||||
break;
|
||||
written = fwrite(buf, 1, buflen, fp2);
|
||||
if (written != buflen) {
|
||||
error(ERR_NONFATAL, "Write error during copy");
|
||||
fclose(fp);
|
||||
fclose(fp2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mode == 'R')
|
||||
fputc('>', fp2);
|
||||
get_email_body(h, fp2, mode);
|
||||
|
||||
putchar(BACKSPACE);
|
||||
putchar(' ');
|
||||
putchar(BACKSPACE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user