CGI email script

B

bojanraic

Hi!

I recently started playing with Python CGI, and I was happy that my
basic input-name--print-hello-name CGI form example worked, so I
thought I should advance to somew\hat more complicated scripts.

I'm trying to write a basic Python email CGI script to send email
through HTML email form.
I've seen a lot of examples out there, but nothing I tried so far
seemed to work. So I would like to know what I am doing wrong.

Here's the HTML form file:

<html>

<head>
<title>Email Form</title>
</head>

<body>

<FORM METHOD="POST" ACTION="sendMail.cgi">
<INPUT TYPE=HIDDEN NAME="key" VALUE="process">
Your name:<BR>
<INPUT TYPE=TEXT NAME="name" size=60>
<BR>
Email:<BR>
<INPUT TYPE=TEXT NAME="email" size=60>
<BR>
<P>
Comments:<BR>
<TEXTAREA NAME="comment" ROWS=8 COLS=60>
</TEXTAREA>
<P>
<INPUT TYPE="SUBMIT" VALUE="Send">
</FORM>

</body>

</html>

Here's the CGI script:

#!/usr/bin/python

import cgitb
cgitb.enable()
import cgi
import smtplib

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

def main():
form = cgi.FieldStorage()
if form.has_key("name") and form["name"].value != "":
fromaddress = form["email"].value
toaddress = (e-mail address removed)
message = form["comment"].value

server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddress, toaddress, message)
server.quit()

print "<html><head><title>Sent</title></head>"
print "<body><h1 align=center>",
print "<p>Your message has been sent!</body>"
print "</html>"

if __name__ == '__main__': main()



Of course, I change the email address to my own.
I keep getting the premature end of script headers error.

Several questions:

1. server = smtplib.SMTP('localhost') should return the name of the
server, right? I don't need to explicitly name it, or do I?
2. cgitb.enable() - shouldn't that give me a trace back if something
goes wrong so I can debug the code? It doesn't seem to give me
anything...
3. What am I doing wrong here? How can I fix the errors and make it
work?

Please understand that I have read all the previous questions on this
matter, and when I tried to follow the instructions, none of them
seemed to work for me.

Any help will be greatly appreciated.
 
K

Kent Johnson

I'm trying to write a basic Python email CGI script to send email
through HTML email form.
I've seen a lot of examples out there, but nothing I tried so far
seemed to work. So I would like to know what I am doing wrong.
#!/usr/bin/python

import cgitb
cgitb.enable()
import cgi
import smtplib

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

This line should be inside main() so it is printed each time the script
runs (OK maybe for a CGI it doesn't matter...), and it should have two
\n - you need a blank line between the HTTP headers and the body.
def main():
form = cgi.FieldStorage()
if form.has_key("name") and form["name"].value != "":
fromaddress = form["email"].value
toaddress = (e-mail address removed)
message = form["comment"].value

server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddress, toaddress, message)

Strangely enough, the message actually has to include the from and to
addresses as well. Try something like this:
msg = '''From: %s
To: %s
Subject: Test
%s
''' % (fromaddress, toaddress, message)

server.sendmail(fromaddress, toaddress, message)
server.quit()

print "<html><head><title>Sent</title></head>"
print "<body><h1 align=center>",
print "<p>Your message has been sent!</body>"
print "</html>"

if __name__ == '__main__': main()



Of course, I change the email address to my own.
I keep getting the premature end of script headers error.

Several questions:

1. server = smtplib.SMTP('localhost') should return the name of the
server, right? I don't need to explicitly name it, or do I?

You should pass the name of the SMTP server, is that on your local machine?

Kent
 
J

Jeffrey Froman

1. server = smtplib.SMTP('localhost') should return the name of the
server, right? I don't need to explicitly name it, or do I?

It returns an SMTP object to the machine known by the name "localhost". Most
machines are configured to think of themselves as "localhost".

3. What am I doing wrong here? How can I fix the errors and make it
work?

One way to investigate the error would be to pass the form parameters
directly, rather than through cgi.FieldStorage, running the script from the
command line to see any tracebacks.

Jeffrey
 
J

Jeffrey Froman

Kent said:
Strangely enough, the message actually has to include the from and to
addresses as well.

The From: and To: headers do not need to be in the message for SMTP to work.
The mail would still be delivered normally without them, but the message
will arrive appearing at first glance to be from nobody, and to nobody. A
close look at the full Received: headers may reveal at least the intended
recipient.

Jeffrey
 
D

Dennis Lee Bieber

(e-mail address removed) wrote:

