#!python:python

"""
A CGI form mailer that supports binary file uploads and can send them
as MIME attachments. Requires Python 1.5.2 or higher.

$Id: formmail.py,v 1.4 2000/12/13 15:35:39 larsga Exp $
"""

OK = 0

try:
    import cgi, StringIO, string, smtplib, sys, MimeWriter, base64

    # Config

    mailserver     = "your.mail.server.here"
    mailrecip      = "you@your.domain"
    subject        = "Form data"
    error_file     = "/usr/data/cgi-data/error.html"
    error_string   = None
    success_file   = "/usr/data/cgi-data/success.html"
    success_string = None
    accept_recip_as_param = 1

    # NOTE: the script will use the string if it is present, otherwise
    # it will use the file.

    # Special form fields
    # EMAIL
    # REQUIRED
    # BINARY (comma-sep list of field names)

    # Create output control

    out = StringIO.StringIO()
    mail = MimeWriter.MimeWriter(out)
    mail.addheader("Subject", subject)

    # Process results

    form = cgi.FieldStorage()

    # Check that required fields are present

    if form.has_key("REQUIRED"):
        missing = []
        for field in string.split(form["REQUIRED"].value):
            if not form.has_key(field):
                missing.append(field)

        if missing != []:
            print "Content-type: text/html\n"

            missing = map(lambda field: "  <li>" + field, missing)
            missing = string.join(missing, "")

            if error_string:
                print error_string
            else:
                print open(error_file).read() % missing

            OK = 1
            sys.exit()

    # Set up the email

    if accept_recip_as_param and form.has_key("EMAIL"):
        mailrecip = form["EMAIL"].value

    mail.addheader("To", mailrecip)
    mail.addheader("From", mailrecip)

    # Quick check
    assert mailserver != "your.mail.server.here" and \
           mailrecip  != "you@your.domain"

    # Write email body

    if form.has_key("BINARY"):
	binary = string.split(form["BINARY"].value, ",")

	mail.startmultipartbody("mixed")
	for fieldname in form.keys():
	    if not fieldname in binary:
		continue

	    part = mail.nextpart()
	    part.addheader("Content-Transfer-Encoding", "base64")
	    part.addheader("Content-Disposition",
	                   'attachment;\n\tfilename="%s"' % fieldname)

	    fp = part.startbody('application/octet-stream;\n\t name="%s"' %
	                        fieldname)
	    fp.write(base64.encodestring(form[fieldname].value))

	part = mail.nextpart()
	fp = part.startbody("text/plain")
    else:
	binary = []
	fp = mail.startbody("text/plain")

    skip_fields = ["REQUIRED", "EMAIL", "BINARY"] + binary
    for fieldname in form.keys():
        if fieldname in skip_fields:
	    continue

	fp.write("---" + fieldname + ": \n")
        fp.write(form[fieldname].value + "\n\n")

    if binary:
	mail.lastpart()

    # Send email
    mail = smtplib.SMTP(mailserver)
    mail.sendmail(mailrecip, [mailrecip], out.getvalue())

    # Print confirmation

    print "Content-type: text/html\n"

    if success_string:
        print success_string
    else:
        print open(success_file).read()

    OK = 1
finally:
    if not OK:
        print "Content-type: text/plain\n"
        sys.stderr = sys.stdout
