/////////////////////////////////////////// // // POP3 Client // Bobbi June 2020 // // https://www.ietf.org/rfc/rfc1939.txt // /////////////////////////////////////////// #include #include #include #include #include #include #include #include #include "../inc/ip65.h" #define FILENAME "/H1/DOCUMENTS/EMAIL.TXT" char expected[80] = ""; volatile uint8_t await_response = 0; volatile uint8_t got_expected = 0; volatile uint8_t data_mode = 0; // Set to 1 when receiving body of email unsigned char buf[1500]; int len; FILE *fp; // Configuration params from POP65.CFG char cfg_server[80]; char cfg_user[80]; char cfg_pass[80]; void error_exit(void) { printf("- %s\n", ip65_strerror(ip65_error)); exit(EXIT_FAILURE); } void confirm_exit(void) { printf("\nPress any key "); cgetc(); } /* * Handle an incoming TCP message */ void __fastcall__ tcpcb(const uint8_t *tcp_buf, int16_t tcp_len) { int idx; await_response = 0; len = tcp_len; if (len != -1) { if (data_mode) { // printf("%d ", len); memcpy(buf, tcp_buf, len); buf[len] = 0; for (idx = 0; idx < len; ++idx) { if ((idx % 11) == 0) ip65_process(); if (buf[idx] != '\r') putchar(buf[idx]); } fwrite(buf, 1, len, fp); idx = strstr(buf, "\r\n.\r\n"); // CRLF.CRLF if (idx) { puts("Found end"); data_mode = 0; // If found, turn off data_mode fclose(fp); } return; } memcpy(buf, tcp_buf, len); buf[len-1] = 0; // HACK TO REMOVE DUPLICATE CR/LF printf("<%s", buf); if (strlen(expected) > 0) { #ifdef DEBUG printf("Expected:%s", expected); #endif if (strncmp(buf, expected, strlen(expected)) == 0) { got_expected = 1; #ifdef DEBUG printf(" match\n"); #endif } else { got_expected = 0; #ifdef DEBUG printf(" NO match\n"); #endif } } else got_expected = 1; } } /* * Check gotexpected flag and quit if false */ void checkgotexpected(void) { int i; while (await_response == 1) { #ifdef DEBUG putchar('.'); #endif ip65_process(); for (i = 0; i < 20000; ++i); } if (!got_expected) { printf("Didn't get expected response\n"); error_exit(); } else putchar('.'); } /* * Send a TCP message * msg - string to send * expect - sting to expect (or empty string) */ void sendmessage(char *msg, char *expect) { strcpy(expected, expect); if (strncmp(msg, "PASS", 4) == 0) printf(">PASS ****\n"); else printf(">%s", msg); if (tcp_send(msg, strlen(msg))) { error_exit(); } await_response = 1; ip65_process(); } void readconfigfile(void) { fp = fopen("POP65.CFG", "r"); if (!fp) { puts("Can't open config file POP65.CFG"); error_exit(); } fscanf(fp, "%s", cfg_server); fscanf(fp, "%s", cfg_user); fscanf(fp, "%s", cfg_pass); fclose(fp); } int main(void) { uint8_t eth_init = ETH_INIT_DEFAULT; char sendbuf[80]; uint16_t msg, nummsgs; uint32_t bytes; if (doesclrscrafterexit()) { atexit(confirm_exit); } videomode(VIDEOMODE_80COL); printf("\nReading POP65.CFG -"); readconfigfile(); printf(" Ok"); #ifdef __APPLE2__ { int file; printf("\nSetting slot -"); file = open("ethernet.slot", O_RDONLY); if (file != -1) { read(file, ð_init, 1); close(file); eth_init &= ~'0'; } printf(" %d\n", eth_init); } #endif printf("Initializing -"); if (ip65_init(eth_init)) { error_exit(); } printf(" Ok\nObtaining IP address -"); if (dhcp_init()) { error_exit(); } printf(" Ok\nConnecting to %s -", cfg_server); if (tcp_connect(parse_dotted_quad(cfg_server), 110, tcpcb)) { error_exit(); } printf(" Ok\n\n"); strcpy(expected, "+OK"); ip65_process(); await_response = 1; checkgotexpected(); sprintf(sendbuf, "USER %s\n", cfg_user); sendmessage(sendbuf, "+OK"); ip65_process(); checkgotexpected(); sprintf(sendbuf, "PASS %s\n", cfg_pass); sendmessage(sendbuf, "+OK Logged in."); ip65_process(); checkgotexpected(); sendmessage("STAT\n", "+OK"); ip65_process(); checkgotexpected(); sscanf(buf, "+OK %u %lu", &nummsgs, &bytes); printf(" %u message(s), %lu total bytes\n", nummsgs, bytes); for (msg = 1; msg <= nummsgs; ++msg) { data_mode = 1; remove(FILENAME); fp = fopen(FILENAME, "wb"); if (!fp) { printf("Can't open %s\n", FILENAME); error_exit(); } sprintf(sendbuf, "RETR %d\n", msg); sendmessage(sendbuf, ""); do { ip65_process(); } while (data_mode == 1); } sendmessage("QUIT\n", "+OK Logging out."); ip65_process(); checkgotexpected(); printf(" Ok\nClosing connection -"); if (tcp_close()) { error_exit(); } printf(" Ok\n\n"); return EXIT_SUCCESS; }