Basic setup

To just get a basic form that can be used to send mail, simply install the Cookbook:PmForm module and then add the following lines to a local customization file (e.g., local/config.php):

$EnablePmFormMailSubjectEncode = 1; # for international sites
$PmForm['maildemo'] = ' form=#mailform fmt=#mailpost';

(for multiple addresses, use quotes around all of them and commas in between)

$PmForm['maildemo'] = 'mailto=",," form=#mailform fmt=#mailpost';

Then, wherever you want a form to appear to send mail to, use the directive

(:pmform maildemo:)

The "maildemo" portion of this directive is called the target, and it indicates that the mail is to be sent according to the options given by the corresponding entry in the $PmForm array. Within the 'maildemo' entry, "mailto=" specifies the recipient address for the email, "form=" specifies the form template to be displayed by the (:pmform maildemo:) directive, and "fmt=" specifies the template for the email to be sent.

Example pmform directive
(:pmform maildemo:)
Your address:


The above mailform actually works -- see mailform.txt to see what the mail looked like when it was received.

Customized templates

The "form=" and "fmt=" options specify pages or page sections to be used for displaying the form and formatting the form output. If only a section identifier is given (e.g., "form=#mailform"), then PmForm looks in the Site.PmFormTemplates and Site.LocalTemplates pages for the template.

The "form=" option specifies the template to use for the form displayed by the (:pmform:) directive. Usually this is built using PmWiki's (:input:) directives.

(:template defaults successpage='' :)
(:input pmform target={$$target} successpage={$$successpage} :)
(:input default request=1:)
||$[Your address]: ||(:input text from size=30:) ||
||$[Subject]:      ||(:input text subject size=30:) ||
(:input textarea text rows=8 cols=60:)\\
{$Captcha} (:input captcha:) \\
(:input submit name=post value='$[Send]':)
(:input end:)

The (:input pmform:) line specifies that this is a form to be handled by the PmForm module, and that it's to process the form according to whatever target was given by the (:pmform:) directive. Here, the form contains three fields to be filled in by the sender: the sender's address ("from"), the message subject ("subject"), and the text of the message itself ("text").

The "fmt=" option specifies the template to use for sending the email based on the inputs provided by the form. For example, the #mailform template that comes with PmForm contains:

(:template require from errmsg="$[Missing 'from' address]" :)
(:template require subject errmsg="$[Missing message subject]" :)
(:template require text errmsg="$[Message text required]" :) 
(:template require if="captcha" errmsg="$[Captcha required]" :)


Sent via PmForm at {$$PageUrl}

The (:template require:) directives are used to specify certain conditions that must be met before the mail can be set. For the above, this template requires that the "from", "subject", and "text" fields supplied by the sender are non-empty (and specifies error messages to display if they aren't).

The remainder of the template specifies the body of the email to be sent by PmForm. The {$$text} field is replaced by the message text coming from the input form, and {$$PageUrl} is substituted with the url to the current page. (The "from" and "subject" fields are automatically handled by PmForm.:)

The {$$...} template substitutions may contain any arbitrary page variables or input fields coming from the form.


Is it possible to put the "form=" and "fmt=" parameters directly into the (:pmform:) directive? (so that modifying the local configuration file is not necessary)

Blues May 23, 2007, at 03:20 AM

I just took a quick look at the code, and it doesn't seem to support that. However, it does seem that the target name can be the name of a text field on the page. (I'm not sure if thats the source page or the target page though), so that one should be able to do something like:

(:pmform foo:)
foo: form=#mailform fmt=#mailpost

and have that work.

StirlingWestrup September 13, 2007, at 09:12 AΜ
Define email in LocalTemplates page
After messing around, adapting the config file with PmFormPageFmt, allowed me to define the target in the LocalTemplates page.
$PmFormPageFmt = 'Site.LocalTemplates';
Damien December 11, 2009, at 02:08 AM

To provide some very basic email validity testing (which is better than none), change line 151 of pmform.php from

$errors = PmFormMail($pagename, $msgtmpl, $opt, $safe_opt);


if (strpos($opt['from'],'@')) $errors = PmFormMail($pagename, $msgtmpl, $opt, $safe_opt);
else $errors = "Please enter a valid email address.";

Ben Stallings December 08, 2008, at 07:33 PM

I (think I) followed the PmForm. instructions, beside of that I didn't create my own lib directory (files are hosted in /wikilib.d/ and /wiki.d/) - and I've omitted the Captcha install, setup and relevant form fields. As we are using PmForm in our Uniserver (XAMPP lite) Cookbook:Standalone Intranet Enterprise Wiki, we don't need Spam protection. (Update 2011-12-17 14:19 - Captcha installed, but it still doesn't work. John Doe is to blame)

After setting up several Mail forms: Everything is there, but no Mails are being sent. Here's my config.php

$PmForm['webmaster'] = 'subject="E-Mail von '.$WikiTitle.'" form=#wemaform fmt=#wemapost';


Dec 17 13:08:45 tls=on auth=on smtpstatus=535 smtpmsg='535 5.0.0 Authentication Failed' 
errormsg='authentication failed (method PLAIN)' exitcode=EX_NOPERM

Do I have to modify php.ini (sendmail_from = no value), anything else? Thanks much for your time and effort, and please excuse my lack of programmer skills! Jazzvox 2011-12-17 14:19

How can I add a replyto address to the emails sent from the server. I don't want the "From" field to be the email the form is submitted from (in case malformed or malicious) — but it would be convenient to stop sending emails back to my server instead of the intended recipient when I reply :) So I want the replyto to be the email sent in the contact form on the website. XES August 16, 2020, at 11:04 PM

You need to set the Reply-To address in the variable $PmFormMailHeaders. If your form field containing the e-mail is "visitor_email", you could do:

if(@$_POST['action'] == 'pmform' &&
  filter_var(@$_POST['visitor_email'], FILTER_VALIDATE_EMAIL)) {
  $PmFormMailHeaders = "Reply-To: {$_POST['visitor_email']}\r\n";

See filter_var() and mail(). --Petko August 17, 2020, at 07:03 AM

You should also use the new input type "email" for a browser-validated field (:input email required=required:) -- not 100% certain but will work for almost all real people by preventing the submission with an invalid or empty address field. --Petko August 17, 2020, at 04:46 PM

 0: 00.00 00.00 config start
 1: 00.01 config end
 2: 00.20 MarkupToHTML begin
 3: 00.20 MarkupToHTML begin
 4: 00.21 MarkupToHTML end
 5: 00.25 ReadApprovedUrls SiteAdmin.ApprovedUrls begin
 6: 00.25 ReadApprovedUrls SiteAdmin.ApprovedUrls end
 7: 00.30 MarkupToHTML end
 8: 00.30 MarkupToHTML begin
 9: 00.32 MarkupToHTML end
10: 00.32 MarkupToHTML begin
11: 00.32 MarkupToHTML end
12: 00.32 now