File Coverage

blib/lib/CGI/Application/Mailform.pm
Criterion Covered Total %
statement 16 109 14.6
branch 0 30 0.0
condition 0 12 0.0
subroutine 5 14 35.7
pod 2 10 20.0
total 23 175 13.1


line stmt bran cond sub pod time code
1              
2             package CGI::Application::Mailform;
3              
4             # Always use strict!
5 1     1   105701 use strict;
  1         2  
  1         32  
6              
7              
8             # This is a CGI::Application module
9 1     1   698 use CGI::Application;
  1         3  
  1         44  
10             @CGI::Application::Mailform::ISA = qw/CGI::Application/;
11              
12              
13             # Required, but not enforced by Makefile.PL!
14 1     1   10 use Net::SMTP;
  1         2  
  1         46  
15 1     1   6 use Carp;
  1         2  
  1         1268  
16              
17              
18              
19             #############################################
20             ## OVERRIDE METHODS
21             ##
22              
23             # Run when new() is called
24             sub setup {
25 1     1 1 1 my $self = shift;
26              
27 1         4 $self->mode_param('rm');
28 1         3 $self->start_mode('showform');
29              
30             # Set up run-mode table. In a typical CGI::Application module, this would
31             # contain multiple run-modes -- one for each think your app can do.
32             # We're using sub-ref instead of name-ref to display more intuitive errors.
33             #
34 1         6 $self->run_modes(
35             'showform' => \&redirect_to_mailform,
36             'submitform' => \&submitform_and_sendmail,
37             );
38             }
39              
40              
41             # Called when run() is called.
42             sub cgiapp_prerun {
43 0     0 1   my $self = shift;
44 0           my $runmode = shift;
45              
46             # Make sure the instance script is correct
47 0           $self->validate_runtime();
48             }
49              
50              
51              
52             #############################################
53             ## RUN-MODE METHODS
54             ##
55              
56             sub redirect_to_mailform {
57 0     0 0   my $self = shift;
58              
59             # Set up the HTTP redirect
60 0           my $redirect_url = $self->param('HTMLFORM_REDIRECT_URL');
61              
62 0           return $self->do_redirect($redirect_url);
63             }
64              
65              
66             sub submitform_and_sendmail {
67 0     0 0   my $self = shift;
68              
69             # Actually send out the email message
70 0           $self->sendmail();
71              
72             # Set up the HTTP redirect
73 0           my $redirect_url = $self->param('SUCCESS_REDIRECT_URL');
74              
75 0           return $self->do_redirect($redirect_url);
76             }
77              
78              
79              
80             #############################################
81             ## PRIVATE METHODS
82             ##
83              
84             # Perform an HTTP redirect
85             sub do_redirect {
86 0     0 0   my $self = shift;
87 0           my $redirect_url = shift;
88              
89 0           $self->header_type( 'redirect' );
90 0           $self->header_props( -url => $redirect_url );
91              
92             # Return HTML to the web browser
93 0           my $redirect_html = "Continue: $redirect_url";
94 0           return $redirect_html;
95             }
96              
97              
98             # This method is to verify that the instance script (i.e., "mailform.cgi")
99             # contains the correct configuration parameters.
100             sub validate_runtime {
101 0     0 0   my $self = shift;
102              
103             ## CHECK REQUIRED PARAMETERS
104             #
105 0           my $req_failed = 0;
106              
107 0           my @required_params = qw/
108             MAIL_FROM
109             MAIL_TO
110             HTMLFORM_REDIRECT_URL
111             SUCCESS_REDIRECT_URL
112             FORM_FIELDS
113             /;
114              
115 0           foreach my $req_param (@required_params) {
116             # Check each req param to verify that it is there
117 0 0 0       unless ( defined($self->param($req_param)) && length($self->param($req_param)) ) {
118 0           $req_failed++;
119 0           carp("Required parameter '$req_param' not specified");
120             } else {
121             # Especially check that FORM_FIELDS is an array-ref
122 0 0 0       if (($req_param eq 'FORM_FIELDS') && (ref($self->param('FORM_FIELDS')) ne 'ARRAY')) {
123 0           $req_failed++;
124 0           carp("Required parameter 'FORM_FIELDS' is not an array reference");
125             }
126             }
127              
128             }
129              
130             # Die if we have an invalid run-time configuration
131 0 0         croak("Missing or invalid required parameters") if ($req_failed);
132              
133              
134             ## CHECK OPTIONAL PARAMETERS / SET DEFAULT VALUES
135             #
136 0           my $opt_failed = 0;
137              
138             ## ENV_FIELDS
139             # If undefined, define as null
140 0 0         $self->param('ENV_FIELDS', []) unless (defined($self->param('ENV_FIELDS')));
141              
142             # Now, check for validity
143 0 0         unless (ref($self->param('ENV_FIELDS')) eq 'ARRAY') {
144 0           $opt_failed++;
145 0           carp("Parameter 'ENV_FIELDS' is not an array reference");
146             }
147              
148             ## SUBJECT
149 0           my $subject = $self->param('SUBJECT');
150 0 0 0       unless (defined($subject) && length($subject)) {
151 0   0       $subject = 'Form submission from ' . ($ENV{HTTP_REFERER} || $ENV{SCRIPT_NAME});
152 0           $self->param('SUBJECT', $subject);
153             }
154              
155             ## SMTP_HOST
156 0 0         $self->param('SMTP_HOST', '') unless (defined($self->param('SMTP_HOST')));
157             # Expect a scalar for SMTP_HOST. Other values will be deemed errors,
158             # to prevent problems when interfacing with Net::SMTP.
159 0 0         unless (ref($self->param('SMTP_HOST')) eq '') {
160 0           $opt_failed++;
161 0           carp("Parameter 'SMTP_HOST' is not a scalar");
162             }
163              
164             # Die if we have an invalid run-time configuration
165 0 0         croak("Invalid optional parameters") if ($opt_failed);
166             }
167              
168              
169             # Establish SMTP connection
170             sub connect_smtp {
171 0     0 0   my $self = shift;
172              
173 0           my $smtp_host = $self->param('SMTP_HOST');
174              
175 0           my $smtp_connection;
176              
177 0 0         if (length($smtp_host)) {
178             # Use provided host
179 0           $smtp_connection = Net::SMTP->new($smtp_host);
180 0 0         croak("Unable to connect to '$smtp_host'")
181             unless (defined($smtp_connection));
182             } else {
183             # Use default host
184 0           $smtp_connection = Net::SMTP->new();
185 0 0         croak("Unable to establish SMTP connection")
186             unless (defined($smtp_connection));
187             }
188              
189 0           return $smtp_connection;
190             }
191              
192              
193             # This method actually generates and sends the email message via
194             # SMTP, or die()s trying.
195             sub sendmail {
196 0     0 0   my $self = shift;
197              
198             # Get the CGI query object
199 0           my $q = $self->query();
200              
201 0           my $mailfrom = $self->param('MAIL_FROM');
202 0           my $mailto = $self->param('MAIL_TO');
203 0           my $subject = $self->param('SUBJECT');
204              
205             # Get the message body
206 0           my $msgbody = $self->build_msgbody();
207              
208             # Connect to SMTP server
209 0           my $smtp_connection = $self->connect_smtp();
210              
211             # Here's where we "do the deed"...
212 0           $smtp_connection->mail($mailfrom);
213 0           $smtp_connection->to($mailto);
214              
215             # Enter data mode
216 0           $smtp_connection->data();
217              
218             # Send the message content (header + body)
219 0           $smtp_connection->datasend("From: $mailfrom\n");
220 0           $smtp_connection->datasend("To: $mailto\n");
221 0           $smtp_connection->datasend("Subject: $subject\n");
222 0           $smtp_connection->datasend("\n");
223 0           $smtp_connection->datasend($msgbody);
224 0           $smtp_connection->datasend("\n");
225              
226             # Exit data mode
227 0           $smtp_connection->dataend();
228              
229              
230             # Be polite -- disconnect from the server!
231 0           $smtp_connection->quit();
232             }
233              
234              
235             # Here's where the majority of the work gets done.
236             # Based on the settings in the instance script and
237             # the CGI form data, an email message body is created.
238             sub build_msgbody {
239 0     0 0   my $self = shift;
240              
241             # Get the CGI query object
242 0           my $q = $self->query();
243              
244             # The longest journey begins with a single step...
245 0           my $msgbody = '';
246              
247             ## Populate message body with form data
248             #
249 0           my $form_fields = $self->param('FORM_FIELDS');
250 0           my $ff_count = 1;
251 0           $msgbody .= "The following data has been submitted:\n\n";
252 0           foreach my $field (@$form_fields) {
253 0           $msgbody .= "$ff_count\. $field\:\n" . $self->clean_data($q->param($field)). "\n\n\n";
254 0           $ff_count++;
255             }
256 0           $msgbody .= "\n";
257              
258             ## Populate message body with environment data
259             #
260 0           my $env_fields = $self->param('ENV_FIELDS');
261             # Do we actually have any env data requested?
262 0 0         if (@$env_fields) {
263 0           my $ef_count = 1;
264 0           $msgbody .= "Form environment data:\n\n";
265 0           foreach my $field (@$env_fields) {
266 0           $msgbody .= "$ef_count\. $field\:\n" . $self->clean_data($ENV{$field}). "\n\n\n";
267 0           $ef_count++;
268             }
269             }
270              
271             # Send back the complete message body
272 0           return $msgbody;
273             }
274              
275              
276             # This method cleans up data for inclusion into the email message
277             sub clean_data {
278 0     0 0   my $self = shift;
279 0           my $field_data = shift;
280              
281             # Set undef strings to a null string
282 0 0         $field_data = '' unless (defined($field_data));
283              
284             # Strip leading & trailing white space
285 0           $field_data =~ s/^\s*//;
286 0           $field_data =~ s/\s$//;
287              
288             # If we have no answer, put "[n/a]" in there.
289 0 0         $field_data = '[n/a]' unless (length($field_data));
290              
291 0           return $field_data;
292             }
293              
294              
295              
296              
297              
298             #############################################
299             ## POD
300             ##
301              
302             =pod
303              
304             =head1 NAME
305              
306             CGI::Application::Mailform -
307             A simple HTML form to email system
308              
309              
310             =head1 SYNOPSIS
311              
312             ## In "mailform.cgi" --
313             use CGI::Application::Mailform;
314              
315             # Create a new Mailform instance...
316             my $mf = CGI::Application::Mailform->new();
317              
318             # Configure your mailform
319             $mf->param('MAIL_FROM' => 'webmaster@your.domain');
320             $mf->param('MAIL_TO' => 'form_recipient@your.domain');
321             $mf->param('HTMLFORM_REDIRECT_URL' => '/uri/or/url/to/mailform.html');
322             $mf->param('SUCCESS_REDIRECT_URL' => '/uri/or/url/to/thankyou.html');
323             $mf->param('FORM_FIELDS' => [qw/name address comments etc/]);
324              
325             # Optional variables
326             $mf->param('SMTP_HOST' => 'mail.your.domain');
327             $mf->param('SUBJECT' => 'New form submission');
328             $mf->param('ENV_FIELDS' => [qw/REMOTE_ADDR HTTP_USER_AGENT/]);
329              
330             # Now run...
331             $mf->run();
332             exit(0);
333              
334              
335            
336             ## In "mailform.html" --
337            
338            
339            
340            
341            
342              
343              
344              
345             ## In "thankyou.html" --
346            
347            