This line should be inside main() so it is printed each time the script
runs (OK maybe for a CGI it doesn't matter...), and it should have two
\n - you need a blank line between the HTTP headers and the body.

Uhmmm... Doesn't the "print" itself emit a newline? If so, only
the single explicit newline is needed to get the double spacing.


--
 
S

Steve Holden

Hi!

I recently started playing with Python CGI, and I was happy that my
basic input-name--print-hello-name CGI form example worked, so I
thought I should advance to somew\hat more complicated scripts.

I'm trying to write a basic Python email CGI script to send email
through HTML email form.
I've seen a lot of examples out there, but nothing I tried so far
seemed to work. So I would like to know what I am doing wrong.

Here's the HTML form file:

<html>

<head>
<title>Email Form</title>
</head>

<body>

<FORM METHOD="POST" ACTION="sendMail.cgi">
<INPUT TYPE=HIDDEN NAME="key" VALUE="process">
Your name:<BR>
<INPUT TYPE=TEXT NAME="name" size=60>
<BR>
Email:<BR>
<INPUT TYPE=TEXT NAME="email" size=60>
<BR>
<P>
Comments:<BR>
<TEXTAREA NAME="comment" ROWS=8 COLS=60>
</TEXTAREA>
<P>
<INPUT TYPE="SUBMIT" VALUE="Send">
</FORM>

</body>

</html>

Here's the CGI script:

#!/usr/bin/python

import cgitb
cgitb.enable()
import cgi
import smtplib

print "Content-type: text/html\n"
It's conventional, though I believe strictly unnecessary, to include a
carriage return in the terminator sequence "Content ... \r\n". Of course
your Python system will take platform specific action with the line
ending *it* inserts, of course :)
def main():
form = cgi.FieldStorage()
if form.has_key("name") and form["name"].value != "":
fromaddress = form["email"].value
toaddress = (e-mail address removed)

Well, this is certainly an error, because "toaddress" should be a list
of addresses (allowing you to send the same message to more than one
person - usually you'd include everyone in the "From:", "Cc:" and "Bcc:"
headers). I'm presuming you just forgot the quotes when you erased your
own email address. What you probably want here is

toaddress = ["(e-mail address removed)"]

or whatever. The "invalid" top-level domain is always the best one to
use when you want to be sure you aren't using a real address.
message = form["comment"].value
here you really do need to be including some SMTP headers in your mail,
though a lot of mailers will be quite forgiving about this. I'd probably
use something like

message = """\
From: %s
To: %s
Subject: A message from your web site

%s
""" % (fromaddress, toaadress[0], form["comment"].value
server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddress, toaddress, message)
server.quit()

print "<html><head><title>Sent</title></head>"
print "<body><h1 align=center>",
print "<p>Your message has been sent!</body>"
print "</html>"

if __name__ == '__main__': main()



Of course, I change the email address to my own.
I keep getting the premature end of script headers error.

Several questions:

1. server = smtplib.SMTP('localhost') should return the name of the
server, right? I don't need to explicitly name it, or do I?

Most systems will resolve localhosts to 127.0.0.1, so as long as your
web server runs an SMTp server as well this will work.
2. cgitb.enable() - shouldn't that give me a trace back if something
goes wrong so I can debug the code? It doesn't seem to give me
anything...

cgitb.enable() does try to produce output, but in this case you will
probably only be able to see it in your server's error log. That's a
sign that the error's occurring very early on int he sequence, which is
puzzling. Of course, if your web server's Python is old enough not to
*implement* cgitb then this would account for the error you are actually
seeing.
3. What am I doing wrong here? How can I fix the errors and make it
work?
Well, there are a few things to try here.
Please understand that I have read all the previous questions on this
matter, and when I tried to follow the instructions, none of them
seemed to work for me.

Any help will be greatly appreciated.

done-my-best-ly y'rs - steve
 
M

Michael Foord

server.set_debuglevel(1)

Note that this line will cause debug messages to be printed before the
start of your HTML.

I've done a set of three functions for sending mail from CGI - one of
them should work ! I usually end up using the sendmailme function,
which isn't cross platform.

import os
import sys

SENDMAIL = "/usr/sbin/sendmail" # location of sendmail on
the server

#############################################################
# Three alternative methods of sending email
# Which one works will depend on your server setup.

def mailme(to_email, email_subject, msg, from_email=None,
host='localhost'):
"""A straight email function using smtplib.
With localhost set as host, this will work on many servers.
"""
head = "To: %s\r\n" % to_email
if from_email:
head = head + ('From: %s\r\n' % from_email)
head = head + ("Subject: %s\r\n\r\n" % email_subject)
msg = head + msg
import smtplib
server = smtplib.SMTP(host)
server.sendmail(from_email, [to_email], msg)
server.quit()


def sendmailme(to_email, email_subject, msg, from_email=None,
sendmail=SENDMAIL ):
"""Quick and dirty, pipe a message to sendmail.
Can only work on UNIX type systems with sendmail.
Will need the path to sendmail - can be specified in the
'SENDMAIL' default (see top of this script).
"""
o = os.popen("%s -t" % sendmail,"w")
o.write("To: %s\r\n" % to_email)
if from_email:
o.write("From: %s\r\n" % from_email)
o.write("Subject: %s\r\n" % email_subject)
o.write("\r\n")
o.write("%s\r\n" % msg)
o.close()

def loginmailme(to_email, email_subject, msg, host, user, password,
from_email=None ):
"""Email function for an smtp server you need to login to.
Needs hostname, username, password etc.
"""
head = "To: %s\r\n" % to_email
if from_email:
head = head + ('From: %s\r\n' % from_email)
head = head + ("Subject: %s\r\n\r\n" % email_subject)
msg = head + msg

import smtplib
server = smtplib.SMTP(host)
server.login(user, password)
server.sendmail(from_email, [to_email], msg)
server.quit()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top