15

I'm trying to send attachments with my email from Drupal. In my custom module i have added:

class SponsorprogramMailSystem implements MailSystemInterface {
  /**
   * Concatenate and wrap the e-mail body for plain-text mails.
   *
   * @param $message
   *   A message array, as described in hook_mail_alter().
   *
   * @return
   *   The formatted $message.
   */
  public function format(array $message) {
    $message['body'] = implode("\n\n", $message['body']);
    return $message;
  }
  /**
   * Send an e-mail message, using Drupal variables and default settings.
   *
   * @see http://php.net/manual/en/function.mail.php
   * @see drupal_mail()
   *
   * @param $message
   *   A message array, as described in hook_mail_alter().
   * @return
   *   TRUE if the mail was successfully accepted, otherwise FALSE.
   */
  public function mail(array $message) {
    $mimeheaders = array();
    foreach ($message['headers'] as $name => $value) {
      $mimeheaders[] = $name . ': ' . mime_header_encode($value);
    }
    $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
    return mail(
      $message['to'],
      mime_header_encode($message['subject']),
      // Note: e-mail uses CRLF for line-endings. PHP's API requires LF
      // on Unix and CRLF on Windows. Drupal automatically guesses the
      // line-ending format appropriate for your system. If you need to
      // override this, adjust $conf['mail_line_endings'] in settings.php.
      preg_replace('@\r?\n@', $line_endings, $message['body']),
      // For headers, PHP's API suggests that we use CRLF normally,
      // but some MTAs incorrectly replace LF with CRLF. See #234403.
      join("\n", $mimeheaders)
    );
  }
}

and i can send mails with html, that part is working.

But when i try to attach a file it does not arrive in my inbox. I attach my test file like this:

$attachment = array(
        'filecontent' => file_get_contents(DRUPAL_ROOT . '/README.txt'),
        'filename' => 'test.txt',
        'filemime' => 'text/plain',
      );

But nothing arrives.

Anyone know how i can fix it?

2
  • It's unclear to me how $attachment is added in your example. Oct 25, 2014 at 8:31
  • any update on D8?
    – Matoeil
    Nov 19, 2021 at 15:27

3 Answers 3

20

There might be other ways, but I have found that mailsystem and mimemail modules have to be installed to send email with attachment. So install these two modules first.

Then implement hook_mail to pass attachment to $message

/**
 * Implements hook_mail().
 */
function mymodule_mail($key, &$message, $params) {
  $message['subject'] = $params['subject'];
  $message['body'][] = $params['body'];

  // Add attachment when available.
  if (isset($params['attachment'])) {
    $message['params']['attachments'][] = $params['attachment'];
  }
}

There are two ways to add attachment, you can either pass filecontent or filepath when adding an unmanaged file as attachment (not recorded in DB) or pass file object when adding an managed file.

When adding unmanaged file:

$attachment = array(
  'filepath' => $filepath, // or $uri
);

or

$attachment = array(
  'filecontent' => file_get_contents($uri),
  'filename' => $filename,
  'filemime' => 'application/pdf'
);

By using filecontent way, you probably will get two php errors by Jan 08, 2015 including

When adding managed file:

$attachment = file_load($fid);

Then send email by:

$params = array(
  'key' => 'my_email_template',
  'to' => 'test@example.com',
  'from' => 'test@example.com',
  'subject' => 'Test email',
  'body' => 'test',
  'attachment' => $attachment
);

drupal_mail('mymodule', $key, $to, $language, $params, $from);
2
  • any headers needs to be set?
    – siddiq
    Oct 10, 2017 at 4:41
  • 1
    @siddiq no need to set any headers Oct 12, 2017 at 6:18
3

I remember I want did it before, I tried this and worked for me

function mymodule_mail($key, &$message, $params) {
  $data['user'] = $params['from'];
  $account = $data['user']->name;

  $file_content = file_get_contents('some/file/path');

  $attachments = array(
     'filecontent' => $file_content,
     'filename' => 'example-' . $account,
     'filemime' => 'application/pdf',
   );

  switch($key) {
    case 'notice':

      $langcode = $message['language']->language;
      $message = drupal_mail($module, $key, $to, $language, $params, $from, $send);
      $message['subject'] = 'example submission from '. $account;
      $message['body'][] =
        '<p>'. $account .' has submitted an example.</p>';
      $message['params']['attachments'][] = $attachments;
    $system = drupal_mail_system($module, $key);
    // Format the message body.
    $message = $system->format($message);
    // Send e-mail.
    $message['result'] = $system->mail($message);

    if($message['result'] == TRUE) {
        drupal_set_message(t('Your message has been sent.'));
    }
    else{
        drupal_set_message(t('There was a problem sending your message and it was not     sent.'), 'error');
    }
      break;
  }
}
3
  • 1
    file_get_contents() did the trick for me. if not using it, I was getting corrupted file attachments. Thanks.
    – anou
    Jun 17, 2016 at 15:34
  • @anou I am happy my solution help another one after 2 years :D
    – Yuseferi
    Jun 17, 2016 at 23:45
  • Again, this will definitely not work unless you have an additional module like Mime Mail which understands and can use the values set in $params['attachment'] - core Drupal by itself does not know how to add attachments and core Drupal will ignore anything you put in $params['attachment'].
    – anonymous
    Dec 1, 2020 at 6:32
3
$attachment = array(
      'filecontent' => $filepathname,
      'filename' => $namefile,
      'filemime' => 'application/pdf'
      );
//where $filepathname should contain the path to the file and $filename should contain the name of the file.
$to = 'test@example.com'; // emails
$from = 'test@example.com';

$params = array(
  'headers' => array('Content-Type' => 'text/html'),
  'key' => 'test',
  'subject' => 'Test email',
  'body' => 'test',
  'attachment' => $attachment
);

drupal_mail($module, $key, $to, $language, $params, $from, $send = TRUE);

This worked for me.

2
  • Seems odd to populate the to and from in $params but not set $to and $from... I'm not sure this will work.
    – drewish
    Jul 28, 2015 at 4:41
  • This will definitely not work - core Drupal by itself does not know how to add attachments and core Drupal will ignore anything you put in $params['attachment'] unless you have an additional module like Mime Mail which understands and can use the values set in $params['attachment'].
    – anonymous
    Dec 1, 2020 at 6:31

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.