#!/usr/bin/awk -f # # # pop3client # # Fetch e-mail from a POP3 server and submit it to the local # sendmail. # # # Some basic library functions I like to have around. # function skip_ws(line) { gsub(/^[ \t\r]+/, "", line); return (line); } function noctrl(line) { gsub(/[ \t\r]+$/, "", line); return (line); } function cfgetd(pop3, line) { if (pop3 |& getline line > 0) { line = noctrl(line); if (line == ".") return ("\001"); else if (substr(line, 1, 1) == ".") line = substr(line, 2); return (line); } return ("\001"); } function cfgets(pop3, line) { if (pop3 |& getline line > 0) { line = noctrl(line); if (debug != 0) printf (">>> %s\n", line) >>STDERR; return (line); } return ("\001"); } function cfputs(pop3, line) { line = noctrl(line); if (debug != 0) printf ("<<< %s\n", line) >>STDERR; printf ("%s\r\n", line) |& pop3; fflush(); return (0); } function cfputc(pop3, cmd, arg, result, k, rc, line) { if (cmd != "") { line = cmd; if (arg != "") line = cmd " " arg; cfputs(pop3, line); } line = cfgets(pop3); if ((k = index(line, " ")) == 0) rc = line; else rc = substr(line, 1, k-1); rc = toupper(rc); if (result != "" && rc != result) { printf ("%s: protocol error: %s\n", program, line) >>STDERR; exit (1); } return (line); } function spoolmail(pop3, num, receiver, maxsize, readonly) { $0 = cfputc(pop3, "LIST", num, "+OK"); if (($3+0) >= maxsize * 1024) { printf ("message %d too large: %d\n", num, $3); return (0); } if (verbose) printf ("getting message %d, %d bytes ...\n", num, $3); cfputc(pop3, "RETR", num, "+OK"); $0 = cfgets(pop3); sender = $2; pipe = "/usr/sbin/sendmail -oi " receiver; while ((line = cfgetd(pop3)) != "\001") { printf ("%s\n", line) | pipe; } close(pipe); if (readonly == 0) cfputc(pop3, "DELE", num, "+OK"); return (0); } function readprofile(filename, profile) { cmd = "/bin/ls -l " filename " 2>/dev/null"; if (cmd | getline <= 0) { printf ("%s: missing configuration file: %s\n", program, filename); exit (1); } close (cmd); if (substr($1, 5, 6) != "------") { printf ("%s: wrong permissions: %s\n", program, filename); exit (1); } section = profile ":"; len = length(section); while (getline 0) { gsub(/#.*$/, "", $0); if (substr($0, 1, len) == section) { while (getline 0) { gsub(/#.*$/, "", $0); if (NF == 0) break; if ($1 == "server") server = $2; else if ($1 == "username") username = $2; else if ($1 == "password") password = $2; } break; } } close (filename); if (server == "" || username == "" || password == "") { printf ("%s: incomplete configuration profile: %s\n", program, profile) >>STDERR; exit (1); } return (0); } function nextarg(par, arg) { if (argi >= ARGC) { printf ("%s: missing argument: %s\n", program, par) >STDERR; exit (1); } arg = ARGV[argi]; ARGV[argi++] = ""; return (arg); } BEGIN { STDERR = "/dev/stderr"; program = "pop3client"; debug = 0 verbose = 0; maxsize = 100; config = ENVIRON["HOME"] "/.pop3client"; argi = 1; while (argi < ARGC && substr(ARGV[argi], 1, 1) == "-") { options = nextarg("option"); if (options == "--") break; for (i = 2; i<=length(options); i++) { c = substr(options, i, 1); if (c == "c") config = nextarg("configuration file"); else if (c == "d") { debug = 1; readonly = 1; } else if (c == "r") readonly = 1; else if (c == "s") { maxsize = nextarg("maxsize") + 0; if (maxsize == 0) maxsize = 20; maxsize = maxsize; } else if (c == "v") verbose = 1; else { printf ("%s: unkown option: -%s\n", program, c) >STDERR; exit (1); } } } profile = nextarg("pop3 profile"); readprofile(config, profile); receiver = ENVIRON["LOGNAME"]; if (verbose) printf ("connecting to %s, user= %s\n", server, username) >>STDERR; pop3 = "/inet/tcp/0/" server "/110"; cfputc(pop3, "", "", "+OK"); cfputc(pop3, "USER", username, "+OK"); cfputc(pop3, "PASS", password, "+OK"); $0 = cfputc(pop3, "STAT", "", "+OK"); msgcount = $2+0; bytes = $3+0; if (verbose != 0) printf ("%d messages, %d bytes\n", msgcount, bytes) >>STDERR; for (i=1; i<=msgcount; i++) spoolmail(pop3, i, receiver, maxsize, readonly); if (readonly != 0) cfputc(pop3, "RSET", "", "+OK"); cfputc(pop3, "QUIT", "", "+OK"); exit (0); }