Thanks for your submission! It has been sent.

348            
349              
350              
351              
352             =head1 DESCRIPTION
353              
354             CGI::Application::Mailform is a reusable and customizable mailform
355             for the web. It is intentionally simple, and provides very few facilities.
356             What it does do is provide an easy-to-use, secure system for taking the contents
357             of a HTML form submission and sending it, via email, to a specified recipient.
358              
359             This module was created as an example of how to use CGI::Application, a
360             framework for creating reusable web-based applications. In addition to
361             providing a simple example of CGI::Application's usage,
362             CGI::Application::Mailform is also a fully functional application,
363             capable of running in a production environment.
364              
365             Just as is the case with any web-application built upon CGI::Application,
366             CGI::Application::Mailform will run on any web server and operating system
367             which supports the Common Gateway Interface (CGI). It will run equally
368             well on Apache as it runs on IIS or the iPlanet server. It will run
369             perfectly well on UNIX, Linux, Solaris or Windows NT. It will take full
370             advantage of the advanced capabilities of MOD_PERL. It will probably
371             even run under FastCGI (although the author has not personally tested it
372             in that environment).
373              
374              
375              
376             =head2 USAGE
377              
378             Once CGI::Application::Mailform has been installed, you must complete the
379             following steps to create a custom mailform on your website:
380              
381             1. Create 'mailform.html'
382             2. Create 'thankyou.html'
383             3. Create 'mailform.cgi'
384              
385             Examples of these files are provided in the directory "Examples"
386             which can be found in the installation tar file for CGI::Application.
387              
388              
389             =head2 Create 'mailform.html'
390              
391             The file 'mailform.html' is simply an HTML file which contains your web form.
392             This is the form whose contents will be sent, via CGI::Application::Mailform,
393             to the specified recipient's email address.
394              
395             This file need only contain the basic HTML form. There are two requirements
396             for this form. First, the "action" attribute of the
element must refer to the
397             CGI instance script ('mailform.cgi') you are about to create. Second,
398             the form must set a "hidden" form field with the name "rm" and the value "submitform".
399             This hidden parameter is what tells the CGI::Application::Mailform application to send the
400             email message, as opposed to send the user to the HTML form.
401              
402             For example:
403              
404            
405            
406            
407            
408              
409             Your 'mailform.html' may also contain JavaScript to provide form validation.
410             The CGI::Application::Mailform does not (currently) have any internal form
411             validation capabilities. As described earlier, this is a very simple system.
412             If it is necessary to enforce any fields as "required", it is recommended that
413             JavaScript be used.
414              
415             NOTE: It is not necessary that your HTML file be called 'mailform.html'.
416             You may name this file anything you like. The only naming limitation is that the name of this
417             file should be correctly referenced in your 'mailform.cgi', in the variable 'HTMLFORM_REDIRECT_URL'.
418              
419              
420              
421              
422             =head2 Create 'thankyou.html'
423              
424             The next file you need to create is your 'thankyou.html' file. This file is the
425             simplest of all. This is the file to which users will be redirected once they have
426             successfully submitted their form data. The purpose of this screen is to inform
427             and assure the user that their form data submission has been successfully received
428             and processed.
429              
430             For example:
431              
432            
433            
434             Thank you!
435            
436            
437            

