I want to allow people to chose which person/department to send a message to using the P&T Contact Form plugin. I've seen one method to do this, eg:

<select name="toEmail">
      <option value="{{ '1stname@example.com'|hash }}">1st name</option>
      <option value="{{ '2ndname@example.com'|hash }}">2nd name</option>

but it does mean that the actual email address is visible in the HTML code. Which would allow the spam robots to harvest it. Although it may be that the hash added makes it harder?

In the ideal world I would like the address to be completely hidden or encrypted in the form page html. I wonder if the name="toEmail" value=" " could be a variable that is passed along with the value="contactForm/sendMessage" action, that could then be referenced and replaced from a list in the contact form config file.

I did think of using a plugin to store the email address related to a name/department as a variable, but it still just adds the plain text address to the final html.

It seems to me that not having plain text email addresses should be the standard way of working so I'm surprised that there isn't already a plugin or method to do this, but I can't find one.

Edit to show the final solution I'm using.

I'm very grateful to Robin Schambach, who provided all the clever code, I've just put it all together here to help anyone looking for a similar solution. The email addresses are never available or visible on the front end.

Create a Section named Contacts with plain text data fields of:




contactKey (this stores the name in camelCase, so "johnSmith" not "John Smith")

This allows the end user to maintain/update the names and addresses of contacts without the developer needing to make changes on the server.

Install P&T Contact form plugin and add a config file to overide the plugin settings. The contents of that file should be:

namespace Craft;
$toEmailId = craft()->request->getPost('toEmail');
$criteria = craft()->elements->getCriteria(ElementType::Entry);
$criteria->section = 'contacts';
$allAddresses = [];
foreach($criteria as $entry){
    $allAddresses[$entry->contactKey] = $entry->contactEmail;
$toEmail = (array_key_exists($toEmailId, $allAddresses))? $allAddresses[$toEmailId] : null;
return array(
    'toEmail' => ($toEmail ?: null),
    'prependSubject'      => '',
    'prependSender'       => '',
    'allowAttachments'    => false,
    'honeypotField'       => 'honeyPot',
    'successFlashMessage' => 'Thanks for your message'

My contact form looks like this (based on the P&T example):

{% macro errorList(errors) %}
    {% if errors %}
        <ul class="errors">
            {% for error in errors %}
                <li>{{ error }}</li>
            {% endfor %}
    {% endif %}
{% endmacro %}

{% from _self import errorList %}

<form method="post" action="" accept-charset="UTF-8">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="contactForm/sendMessage">
    <input type="hidden" name="redirect" value="contact/thanks">

    {% set entries = craft.entries.section('contacts').find %}
    {% for entry in entries %}
        <select name="toEmail">{# you could also use radio buttons #}
            <option value="{{ entry.contactKey }}">{{ entry.contactName }}, {{ entry.contactTitle }}</option>
    {% endfor %}

    <h3><label for="fromName">Your Name</label></h3>
    <input id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

    <h3><label for="fromEmail">Your Email</label></h3>
    <input id="fromEmail" type="email" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

    <h3><label for="subject">Subject</label></h3>
    <input id="subject" type="text" name="subject" value="{% if message is defined %}{{ message.subject }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('subject')) }}

    <h3><label for="message">Message</label></h3>
    <textarea rows="10" cols="40" id="message" name="message">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
    {{ message is defined and message ? errorList(message.getErrors('message')) }}

    <input id="honeyPot" name="honeyPot" type="text">{# hide this via CSS #}

    <input type="submit" value="Send">

You can Create a custom array in which you store all valid email addresses and send the id which email to use

<select name="toEmail">
  <option value="1">1st name</option>
  <option value="2">2nd name</option>

and in your config file

namespace Craft;

$toEmailId = craft()->request->getPost('toEmail');
$yourArray = [
    1 => 'firstmail.com',
    2 => 'secondmail.com',
$toEmail = (array_key_exists($toEmailId, $yourArray))? $yourArray[$toEmailId]  : null;
return array(
    'toEmail' => $toEmail,
  • I've tried various combinations but I can't work out where to add your bit of backend code into my config file, which looks like this: <?php namespace Craft; $toEmail = craft()->request->getPost('toEmail'); return array( 'toEmail' => ($toEmail ?: null), 'prependSubject' => 'From website: ', ); I've tried every permutation I can think of. – Paul Frost Dec 19 '17 at 14:35
  • Ah, we are back to my limited programming skills again. I've looked at the ContactFormController in the P&T plugin but can't see anything like your code that I can edit. I had hoped there would be a simple plugin to solve what seemed like a common function on a website. But I should know by now that things I think of as normal everyday requirements are unusual and require programming skills outside of html & css. – Paul Frost Dec 19 '17 at 15:06
  • I edited my answer, it is untested but I thing that should work. I thing this approach might be easier for you. A custom controller/service would have been a little bit better but that works as well – Robin Schambach Dec 19 '17 at 15:07
  • Initial testing is working, so thanks for that, you have bailed me out again. Now I'll try and understand what's going on in that code. – Paul Frost Dec 19 '17 at 15:18
  • It's actually pretty easy. $toEmailId is the value / the id the requests sends. $yourArray is a simple array map, so a simple pair of key => emails depending which key the user selects in the frontend the array "converts" it to an email address and returns this value to the service. Depending on how you create your select you can change the $yourArray as well. So when you have a set of global configs, you can check this as well. – Robin Schambach Dec 19 '17 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.