mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-09-28 17:54:39 +00:00
Improvements to EMAIL.DB format. Don't delete headers, just hide them.
This commit is contained in:
parent
71cfe5f60b
commit
b3b556b440
64
apps/email.c
64
apps/email.c
@ -1,8 +1,8 @@
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Simple Email User Agent
|
||||
// Bobbi June 2020
|
||||
// Handles INBOX in the format created by POP65
|
||||
//
|
||||
// Bobbi June 2020
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -10,6 +10,9 @@
|
||||
#include <conio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EMAIL_C
|
||||
#include "email_common.h"
|
||||
|
||||
#define SCROLLBACK 25*80
|
||||
|
||||
char filename[80];
|
||||
@ -18,23 +21,6 @@ struct emailhdrs *headers;
|
||||
uint16_t selection, prevselection;
|
||||
uint16_t num_msgs;
|
||||
|
||||
// Configuration params from POP65.CFG
|
||||
char cfg_server[80]; // IP of POP3 server
|
||||
char cfg_user[80]; // Username
|
||||
char cfg_pass[80]; // Password
|
||||
char cfg_spooldir[80]; // ProDOS directory to spool email to
|
||||
char cfg_inboxdir[80]; // ProDOS directory for email inbox
|
||||
|
||||
// Represents the email headers for one message
|
||||
struct emailhdrs {
|
||||
char date[80];
|
||||
char from[80];
|
||||
char to[80];
|
||||
char cc[80];
|
||||
char subject[80];
|
||||
struct emailhdrs *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Keypress before quit
|
||||
*/
|
||||
@ -71,7 +57,7 @@ void readconfigfile(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Read EMAIL.DB
|
||||
* Read EMAIL.DB and populate linked list rooted at headers
|
||||
*/
|
||||
void read_email_db(void) {
|
||||
struct emailhdrs *curr = NULL, *prev = NULL;
|
||||
@ -116,9 +102,9 @@ void printfield(char *s, uint8_t start, uint8_t end) {
|
||||
/*
|
||||
* Print one line summary of email headers for one message
|
||||
*/
|
||||
void print_one_email_summary(uint16_t num, struct emailhdrs *h, uint8_t inverse) {
|
||||
void print_one_email_summary(struct emailhdrs *h, uint8_t inverse) {
|
||||
putchar(inverse ? 0xf : 0xe); // INVERSE or NORMAL
|
||||
printf("%02d|", num);
|
||||
printf("%02d|", h->emailnum);
|
||||
printfield(h->date, 0, 16);
|
||||
putchar('|');
|
||||
printfield(h->from, 0, 20);
|
||||
@ -129,7 +115,7 @@ void print_one_email_summary(uint16_t num, struct emailhdrs *h, uint8_t inverse)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get emailhdrs for nth email
|
||||
* Get emailhdrs for nth email in list of headers
|
||||
*/
|
||||
struct emailhdrs *get_headers(uint16_t n) {
|
||||
uint16_t i = 1;
|
||||
@ -149,14 +135,14 @@ void email_summary(void) {
|
||||
struct emailhdrs *h = headers;
|
||||
clrscr();
|
||||
while (h) {
|
||||
print_one_email_summary(i, h, (i == selection));
|
||||
print_one_email_summary(h, (i == selection));
|
||||
++i;
|
||||
h = h->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Show email summary for nth email message
|
||||
* Show email summary for nth email message in list of headers
|
||||
*/
|
||||
void email_summary_for(uint16_t n) {
|
||||
struct emailhdrs *h = headers;
|
||||
@ -165,7 +151,7 @@ void email_summary_for(uint16_t n) {
|
||||
putchar(0x19); // HOME
|
||||
for (j = 0; j < n - 1; ++j)
|
||||
putchar(0x0a); // CURSOR DOWN
|
||||
print_one_email_summary(n, h, (n == selection));
|
||||
print_one_email_summary(h, (n == selection));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -185,7 +171,7 @@ void email_pager(void) {
|
||||
uint8_t line, eof;
|
||||
char c;
|
||||
clrscr();
|
||||
sprintf(filename, "%s/EMAIL.%u", cfg_inboxdir, selection);
|
||||
sprintf(filename, "%s/EMAIL.%u", cfg_inboxdir, h->emailnum);
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
printf("Can't open %s\n", filename);
|
||||
@ -193,6 +179,8 @@ void email_pager(void) {
|
||||
cgetc();
|
||||
return;
|
||||
}
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET); // Skip over headers
|
||||
restart:
|
||||
clrscr();
|
||||
line = 6;
|
||||
@ -221,7 +209,7 @@ restart:
|
||||
++line;
|
||||
if (line == 22) {
|
||||
putchar(0x0f); // INVERSE
|
||||
printf("[%05lu] SPACE continue reading | B)ack | T)op | Q)uit", pos);
|
||||
printf("[%05lu] SPACE continue reading | B)ack | T)op | H)drs | Q)uit", pos);
|
||||
putchar(0x0e); // NORMAL
|
||||
retry1:
|
||||
c = cgetc();
|
||||
@ -231,7 +219,7 @@ retry1:
|
||||
case 'B':
|
||||
case 'b':
|
||||
if (pos < (uint32_t)(SCROLLBACK)) {
|
||||
pos = 0;
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
} else {
|
||||
@ -241,6 +229,12 @@ retry1:
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
pos = 0;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
@ -258,7 +252,7 @@ retry1:
|
||||
}
|
||||
} else if (eof) {
|
||||
putchar(0x0f); // INVERSE
|
||||
printf("[%05lu] *** END *** | B)ack | T)op | Q)uit", pos);
|
||||
printf("[%05lu] *** END *** | B)ack | T)op | H)drs | Q)uit", pos);
|
||||
putchar(0x0e); // NORMAL
|
||||
retry2:
|
||||
c = cgetc();
|
||||
@ -266,7 +260,7 @@ retry2:
|
||||
case 'B':
|
||||
case 'b':
|
||||
if (pos < (uint32_t)(SCROLLBACK)) {
|
||||
pos = 0;
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
} else {
|
||||
@ -276,6 +270,12 @@ retry2:
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
pos = h->skipbytes;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
pos = 0;
|
||||
fseek(fp, pos, SEEK_SET);
|
||||
goto restart;
|
||||
|
27
apps/email_common.h
Normal file
27
apps/email_common.h
Normal file
@ -0,0 +1,27 @@
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// EMAIL_COMMON.H
|
||||
// Definitions shared between pop65.c and email.c
|
||||
// Bobbi June 2020
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
// Configuration params from POP65.CFG
|
||||
char cfg_server[80]; // IP of POP3 server
|
||||
char cfg_user[80]; // Username
|
||||
char cfg_pass[80]; // Password
|
||||
char cfg_spooldir[80]; // ProDOS directory to spool email to
|
||||
char cfg_inboxdir[80]; // ProDOS directory for email inbox
|
||||
|
||||
// Represents the email headers for one message
|
||||
struct emailhdrs {
|
||||
uint16_t emailnum; // Name of file is EMAIL.n (n=emailnum)
|
||||
uint16_t skipbytes; // How many bytes to skip over the headers
|
||||
char date[40];
|
||||
char from[80];
|
||||
char to[80];
|
||||
char cc[80];
|
||||
char subject[80];
|
||||
#ifdef EMAIL_C
|
||||
struct emailhdrs *next; // Used in email.c only for linked list
|
||||
#endif
|
||||
};
|
||||
|
63
apps/pop65.c
63
apps/pop65.c
@ -6,7 +6,6 @@
|
||||
// Bobbi June 2020
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <dio.h>
|
||||
#include <cc65.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
@ -16,14 +15,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <device.h>
|
||||
|
||||
#include "../inc/ip65.h"
|
||||
#include "w5100.h"
|
||||
#include "w5100_http.h"
|
||||
#include "linenoise.h"
|
||||
|
||||
#include "email_common.h"
|
||||
|
||||
#define BACKSPACE 8
|
||||
|
||||
// Both pragmas are obligatory to have cc65 generate code
|
||||
@ -34,8 +33,8 @@
|
||||
#define NETBUFSZ 1500
|
||||
#define LINEBUFSZ 1000 // According to RFC2822 Section 2.1.1 (998+CRLF)
|
||||
#define READSZ 1024 // Must be less than NETBUFSZ to fit in buf[]
|
||||
|
||||
static unsigned char buf[NETBUFSZ+1]; // One extra byte for null terminator
|
||||
static char padding[1] = {0}; // Having an extra byte before linebuf[] helps
|
||||
static char linebuf[LINEBUFSZ];
|
||||
|
||||
char filename[80];
|
||||
@ -43,27 +42,10 @@ int len;
|
||||
FILE *fp;
|
||||
uint32_t filesize;
|
||||
|
||||
// Configuration params from POP65.CFG
|
||||
char cfg_server[80]; // IP of POP3 server
|
||||
char cfg_user[80]; // Username
|
||||
char cfg_pass[80]; // Password
|
||||
char cfg_spooldir[80]; // ProDOS directory to spool email to
|
||||
char cfg_inboxdir[80]; // ProDOS directory for email inbox
|
||||
|
||||
// Represents the email headers for one message
|
||||
struct emailhdrs {
|
||||
char date[80];
|
||||
char from[80];
|
||||
char to[80];
|
||||
char cc[80];
|
||||
char subject[80];
|
||||
};
|
||||
|
||||
/*
|
||||
* Keypress before quit
|
||||
*/
|
||||
void confirm_exit(void)
|
||||
{
|
||||
void confirm_exit(void) {
|
||||
printf("\nPress any key ");
|
||||
cgetc();
|
||||
exit(0);
|
||||
@ -72,16 +54,14 @@ void confirm_exit(void)
|
||||
/*
|
||||
* Called for all non IP65 errors
|
||||
*/
|
||||
void error_exit()
|
||||
{
|
||||
void error_exit() {
|
||||
confirm_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called if IP65 call fails
|
||||
*/
|
||||
void ip65_error_exit(void)
|
||||
{
|
||||
void ip65_error_exit(void) {
|
||||
printf("%s\n", ip65_strerror(ip65_error));
|
||||
confirm_exit();
|
||||
}
|
||||
@ -225,6 +205,8 @@ bool w5100_tcp_send_recv(char* sendbuf, char* recvbuf, size_t length,
|
||||
*++dataptr = data;
|
||||
|
||||
// TODO -- check we are not looking before start of recvbuf here!!
|
||||
// TODO -- this doesn't handle the case where the sequence is split across
|
||||
// packets!!!
|
||||
if (!memcmp(dataptr - 4, "\r\n.\r\n", 5))
|
||||
cont = 0;
|
||||
}
|
||||
@ -317,10 +299,10 @@ void readconfigfile(void) {
|
||||
|
||||
/*
|
||||
* Read a text file a line at a time leaving the line in linebuf[]
|
||||
* Returns 1 if line read, 0 if EOF.
|
||||
* Returns number of chars in the line, or -1 if EOF.
|
||||
* Converts line endings from CRLF -> CR (Apple ][ style)
|
||||
*/
|
||||
uint8_t get_line(FILE *fp) {
|
||||
int16_t get_line(FILE *fp) {
|
||||
static uint16_t rd = 0;
|
||||
static uint16_t buflen = 0;
|
||||
uint8_t found = 0;
|
||||
@ -329,6 +311,7 @@ uint8_t get_line(FILE *fp) {
|
||||
while (1) {
|
||||
for (i = rd; i < buflen; ++i) {
|
||||
linebuf[j++] = buf[i];
|
||||
// The following line is safe because j>=1 at this point
|
||||
if ((linebuf[j - 1] == '\n') && (linebuf[j - 2] == '\r')) {
|
||||
found = 1;
|
||||
break;
|
||||
@ -337,13 +320,12 @@ uint8_t get_line(FILE *fp) {
|
||||
if (found) {
|
||||
rd = i + 1;
|
||||
linebuf[j - 1] = '\0'; // Remove LF from end
|
||||
j = 0;
|
||||
return 1;
|
||||
return j - 2;
|
||||
}
|
||||
buflen = fread(buf, 1, READSZ, fp);
|
||||
if (buflen == 0) {
|
||||
rd = 0;
|
||||
return 0; // Hit EOF before we found EOL
|
||||
return -1; // Hit EOF before we found EOL
|
||||
}
|
||||
rd = 0;
|
||||
}
|
||||
@ -399,7 +381,7 @@ void write_next_email(uint16_t num) {
|
||||
*/
|
||||
void update_inbox(uint16_t nummsgs) {
|
||||
static struct emailhdrs hdrs;
|
||||
uint16_t nextemail, msg;
|
||||
uint16_t nextemail, msg, chars, headerchars;
|
||||
uint8_t headers;
|
||||
FILE *destfp;
|
||||
sprintf(filename, "%s/NEXT.EMAIL", cfg_inboxdir);
|
||||
@ -419,6 +401,7 @@ void update_inbox(uint16_t nummsgs) {
|
||||
printf("Can't open %s\n", filename);
|
||||
error_exit();
|
||||
}
|
||||
hdrs.emailnum = nextemail;
|
||||
sprintf(filename, "%s/EMAIL.%u", cfg_inboxdir, nextemail++);
|
||||
puts(filename);
|
||||
destfp = fopen(filename, "wb");
|
||||
@ -428,10 +411,13 @@ void update_inbox(uint16_t nummsgs) {
|
||||
error_exit();
|
||||
}
|
||||
headers = 1;
|
||||
while (get_line(fp)) {
|
||||
headerchars = 0;
|
||||
hdrs.skipbytes = 0; // Just in case it doesn't get set
|
||||
while ((chars = get_line(fp)) != -1) {
|
||||
if (headers) {
|
||||
headerchars += chars + 1; // Don't forget the LF we deleted
|
||||
if (!strncmp(linebuf, "Date: ", 6)) {
|
||||
copyheader(hdrs.date, linebuf + 6, 79);
|
||||
copyheader(hdrs.date, linebuf + 6, 39);
|
||||
hdrs.date[79] = '\0';
|
||||
}
|
||||
if (!strncmp(linebuf, "From: ", 6)) {
|
||||
@ -450,9 +436,12 @@ void update_inbox(uint16_t nummsgs) {
|
||||
copyheader(hdrs.subject, linebuf + 9, 79);
|
||||
hdrs.subject[79] = '\0';
|
||||
}
|
||||
if (linebuf[0] == '\r')
|
||||
//if (linebuf[0] == '\r') {
|
||||
if (strlen(linebuf) < 10) {
|
||||
headers = 0;
|
||||
} else
|
||||
hdrs.skipbytes = headerchars;
|
||||
}
|
||||
}
|
||||
fputs(linebuf, destfp);
|
||||
}
|
||||
fclose(fp);
|
||||
@ -468,8 +457,6 @@ void main(void) {
|
||||
uint16_t msg, nummsgs;
|
||||
uint32_t bytes;
|
||||
|
||||
padding[0] = 0; // To shut up warning
|
||||
|
||||
videomode(VIDEOMODE_80COL);
|
||||
printf("\nReading POP65.CFG -");
|
||||
readconfigfile();
|
||||
|
Loading…
Reference in New Issue
Block a user