Contact for per node in Drupal 8? This was quite easy on Drupal 7. You could just use Webform. In Drupal 8, I'm not so sure. 

I have nodes of type "Business". I want a form to appear on this page, that when filled in, it must send an email to the business. The "Business" content type has a field on it called "Business Contact Email Address". This is where the mail must go...

I was thinking of:


Finding a way to do it using the inherent Drupal 8 contact forms... any clues as to how?
Creating a new content type called "Node Contact Form" that references a node and then use Rules to mail the field on the referenced node.


Is there an easy way to do this?
Not without code, but its fairly easy.

You could add a reference field to contact forms to your node type, and "view" the contact form. contact_storage provides a view builder that will display the form then. That doesn't work for your additional mail requirement, however.

To be able to do that, you need custom code to display the form, something like this in hook_node_view(). field_node_reference is an entity reference field that points back to the node. that will allow you to easily see for which node it was submitted and also use it later on to change the recipient:

  $message = \Drupal::entityManager()-&gt;getStorage('contact_message')
    -&gt;create(array(
      'contact_form' =&gt; 'YOUR_FORM_ID',
      'field_node_reference' =&gt; $node,
      // You can generate a default subject or even hide it completely
      // and always use this value.
      'subject' =&gt; t('Contact about "@title".', ['@title' =&gt; $node-&gt;label()]),
    ));
  $form = \Drupal::getContainer()-&gt;get('entity.form_builder')-&gt;getForm($message);
  $build['yourmodule_contact_form'] = array(
    '#type' =&gt; 'details',
    '#open' =&gt; TRUE,
    '#title' =&gt; t('Contact the business'),
  );
  $build['yourmodule_contact_form']['form'] = $form;


yourmodule_contact_form can be defined as an extra field (hook_entity_extra_field_info), then you can conditionally display it using if ($component = $display-&gt;getComponent('yourmodule_contact_form')) { and you can configure the place and if it should be displayed per view mode.

The final piece is then to override the mail recipient of the sent mail using a hook_mail_alter():

function yourmodule_mail_alter(&amp;$message) {
  if (!empty($message['params']['contact_form']) &amp;&amp; !empty($message['params']['contact_message'])) {
    /** @var \Drupal\contact\Entity\ContactForm $contact_form */
    $contact_form = $message['params']['contact_form'];
    /** @var \Drupal\contact\Entity\Message $contact_message */
    $contact_message = $message['params']['contact_message'];

    if ($contact_form-&gt;id() == 'YOUR_FORM_ID' &amp;&amp; $contact_message-&gt;hasField('field_node_reference')) {
      /** @var \Drupal\node\NodeInterface $node */
      $node = $contact_message-&gt;field_node_reference-&gt;entity;
      if ($node &amp;&amp; $email = $node-&gt;field_email-&gt;value) {
        $message['to'] = $email;
      }
    }
  }


This could possibly be built in a generic way but it would require configuration for the mail and reference fields.