0

Through drupal_mail('mymodule', ...) I'm trying to send e-mails with four (4) attachments. When I send an e-mail, I is delivered instantly with the correct subject and body. However, I only get the first attachment, not the other three (3).

Details below. Does anyone have an idea what's going on here?

What I've tried

So far I've tried several (not notable) combinations of headers, providing attachments as content of with filepath only, and some variations suggested in related Q&As. Attachment structure is per the documentation in the module at mimemail.module::mimemail_prepare_message() (~line 309).

The e-mails I'm sending are HTML emails, with attachments, routed through custom SMTP settings (sending through SendGrid).

The total size of the emails is well below the 8MB limit Drupal seems to impose.

In the bottom code block of my post I have added a var_dump() of my $message. This dump also contains the array $message['params], which contains the $params I've passed to drupal_mail('mymodule', ...).

Technical details:

Installed mail modules:

Mail configuration, through Mail System module:

  • Site-wide default MailSystemInterface class: HTMLMailSystem__SmtpMailSystem
  • HTML Mail module class: HTMLMailSystem__SmtpMailSystem
  • Mime Mail module class: MimeMailSystem

Custom mail hooks:

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

    if (!empty($params['body'])) {
        $message['body'] = $params['body'];
    }

    if (!empty($params['attachments'])) {
        $message['attachments'] = $params['attachments'];
    }

    if (!empty($params['Cc'])) {
        $message['Cc'] = $params['Cc'];
    }
}

/**
 * Implements hook_mail_alter().
 */
function mymodule_mail_alter(&$message)
{
    if (!empty($message['params']['headers'])) {
        $message['headers'] = array_merge($message['headers'], $message['params']['headers']);
    }
}

A var_dump of $message, called at the bottom of mymodule_mail_alter() (data partially faked to protect client):

array (size=12)
  'id' => string 'mymodule_mymail' (length=38)
  'module' => string 'mymodule' (length=10)
  'key' => string 'mymail' (length=27)
  'to' => string 'someone@example.com' (length=30)
  'from' => string 'test-someone@example.com' (length=35)
  'language' => string 'nl' (length=2)
  'params' => 
    array (size=4)
      'headers' => 
        array (size=2)
          'MIME-Version' => string '1.0' (length=3)
          'Content-Type' => string 'multipart/mixed; text/html; text/plain; charset=UTF-8; format=flowed; delsp=yes' (length=79)
      'subject' => string 'Title' (length=46)
      'body' => 
        array (size=1)
          0 => string '<p>HTML</p><p>Mail</p>'... (length=555)
      'attachments' => 
        array (size=4)
          0 => 
            array (size=4)
              'filecontent' => string 'test file' (length=16)
              'filename' => string 'test_mail.txt' (length=11)
              'filemime' => string 'text/plain' (length=10)
              'filepath' => null
          1 => 
            array (size=4)
              'filecontent' => string 'test file' (length=16)
              'filename' => string 'test_mail_2.txt' (length=13)
              'filemime' => string 'text/plain' (length=10)
              'filepath' => null
          2 => 
            array (size=4)
              'filecontent' => string 'test file' (length=16)
              'filename' => string 'test_file_3.txt' (length=32)
              'filemime' => string 'text/plain' (length=10)
              'filepath' => null
          3 => 
            array (size=4)
              'filecontent' => string 'test file' (length=16)
              'filename' => string 'test_mail.txt' (length=11)
              'filemime' => string 'text/plain' (length=10)
              'filepath' => null
  'send' => boolean true
  'subject' => string 'Title' (length=46)
  'body' => 
    array (size=1)
      0 => string '<p>HTML</p><p>Mail</p>'... (length=555)
  'headers' => 
    array (size=7)
      'MIME-Version' => string '1.0' (length=3)
      'Content-Type' => string 'multipart/mixed; text/html; text/plain; charset=UTF-8; format=flowed; delsp=yes' (length=79)
      'Content-Transfer-Encoding' => string '8Bit' (length=4)
      'X-Mailer' => string 'Drupal' (length=6)
      'Return-Path' => string 'test-someone@example.com' (length=35)
      'Sender' => string 'test-someone@example.com' (length=35)
      'From' => string 'test-someone@example.com' (length=35)
  'attachments' => 
    array (size=4)
      0 => 
        array (size=4)
          'filecontent' => string 'test file' (length=16)
          'filename' => string 'test_mail.txt' (length=11)
          'filemime' => string 'text/plain' (length=10)
          'filepath' => null
      1 => 
        array (size=4)
          'filecontent' => string 'test file' (length=16)
          'filename' => string 'test_mail_2.txt' (length=13)
          'filemime' => string 'text/plain' (length=10)
          'filepath' => null
      2 => 
        array (size=4)
          'filecontent' => string 'test file' (length=16)
          'filename' => string 'test_file_3.txt' (length=32)
          'filemime' => string 'text/plain' (length=10)
          'filepath' => null
      3 => 
        array (size=4)
          'filecontent' => string 'test file' (length=16)
          'filename' => string 'test_mail.txt' (length=11)
          'filemime' => string 'text/plain' (length=10)
          'filepath' => null
