#!/usr/bin/python

# rmmail 0.0.1 (21 Feb 2002)
# Copyright (c) 2002 Hans-Georg Eer <h.g.esser@gmx.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import sys
from string import split
from re import match
import readline
from os import mkdir,environ
from os.path import isdir
# import ConfigParser


# BEGIN flags
deb_flag=0
verbose_flag=0
# END flags


# BEGIN init
def init():
    global fname, homedir
    try: homedir=environ["HOME"]
    except: homedir="/tmp"
    try: localmail=environ["MAIL"]
    except: localmail=""
    if len(sys.argv) > 2: print ("rmmail: Call with one or no argument."); sys.exit(1)
    if len(sys.argv) == 2:
        fname = sys.argv[1]
        if fname in ["-h","-H","--help"]:
            print """Syntax: rmmail [mailfolder]
Remove mails quickly.
If called without any arguments, rmmail tries to open the
users' incoming mail folder as set in $MAIL. rmmail knows
no arguments."""; sys.exit()            
    else:
        fname = localmail
# END init

# BGEIN debug
def debug(mesg):
    if deb_flag: print "debug:",mesg
# END debug


# BEGIN analyze
def analyze(filename):
    global lines, nummails, numberformat
    try: mbox=open(filename)
    except: print "rmmail: Could not open "+filename; sys.exit(1)
    
    lines=mbox.readlines()
    numlines=len(lines)
    mails=[]
    mail=-1
    i=0
    while i<=numlines:
        if i<numlines:
            line=lines[i]
        else:
            line=-1
        if line == -1 or line[:5] == "From ":
            mail=mail+1
            if i>0:
                end=i-1
                if verbose_flag:
                    print "MailNr: ", mail
                    print "Anfang: ", start
                    print "Ende:   ", end
                    print "From:   ", frm
                    print "To:     ", to
                    print "Subject:", sub
                    print
                mails.append([mail,1,start,end,frm,to,sub])
                
            start=i
            # search this message
            to_seek,from_seek,sub_seek=1,1,1
            while (to_seek or from_seek or sub_seek) and i<numlines-1:
                i=i+1
                if i >= numlines: debug("end of file")
                line=lines[i]
                if line[:5] == "From:":
                    frm=line[6:-1]
                    from_seek=0
                    debug("From found")
                if line[:3] == "To:":
                    to=line[4:-1]
                    to_seek=0
                    debug("To found")
                if line[:8] == "Subject:":
                    sub=line[9:-1]
                    sub_seek=0
                    debug("subject found")
                # handle possible "header missing" problem
                if line[:5] == "From ":
                    debug("Not complete")
                    if from_seek: frm="<No Sender>"; from_seek=0
                    if to_seek:   to ="<No Recipient>"; to_seek=0
                    if sub_seek:  sub="<No Subject>"; sub_seek=0
                    i=i-1
            # all headers read; now skip to end
            debug("2nd stage")
        i=i+1    
    mbox.close()
    nummails=mail
    if   nummails<10: numberformat="%1d"
    elif nummails>=10   and nummails<100:   numberformat="%2d"
    elif nummails>=100  and nummails<1000:  numberformat="%3d"
    elif nummails>=1000 and nummails<10000: numberformat="%4d"
    if verbose_flag: print "# Mails:", nummails
    return mails
# END analyze


# BEGIN simple_output
def simple_output(mail):
    print numberformat % (mail[0]),
    if mail[1]: print "[x] ",
    else: print "[ ] ",
    print "%-20s -> %-15s : %-30s" % (mail[4][:20],mail[4][:15],mail[6][:30])
# END simple_output


# BEGIN list
def list():
    for m in mails:
        simple_output(m)
    if len(mails) == 0: print "No mail."
# END list


# BEGIN preparse
def preparse(args):
    removelist=[]
    for arg in args:
        try:
            arg_int=int(arg)
            if arg_int<1 or arg_int>nummails: print "Non-existent Mail:",arg; removelist.append(arg)
        except:
            if match("[0-9]+-[0-9]+",arg):
                [num1,num2]=split(arg,"-")
                num1=int(num1); num2=int(num2)
                if num1>num2:
                    print "Wrong order in range",num1,"-",num2
                    removelist.append(arg)
                else:
                    for i in range(num1,num2+1):
                        if i in range(1,nummails+1): args.append(i)
                    removelist.append(arg)
            else: print "Wrong syntax."
    for arg in removelist:
        args.remove(arg)
    return
# ENDE preparse


# BEGIN delete_one
def delete_one(number):
    try: mails[number-1][1]=0
    except: print "Wrong Mail number",number-1
# END delete_one

# BEGIN delete
def delete(args):
    preparse(args)
    for arg in args:
        if verbose_flag: print "deleting", int(arg)
        delete_one(int(arg))
# END delete


# BEGIN undelete_one
def undelete_one(number):
    mails[number-1][1]=1
# END undelete_one

# BEGIN undelete
def undelete(args):
    preparse(args)
    for arg in args:
        print "undeleting", int(arg)
        undelete_one(int(arg))
# END undelete


# BEGIN write
def write():
    global mails
    out=open(fname,"w")
    if not isdir(homedir+"/.rmmail"): mkdir(homedir+"/.rmmail")
    deleted=open(homedir+"/.rmmail/deleted.mails","a")
    delno=0; saveno=0
    for mail in mails:
        if mail[1]:
            saveno=saveno+1
            for i in range(mail[2],mail[3]+1):
                out.write(lines[i]),
        else:
            delno=delno+1
            for i in range(mail[2],mail[3]+1):
                deleted.write(lines[i]),
    out.close()
    deleted.close()
    print delno,"Mails deleted; saved in "+homedir+"/.rmmail/deleted.mails"
    print saveno,"Mails saved in "+fname
    mails=analyze(fname)
    print fname+" reopened"
# END write


# BEGIN info
def info():
    print "Mail file: "+fname+" ("+str(nummails)+")"

# END info


# BEGIN interact
def interact():
    cmd=""
    while cmd <> "q":
        cmd_input = raw_input ("rmmail["+fname+"/"+str(nummails)+"]: ")
        cmdsplit = split(cmd_input, " ")
        cmd = cmdsplit[0]
        args = cmdsplit[1:]
        # selection of command
        if   cmd == "l": list()
        elif cmd == "i": info()
        elif cmd in ["h","H","?","help"]: print """rmmail help:
  l  list mails
  i  information
  o  open new mail folder
  d  delete mail(s)
  u  undelete mail(s)
  w  write (save changes)
  q  quit (ignore changes)
  h  show this help
Checked files [x] remain intact; unchecked files [ ] will
be deleted when a write command is issued."""
        elif cmd == "d": delete(args)
        elif cmd == "u": undelete(args)
        elif cmd == "o": print "open", args[0]; analyze(args[0])
        elif cmd == "w": write()
        elif cmd == "q": print "Exiting."
        elif cmd == "":  cmd=""
        else: print "Unknown command",cmd,"- try h for help."
# END interact


# BEGIN main
try:
    init()
    mails=analyze(fname)
    list()
    if len(mails) == 0: sys.exit()
    interact()
except KeyboardInterrupt:
    # Catch Ctrl-C and terminate properly
    print "\nrmmail terminates (ctrl-c). No changes made since last 'write'."
# END main
