Hi

I am hoping some one can help me with this snippet of code for sending emails with an attachment. I have added the MimeMail module to handle the email attachment encoding, but it never attaches the file.

I have tried using the raw $file->uri (public://) and the drupal_realpath($file->uri) but none of them seem to work.

I'm not even sure if its invoking the MimeMail module although my `variable_get('mail_system')` says its set to `MimeMailSystem`

Can anyone check the code below and advise of any errors/ommissions?

$file = file_load($form_state['values'][0]);
    
$message = array(
  'headers' => array('Content-Type' => 'text/html'),
  'key' => 'test',
  'to' => 'paul.linney@weareroobarb.com',
  'from' => 'info@weareroobarb.com',
  'subject' => 'Test email',
  'body' => '<h1>Test Email</h1></p>This is a test email with HTML formats and styling</p>
<dl><dt>Bulleted list</dt><dd><ul><li>Item one</li><li>Item two</li><li>Item three</li></ul></dd>
<dt>Ordered list</dt><dd><ol><li>Item one</li><li>Item two</li><li>Item three</li></ol></dd>
<dt>Table</dt><dd><table><thead><tr><th>Left column header</th><th>Right column header</th></tr></thead>
<tbody><tr><th>First row header</th><td>First row data</td></tr>
<tr><th>Second row header</th><td>Second row data</td></tr></tbody></table></dd></dl>'
);
$message['attachments'][] = array(
  'filepath' => $file->uri,
  'filename' => $file->filename,
  'filemime' => $file->filemime,
  'list' => TRUE
);

$system = drupal_mail_system('mimemail', 'test');
$system->format($message);
$result = $system->mail($message);

regards,
Paul

Comments

Isostar’s picture

I am looking for the same answer.
I also tried 'filepath' => file_uri_target($file->uri), but without success.

Anonymous’s picture

I got so p**sed off with the MimeMail module in Drupal 7 I went down another route that 100% works:

class AttachmentEmail {
	private $from = '';
	private $from_name = '';
	private $reply_to = '';
	private $to = '';
	private $subject = '';
	private $message = '';
	private $attachment = '';
	private $attachment_filename = '';

  /**
   * Function for defining email
   * @param $to
   *    Email recipient address
   * @param $from
   *    Email sender address
   * @param $message
   *    Message text of body. (currenlty plain text only)
   * $param $attachment (optional)
   *    An array containing attachment file name and path
   *    array('filename' => 'attachment.pdf', 'uri' => '/tmp/attachment.pdf')
 **/
  public function __construct($to, $from, $subject, $message, $attachment =
  array()) {
		$this->to = $to;
    $this->from = $from;
		$this->subject = $subject;
		$this->message = $message;
		if (isset($attachment['uri']) && isset($attachment['filename'])) {
      $this->attachment = $attachment['uri'];
      $this->attachment_filename = $attachment['filename'];
    }
	}

  /**
   * Hook for sending actual eamil
  **/
  public function send() {
		if (!empty($this -> attachment)) {
			$filename = empty($this -> attachment_filename) ? basename($this -> attachment) : $this -> attachment_filename ;
			$path = dirname($this -> attachment);
			$mailto = $this -> to;
			$from_mail = $this -> from;
			$from_name = $this -> from_name;
			$replyto = $this -> reply_to;
			$subject = $this -> subject;
			$message = $this -> message;

      $content = file_get_contents($this->attachment);
			$content = chunk_split(base64_encode($content));
			$uid = md5(uniqid(time()));
			$header = "From: " . $from_mail . "\r\n";
			$header .= "MIME-Version: 1.0\r\n";
			$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
			$header .= "This is a multi-part message in MIME format.\r\n";
			$header .= "--".$uid."\r\n";
			$header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
			$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
			$header .= $message."\r\n\r\n";
			$header .= "--".$uid."\r\n";
			$header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use diff. tyoes here
			$header .= "Content-Transfer-Encoding: base64\r\n";
			$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
			$header .= $content."\r\n\r\n";
			$header .= "--".$uid."--";
			if (mail($mailto, $subject, "", $header)) {
				return true;
			}
      else {
				return false;
			}
		}
    else {
			$header = "From: ".($this -> from_name)." <".($this -> from).">\r\n";
			$header .= "Reply-To: ".($this -> reply_to)."\r\n";

			if (mail($this -> to, $this -> subject, $this -> message, $header)) {
				return true;
			} else {

				return false;
			}

		}
	}
}

Then use it like this:

$email = new AttachmentEmail($recipient, $sender, $subject, $body, $attachment);
$email->send();

Hope that helps

paul.linney’s picture

Hi,

Its frustrating as I can't understand why it doesn't work. However my solution was to take the burden off Drupal completely by using SwiftMail.

I dumped the SwiftMail into a folder in my theme and then used the following:

/*
* Email attachments
**/
function external_email_attachments($mail_content){

    require_once realpath('./').'/'. drupal_get_path('theme', 'my_theme').'/assets/php/swift/lib/swift_required.php';
    
    /*
    * Choose transport method:
    **/
        //SMTP
        //$transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
        //  ->setUsername('your username')
        //  ->setPassword('your password')
        //  ;
        
        //Sendmail
        //$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
        
        //Mail
        $transport = Swift_MailTransport::newInstance();
    
    //Create the Mailer using created Transport
    $mailer = Swift_Mailer::newInstance($transport);

    //Create message
    $message = Swift_Message::newInstance('Documents Emailer')
      ->setFrom(array($mail_content['from'] => $mail_content['from_name']))
      ->setTo(array($mail_content['to'] => $mail_content['to_name']))
      ->setSubject($mail_content['subject'])
      ->setBody($mail_content['body'], 'text/html');
    
    //Attach files
    foreach ($mail_content['attachments'] as $file){
        $message->attach(Swift_Attachment::fromPath($file['filepath']));
    }
    
    //Send the message
    $result = $mailer->send($message);
    
    return $result;
}

Paul

Paul Linney
Owner & Web Developer

breeze76’s picture

I use both the mimemail and mailsystem and it sends the attachment but gives and error on top of confirmation section, error below:

Notice: Undefined property: stdClass::$filecontent in mimemail_html_body() (line 357 of /data/12/1/33/48/1196048/user/1274238/htdocs/tcsite/sites/all/modules/mimemail/mimemail.inc).
Notice: Undefined property: stdClass::$filecontent in mimemail_html_body() (line 357 of /data/12/1/33/48/1196048/user/1274238/htdocs/tcsite/sites/all/modules/mimemail/mimemail.inc).

It always sends the two lines together. Any ideas??

NewZeal’s picture

Following is the code from isos adapted for multiple attachments

<?php
class AttachmentEmail {
    private $from = '';
    private $from_name = '';
    private $reply_to = '';
    private $to = '';
    private $subject = '';
    private $message = '';
    private $attachments = array();

  /**
   * Function for defining email
   * @param $to
   *    Email recipient address
   * @param $from
   *    Email sender address
   * @param $message
   *    Message text of body. (currenlty plain text only)
   * $param $attachment (optional)
   *    An array containing attachment file name and path
   *    array('filename' => 'attachment.pdf', 'uri' => '/tmp/attachment.pdf')
**/
  public function __construct($to, $from, $subject, $message, $attachments =
  array()) {
        $this->to = $to;
        $this->from = $from;
        $this->subject = $subject;
        $this->message = $message;
		$this->attachments = $attachments;
    }

  /**
   * Hook for sending actual eamil
  **/
  public function send() {
        if (!empty($this->attachments)) {
            $mailto = $this -> to;
            $from_mail = $this -> from;
            $from_name = $this -> from_name;
            $replyto = $this -> reply_to;
            $subject = $this -> subject;
            $message = $this -> message; 
			$mime_boundary = "==Multipart_Boundary_x". md5(mt_rand()) ."x";
            $uid = md5(uniqid(time()));
            $header = "From: " . $from_mail . "\r\n";
            $header .= "MIME-Version: 1.0\r\n";
            $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
            $header .= "This is a multi-part message in MIME format.\r\n";
            $header .= "--".$uid."\r\n";
            $header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
            $header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
            $header .= $message."\r\n\r\n";
            $header .= "--".$uid."\r\n";
			
			foreach ($this->attachments as $attachment) {
              $filename = empty($attachment['filename']) ? basename($attachment['uri']) : $attachment['filename'];
              $path = dirname($attachment['uri']);
              $part = file_get_contents($path);
              $content = chunk_split(base64_encode($part));
			  $header .= "--".$uid."\r\n";
              $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use diff. tyoes here
              $header .= "Content-Transfer-Encoding: base64\r\n";
              $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
			  $header .= $content ."\r\n\r\n";
			  
			}
			$header .= "--".$uid."--";
            
            if (mail($mailto, $subject, "", $header)) {
                return true;
            }
            else {
                return false;
            }
        }
        else {
            $header = "From: ".($this -> from_name)." <".($this -> from).">\r\n";
            $header .= "Reply-To: ".($this -> reply_to)."\r\n";

            if (mail($this -> to, $this -> subject, $this -> message, $header)) {
                return true;
            } else {

                return false;
            }

        }
    }
}

Attachments are now an array with multiple file arrays

<?php
$email = new AttachmentEmail($recipient, $sender, $subject, $body, $attachments);
$email->send();
?>
skcuslapurd’s picture

Instead of putting your attachments in
$message['attachments'][]
try adding them to
$message['params']['attachments'][]

Anybody’s picture

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes

yangli0516’s picture

Thanks skcuslapurd, your solution works for me.