Sending E-Mail in Drupal 8

Need to send an email from your custom module?

First, let's make a template file so you can add some HTML markup if you want. This will go in your custom_module/templates directory.

<h1>Here is a header for your e-mail</h1>
{{ text|raw }}

Sincerely,
{{ sender_name|raw }}

Some pieces that will go into your custom module

Include the template in your hook_theme()

Be sure to clear your cache for this template to be used.

/**
 * Implements hook_theme().
 * To add the template definition.
 **/
function MY_MODULE_theme($existing, $type, $theme, $path) {
  return [
    'my-custom-email' => [
      'variables' => [
        'text' => NULL,
        'sender_name' => NULL,
      ],
    ], 
  ];  
}

Add hook_mail()

/**
* Implements hook_mail().
*/
function MY_MODULE_mail($key, &$message, $params) {
 $options = array(
   'langcode' => $message['langcode'],
 );
 switch ($key) {
   case 'my_custom_key':
      $message['headers'] = $params['headers'];
      $message['from'] = $params['from'];
      $message['subject'] = $params['subject'];
      $message['body'][] = $params['message'];
      $message['params']['files'] = $params['attachments'];
      break;
 }
}

Now, you can wrap the emailing into a function while using variables such as the recipient, sender, etc.

<?php
  
function _send_my_custom_email($data) {
  // Set a reply-to value
  $reply_to = $data['reply_to'];
  
  // Set a from value
  $from = $data['from'];
  
  // Set a subject
  $subject = $data['subject']
  
  // Set a sender name
  $sender_name = $data['sender_name'];
  
  // Set a recipient email
  $to = $data['to'];
  
  // Set your message body
  $body = $data['body'];
  
  // Use the theme to send the message
  $theme_body = array(
    '#theme' => 'my-custom-email',
    '#text' => $body,
    '#sender_name' => $sender_name,
  );
  
  // Set up the Drupal Mail manager
  $mailManager = \Drupal::service('plugin.manager.mail');
  
  // Tell the mail system what module you are sending this from
  $module = 'my_custom_module';
  
  // Set up the parameters for your email from the variables
  $params['message'] = drupal_render($theme_body);
  // Set some header information
  $params['headers'] = [
    'content-type' => 'text/html',
    'MIME-Version' => '1.0',
    'reply-to' => $data['from'],
    'from' => 'sender name <' . $from . '>',
    'Return-Path' => 'sender name <' . $from . '>',
  ];
  $params['from'] = $from;
  $params['subject'] = $subject;
  
  // Need to attach a file? Maybe uploaded through a form
  if(!empty($data['attach'])) {
    $file_info = array();
    $file_info['filepath'] = $data['attach']['uri']; // File path
    $file_info['filename'] = $data['attach']['filename']; //File name
    $file_info['filemime'] = $data['attach']['filemime']; //File mime type
    $params['attachments'][] = $file_info;
  }
  
  
  // Set a key so you can send different types of message
  $key = 'my_custom_key';
  
  // Get the language code from your site
  $langcode = \Drupal::currentUser()->getPreferredLangcode();
  
  // Set sending to true in case there is other logic that needs to happen before
  $send = true;
  
  // Send the E-Mail
  $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, $send);

}

Now, you can call the function to email while passing along some parameters

// Within a function that you are using that requires an email to be sent, you call the function with some data

use Drupal\file\Entity\File;

function _something_should_be_happening() {
  if($something == 'happened') {
    $data['reply_to'] = 'reply_to@example.com';
    $data['from'] = 'from@example.com';
    $data['subject'] = 'Subject text here';
    $data['sender_name'] = 'John Doe'; 
    $data['to'] = 'receiver@example.com';
    $data['body'] = 'A long value that can also hold <div>HTML Markup</div>';
    
    if($add_a_file == TRUE) {
      // Need to send a file attachment?
      // Load a file
      $file = File::load('FILE_ID');
      // attach some file info
      $data['attach']['uri'] = $file->getFileUri();
      $data['attach']['filename'] = $file->getFileName();
      $data['attach']['filemime'] = $file->getMimeType();
    }
  
    _send_my_custom_email($data);
    return;
  } else {
    return;
  }
}