#!/usr/local/bin/kermit +

; http://www.faqs.org/rfcs/rfc1939.html

; p o p 3  --  POP3 mail retrieval
;
; This kermit script retrieves mail from a POP3 server and appends it
; to a local mailbox file.  The protocol is defined in rfc 1939.

; It accepts one optional argument which is the word "delete".  If
; "delete" is specified, the server is asked to delete the messages
; as they are retrieved.  Otherwise, the server is not asked to delete
; them and they will be retained.

; Any errors or unexpected responses from the server will cause the
; script to quit with an appropriate message.  If the script had
; succeeded in logging in to the server, it will request the server
; to abandon any changes before quitting.

; If no errors occur, the script reports the number of messages
; retrieved and exits normally.

; in this version, the identity of the POP3 server is built in,
; the local mailbox is taken from the environment, the userid is
; taken from the kermit variable and the password is requested
; interactively.  Of course, any of these things could be done
; differently depending on specific needs.

; This script precedes each appended message with a "From " line
; containing the current date and time and a hyphen for the source.
; this seems compatible with most mail user programs.

; Mark Sapiro, San Francisco Bay Area, California, September 2001

.pophost = mail.value.net
.mailbox := \$(MAIL)

; check kermit version
if < \v(version) 700000 -
  exit 1 \%0: C-Kermit 7.0 or later required.

if not writeable \m(mailbox) exit 1 \%0: \m(mailbox) not writeable.

; macro to check the status response from the POP3 server
;  2 args, \%1 is a string saying what we're doing used in error message
;          \%2 is a label to go to if there is an error
;  The server's response is in \v(input)
define ckstat {
	.popstat := \fsubst(\v(input),1,3)

	switch \m(popstat) {
		:+OK, break
		:-ER, echo Error response to \%1: \v(input), goto \%2
		:default, echo Unknown response to \%1: \v(input), goto \%2
	}
}

.delsw = 0	; assume no delete, then check
if defined \%2 exit 1 Usage: \%0 [delete]
if defined \%1 {
	if equal {\%1} {delete} .delsw = 1
        else exit 1 Usage: \%0 [delete]
}

fopen /append \%c \m(mailbox)  ; open mailbox first
if fail exit 1 Can't open \m(mailbox) for appending

askq passwd {Password for \v(userid) on \m(pophost):}

;  format a date-time for the From line, e.g. {Sat Sep 29 16:42:06 2001}
if > \fword(\v(date),1) 9 {
	.datime := {\v(day) \fword(\v(date),2) -  ; one space, 2 digits
\fword(\v(date),1) \v(time) \fword(\v(date),3)}
} else {
	.datime := {\v(day) \fword(\v(date),2)  - ; two spaces, one digit
\feval(\fword(\v(date),1)) \v(time) \fword(\v(date),3)}
; \feval above removes possible leading zero from one digit "day of month"
}

set host \m(pophost) pop3 /raw
if fail exit 1 Can't open \m(pophost)

set input echo off

clear input
input -1 \13\10
ckstat connect giveup

output USER \v(userid)\13\10

clear input
input -1 \13\10
ckstat USER giveup

output PASS \m(passwd)\13\10

clear input
input -1 \13\10
ckstat PASS giveup

;  Now in Transaction state

output STAT\13\10	; get message count

clear input
input -1 \13\10
ckstat STAT reset

.msgcnt := \fword(\v(input),2)

if = \m(msgcnt) 0 goto fini

for \%m 1 \m(msgcnt) 1 {
	output RETR \%m\13\10

	clear input
	input -1 \13\10
	ckstat RETR reset

	fwrite /line \%c {From - \m(datime)}	; write a From line
	if fail {echo fwrite failed, goto reset}

	clear input
	input -1 \13\10

	while not equal {\v(input)} {.\13\10} {
		.line := \ftrim(\v(input),\13\10)
		.\%l := \flength(\m(line))

		;	strip leading "." from ".." lines

		if > \%l 1 {
			if equal {.} {\fsubstring(\m(line),1,1)} {
				.line := \fsubstring(\m(line),2,\%l - 1)
			}
		}
		fwrite /line \%c \m(line)
		if fail {echo fwrite failed, goto reset}
		clear input
		input -1 \13\10
	}
	if = \m(delsw) 1 {
		output DELE \%m\13\10

		clear input
		input -1 \13\10
		ckstat DELE reset
	}
}

:fini
fclose \%c
output QUIT\13\10
input -1 \13\10
close connection
exit 0 Normal Termination: \m(msgcnt) messages

:reset
output RSET\13\10
input -1 \13\10
goto giveup

:giveup
output QUIT\13\10
input -1 \13\10
close connection
exit 1 Quitting
