The following describes how I used eForm events to produce a form with a selection list for subjects, with messages being sent to different recipients depending on the selected subject. It’s possible to do this without extending eForm (using the
&mailselector parameter), but I wanted to keep the recipient data in a template variable to make updating easier. This is a follow-up to the thread at
http://modxcms.com/forums/index.php/topic,44803.0.html.
Apart from the multiple-selection + recipient aspect, the "one or other field must be completed" validation and the elementary non-CAPTCHA anti-spam technique may prove useful when generating forms.
Snippet call:
[!eFormExtenders?!]
[!eForm? &formid=`contactForm` &tpl=`pkMessageForm` &noemail=`0` &eFormOnValidate=`valext` &subject=`((cSubject)) (from XYZ website)` &report=`pkResponseMessage` &eFormOnBeforeMailSent=`sendMessage` &eFormOnBeforeFormMerge=`setMessages` &sendirect=`1` &debug=`0`!]
This uses eForm extender functions
&eFormOnValidate,
&eFormOnBeforeFormMerge and
&eFormOnBeforeMailSent. Note also
&sendirect=`1` to specify that a field called
email be used for the "to" address, not the
&to parameter or site config’s email address.
Snippet
eFormExtenders (see note at end re validation)
<?php
// extra handling for eForm
include $modx->config["base_path"].'assets/snippets/eform/extenders.php';
return;
?>
extenders.php:
<?php
/* extensions to eForm for Contacts page emails to different addresses */
function setMessages(&$fields) {
/* set up options for dropdown list held in chunk rhMessageList
save messages in placeholder for use by sendMessage */
global $modx;
$options = explode('||',$modx->getChunk('rhMessageList'));
$select = "\t" . '<span class="edLabel"> </span>';
$select .= "\t" . '<span class="edField">';
$select .= "\t" . '<select name="messageType" id="messageType" size="1">' . "\n";
foreach ($options as $option) {
$item = explode('==', $option);
$select .= "\t" . '<option value="' . $item[1] . '"';
$select .= ($item[1] == 0) ? 'selected="selected"' : NULL;
$select .= '>' . $item[0] . "</option>\n";
}
$select .= "\t</select>\n\t</span>\n";
$fields['rhMessageList'] = $select;
}
function valext(&$fields,&$vMsg,&$rMsg) {
/* Require either phone number or email or both for contact form */
if (empty($fields['cMail']) AND empty($fields['cPhone'])) {
$rMsg[] = '<br />An email address or phone number';
}
/* Check something is selected from drop-down list, */
if ($fields[recipient] == '0') {
$rMsg[] = '<br />Please select a message subject from the list';
}
return true;
}
function sendMessage(&$fields) {
// set up email adress and response form fields when form submitted
global $modx;
// recreate messages for use as subject field
$options = explode('||',$modx->getChunk('rhMessageList'));
$option = explode('==',$options[$fields['messageType']]);
$fields['cSubject'] = trim($option[0]);
// Match email address, stored as TV rhMailAddresses in format
// <1>mailaddress1||<2>mailaddress2|| etc., (with returns to be stripped)
$mailAddresses = $modx->getTemplateVar('rhMailAddresses','id');
$mailAddresses = explode('||',$mailAddresses['value']);
$recipientAddress = trim($mailAddresses[--$fields['messageType']]);
$recipientAddress = ereg_replace('<.*>','',$recipientAddress);
$fields['email'] = $recipientAddress;
/* set up strings for empty fields */
if (empty($fields['cPhone'])) {
$fields['cPhone'] = '(no phone number supplied)';
}
if (empty($fields['cMail'])) {
$fields['cMail'] = '(no email supplied)';
}
$fields['cText'] = str_replace("\n\n","\n",$fields['cText']);
$fields['cText'] = str_replace("\n","<br />\n",$fields['cText']);
}
?>
The chunk
rhMessageList contains the options for the selection list.
- Please select message subject -==0||Request for details==1||Message to Martha==2||Message to Santa==3||Comment on the website==4
The destination addresses matching the rhMessageList values are stored in the TV
rhMailAddresses, of type Textarea, to make updates easier. The format is
The numbers in angle brackets just help ensure the list is in step with the selection list. They are stripped off along with any newlines, which are only there to make the list more readable. Multiple recipients for any selection are entered as a comma-separated list. I expect you could use newlines as the separator rather than ||, but while that would make updates by non-computerati easier, you might need to take care with different newline definitions across different systems.
The form chunk
pkMessageForm looks like this ():
[+validationmessage+]
<form id="contactForm" name="contactForm" action="/[~[*id*]~]" method="post">
<fieldset>
[+legend+]
<div class="row">
<span class="edLabel"><label for="cName">Name</label></span>
<span class="edField"><input class="field"type="text"size="66" id="cName" name="cName" value="" eform="Name:string:1:Name required"></span>
</div>
<div class="row">
<span class="edLabel"><label for="cMail">Email</label></span>
<span class="edField"><input type="text" class="field" name="cMail" id="cMail" value="" eform="Email:email:0:Invalid email address"></span>
</div>
<div class="row">
<span class="edLabel"><label for="cPhone">Phone</label></span>
<span class="edField"><input type="text" class="field" name="cPhone" id="cPhone" value="" eform="Phone::0:Invalid phone number:#REGEX /^[0-9\+ \(][0-9 \(\)\+\-]{5,20}$/"></span>
</div>
<div class="row">
<span class="edField">
[+rhMessageList+]
</span>
</div>
<div class="row">
<span class="edField"><textarea name="cText" id="cText" cols="29" rows="10" eform="Message:string:1:No message">[+cText+]</textarea></span>
</div>
<div class="row">
<input type="submit" id="submitButton" name="Send this message" value="Send this message" accesskey="S" /></div>
<noscript><hr />
Javascript is not enabled. This box is a precaution against abuse. <br />Please <b>LEAVE IT BLANK</b>, or your message will be rejected. <br />Fake number: 3276 <!-- or output of a random-number generator snippet -->
<input type="text" name="captcha" value=" " eform="Abuse blocker:string:1:Must be blank!:#LIST :-], ,">
</noscript>
</fieldset>
</form>
The message chunk:
<html>
<style> P {font-family: Verdana,Arial,sans-serif;}</style>
<p>This is a response sent by <b>[+cName+]</b> using the feedback form on the XYZ website. </p>
<p>If email was given, you can use this link to reply: <a href="mailto:[+cMail+]?subject=RE: [+cSubject+]">[+cMail+]</a></p>
<p>The details:<br />
Time sent: [+postdate+] <br />
From: [+cName+]<br />
Phone: [+cPhone+]<br />
Email: <a href="mailto:[+cMail+]?subject=RE: [+cSubject+]">[+cMail+]</a><br />
Subject: [+cSubject+]<br /></p>
<p><b>Message</b>:<br />[+cText+]</p>
</html>
Notes:
Validation of the email and phone number: the requirement is that one or other field must have a valid entry. The phone number validation is by no means comprehensive - it just ensures that anything entered in it only contains characters that would occur in a genuine number (and not "99" or "asdfhvsd" or some such rubbish).
There’s a <noscript> block in the form to reduce the chances of spam. Looking at server logs, it seems to me very rare for a spam robot to read CSS, image or Javascript files. So if a robot reads the page, it will see a field here called "captcha" with a number to enter in it. Doing anything but leaving the single space in the input field will lead to rejection of the message. Simple, but quite effective.
In the snippet call, the subject is defined as
&subject=`((cSubject)) (from XYZ website)` instead of using
[+cSubject+]. The double-parenthesis avoids a clash that can arise if you use PHx as a plugin on your site. I don’t do that on this site, but the parenthesis is translated into normal placeholder notation anyway by the eForm snippet.
Hope someone finds this of use

KP