Thanks for your submission!

438            

We have received your form, and

439             we will get back to you shortly.

440            
441            
442              
443             NOTE: It is not necessary that your HTML file be called 'thankyou.html'. You may name
444             this file anything you like. The only naming limitation is that the name of this
445             file should be correctly referenced in your 'mailform.cgi', in the variable 'SUCCESS_REDIRECT_URL'.
446              
447              
448              
449              
450             =head2 Create 'mailform.cgi'
451              
452             The file 'mailform.cgi' is where all the functionality of CGI::Application::Mailform
453             is configured. This file is referred to as a "CGI instance script" because it
454             creates an "instance" of your form. A single website may have as many instance
455             scripts as needed. All of these instance scripts may use CGI::Application::Mailform.
456             They may each use a different form (with different fields, etc.) if desired.
457             The ability to create multiple instances of a single
458             application, each with a different configuration is one of the benefits
459             of building web-based applications using the CGI::Application framework.
460              
461             Your instance script, 'mailform.cgi', must be created in such a way that it is
462             treated by your web server as an executable CGI application (as opposed to a
463             document). Generally (on UNIX), this entails setting the "execute bit" on the file and
464             configuring your web server to treat files ending ".cgi" as CGI applications.
465             Please refer to your particular web server's manual for configuration details.
466              
467             Your instance script 'mailform.cgi' must start with the following:
468              
469             #!/usr/bin/perl -w
470             use CGI::Application::Mailform;
471             my $mf = CGI::Application::Mailform->new();
472              
473             These lines invoke the Perl interpreter, include the CGI::Application::Mailform
474             module, and instantiate a Mailform object, respectively. (The
475             author assumes your Perl binary is located at "/usr/bin/perl". If it is not,
476             change the first line to refer to the correct location of your Perl binary.)
477              
478             Once you have a Mailform object ($mf), you have to configure the Mailform for your
479             particular application. This is done by using the param() method to set a number of
480             variables. These variables are specified as follows.
481              
482              
483              
484             B
485              
486              
487             =over 4
488              
489              
490             =item MAIL_FROM
491              
492             $mf->param('MAIL_FROM' => 'webmaster@your.domain');
493              
494             This variable specifies the email address from which the email created by this
495             mailform will appear to be sent. This can be any address you like.
496             Typically, this will be "webmaster@your.domain". Keep in mind, this is
497             the address to which a bounce or a reply will be sent if one is generated
498             as a result of the mailform email. The MAIL_FROM can also be useful for
499             assisting the recipient of these email messages in automatically filtering
500             and organizing the submissions they receive.
501              
502             This variable is required. If not specified, CGI::Application::Mailform
503             will die() with appropriate errors.
504              
505              
506             =item MAIL_TO
507              
508             $mf->param('MAIL_TO' => 'form_recipient@your.domain');
509              
510             This variable specifies the email address to which the email created by this
511             mailform should be sent. This should be the email address of the person to
512             whom the form contents should be emailed. This person will receive a
513             reasonably formatted message every time this mailform is submitted.
514              
515             This variable is required. If not specified, CGI::Application::Mailform
516             will die() with appropriate errors.
517              
518              
519             =item HTMLFORM_REDIRECT_URL
520              
521             $mf->param('HTMLFORM_REDIRECT_URL' => '/uri/or/url/to/mailform.html');
522              
523             This variable specifies the URL (or URI) to which the web user should be
524             redirected before they have submitted the mailform. This should be the
525             HTML form which the user fills out, the contents of which will be
526             emailed once they are submitted.
527              
528             This variable is required. If not specified, CGI::Application::Mailform
529             will die() with appropriate errors.
530              
531              
532             =item SUCCESS_REDIRECT_URL
533              
534             $mf->param('SUCCESS_REDIRECT_URL' => '/uri/or/url/to/thankyou.html');
535              
536             This variable specifies the URL (or URI) to which the web user should be
537             redirected once they have submitted the mailform. Typically, this would be
538             a "thank you" screen which assures the user that their form submission has
539             been received and processed.
540              
541             This variable is required. If not specified, CGI::Application::Mailform
542             will die() with appropriate errors.
543              
544              
545             =item FORM_FIELDS
546              
547             $mf->param('FORM_FIELDS' => [qw/name address comments etc/]);
548              
549             This variable specifies the list of HTML form fields which will be
550             processed and sent via email to the specified recipient. Only the
551             form fields specified in this list will be put in the email message
552             which is generated by this mailform and sent to the specified
553             recipient.
554              
555             The value of this variable must be an array reference.
556             This variable is required. If not specified, CGI::Application::Mailform
557             will die() with appropriate errors.
558              
559              
560              
561             =back
562              
563              
564             B
565              
566              
567             =over 4
568              
569              
570             =item SMTP_HOST
571              
572             $mf->param('SMTP_HOST' => 'mail.your.domain');
573              
574             This variable specifies the Internet host name (or IP address) of the
575             server which provides Simple Mail Transfer Protocol (SMTP) services.
576             CGI::Application::Mailform sends all mail via SMTP using Net::SMTP.
577              
578             If SMTP_HOST is unspecified, Net::SMTP will use the default host
579             which was specified when Net::SMTP was installed. If
580             CGI::Application::Mailform is unable to make an SMTP connection,
581             or successfully send mail via the SMTP host, it will die() with
582             appropriate errors.
583              
584              
585             =item SUBJECT
586              
587             $mf->param('SUBJECT' => 'New form submission');
588              
589             This variable specifies the subject line of the email message which is
590             created by this mailform. The subject is useful to the mailform recipient
591             in easily recognizing (and possibly filtering) form submissions.
592              
593             This variable is optional. If not supplied, CGI::Application::Mailform will
594             set the subject to a reasonable default.
595              
596              
597             =item ENV_FIELDS
598              
599             $mf->param('ENV_FIELDS' => [qw/REMOTE_ADDR HTTP_USER_AGENT/]);
600              
601             This variable specifies the list of "environment" variables which will be
602             processed and sent via email to the specified recipient. Only the
603             environment variables specified in this list will be put in the email message
604             which is generated by this mailform and sent to the specified
605             recipient.
606              
607             Any environment variable which is present in the CGI
608             environment may be included. Typical variables might be:
609              
610             AUTH_TYPE
611             CONTENT_LENGTH
612             CONTENT_TYPE
613             GATEWAY_INTERFACE
614             HTTP_ACCEPT
615             HTTP_USER_AGENT
616             PATH_INFO
617             PATH_TRANSLATED
618             QUERY_STRING
619             REMOTE_ADDR
620             REMOTE_HOST
621             REMOTE_IDENT
622             REMOTE_USER
623             REQUEST_METHOD
624             SCRIPT_NAME
625             SERVER_NAME
626             SERVER_PORT
627             SERVER_PROTOCOL
628             SERVER_SOFTWARE
629              
630             See your web server documentation for a complete list and descriptions
631             of the available environment variables. The list of environment variables
632             specified by the CGI protocol can be found at the following URL:
633              
634             http://hoohoo.ncsa.uiuc.edu/cgi/env.html
635              
636             The value of this variable must be an array reference. This variable
637             is optional. If not specified, no environment variables will be included
638             in the mailform email message.
639              
640             =back
641              
642              
643             Finally, you must actually cause your Mailform to be executed by calling the run()
644             method. Your instance script 'mailform.cgi' should end with the following lines:
645              
646             $mf->run();
647             exit(0);
648              
649             These lines cause your configured Mailform ($mf) to be executed, and for the program to
650             cleanly exit, respectively.
651              
652             NOTE: It is not necessary that your HTML file be called 'mailform.cgi'. You may name
653             this file anything you like. The only naming limitations are that this file should be
654             named so that your web server recognizes it as an executable CGI, and that your
655             'mailform.html' file specifies your instance script in the "action" attribute of the
656            
element.
657              
658              
659             All things considered, your CGI instance script will be a very small, simple file. Unlike
660             other reusable "mailform" scripts, the instance scripts are specifically intended to be
661             very easy to work with. Essentially, these instance scripts are "configuration files" for
662             your web-based application. The structure of instance scripts is a benefit of
663             building applications based on the CGI::Application framework.
664              
665              
666              
667             =head1 SEE ALSO
668              
669             L
670              
671              
672             =head1 AUTHOR
673              
674             Jesse Erlbaum
675              
676              
677             =head1 LICENSE
678              
679             Copyright (c) 2001, 2002, Jesse Erlbaum .
680              
681             This library is free software; you can redistribute it
682             and/or modify it under the same terms as Perl itself.
683              
684              
685              
686              
687             =cut
688              
689              
690              
691              
692             1;
693