0

We ran into the following article at the office: Let the Drupal send an email with attachment using Mimemail module.

Only one line in the code needed to be changed, I added 'filepath' to my attachment data. I first had filepath => null, but setting it to $file_data->uri fixed it:

$attachment_data[] = array(
    'filename' => $file_data->filename,
    'filemime' => $file_data->filemime,
    'filepath' => $file_data->uri,
);

Note: I had to remove filecontent from my attachment data. If you supply both filecontent and filepath, the same attachment is sent twice.

1
  • This works because you are specifying filepath for each attachment. If the paths are different, then all the files will be attached. If some of the paths are the same, the duplicates will NOT be attached. In the original post you were specifying filecontent instead. That also works, but with filecontent the contents need to be different. If the contents of all attachments are different all will be attached. If some of the files have duplicate contents, the duplicates will NOT be attached. – anonymous Aug 19 '20 at 20:38
0

When attaching a file, you provide information about that file to Mime Mail using the keys: filecontent, filename, filemime, and filepath as shown above. The important part is to understand what these keys mean and what they are used for.

If you provide a filepath, then Mime Mail uses that to find the file and to extract its contents. If you DON'T provide a filepath (or if it is NULL), then you MUST store the contents of the file in filecontent.

filename and filemime are optional, and are just used to tell the recipient's mail client what to call the file and what the file contains. The name doesn't have to be the same as the "real" name of the file on your server.

If filepath is set but filename isn't, the "real" file name will be used. If filecontent is set but filename isn't, the file will be called "attachment.dat"

Likewise, if filemime isn't set, the mime type will be automatically computed based on the file extension.

There is one other important thing to know: Mime Mail automatically detects duplicate attachments and removes them. This is mostly used for images - themes often use the same image many times on a page, and rather than attaching many copies of the same image Mime Mail attaches the image only once (and uses that one copy many times). But this removal of duplicates is not only for images but for all attachments.

The problem in the original post is because you attached the SAME file four times - Mime Mail detected that this was the same file and didn't try to include all four duplicates in your email.

If you specify the file with filepath, Mime Mail identifies duplicates by comparing the paths - if the paths are the same, the files are duplicates. But if you specify the files using the filecontent, like you did in the original post, then Mime Mail compares the contents to determine if the files are duplicates. (Actually, it calculates a hash of the contents and compares the hashes, but that's effectively the same.)

As I said above, filename is just an optional name for the use of the recipient, it is not used to identify the file or determine if it is a duplicate.

To fix the example in the original post, just make the contents of the four files different, then you will get four attachments.

-1

Use Drupal's Swift Mailer module, it does the task perfectly. I have used it to send multiple system reports in csv format.

3
  • Thank you for your suggestion. Will keep it in mind for other projects. – Marijke Luttekes Jan 8 '16 at 12:41
  • You can use this in the same project as well, Drupal allows to define Mail class per module/key combinations as well. – nikunj Jan 12 '16 at 5:48
  • Using Mime Mail does the task perfectly too. – anonymous Aug 19 '20 at 20:06

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.