Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

send email with attached files in ZF2

How to send email with text/plain, text/html and attaches in zf2 ? I use this code to send email with smtp:

$files = $this->params()->fromFiles();
$smtp = new \Zend\Mail\Transport\Smtp();
$smtp->setAutoDisconnect(true);
$optn = new \Zend\Mail\Transport\SmtpOptions(array(
    'host'              => 'mail.myserver.com',
    'connection_class'  => 'login',
    'connection_config' => array(
        'username' => '[email protected]',
        'password' => 'mypassword',
    ),
));
$smtp->setOptions($optn);


$htmlPart = new \Zend\Mime\Part('<p>some html</p>');
$htmlPart->type = Mime::TYPE_HTML;

$textPart = new \Zend\Mime\Part('some text');
$textPart->type = Mime::TYPE_TEXT;

$i=0;
$attaches = array();
foreach($files as $file){
    if ($file['error'])
        continue;
    $attaches[$i] = new \Zend\Mime\Part(file_get_contents($file['tmp_name']));
    $attaches[$i]->type = $file['type'].'; name="'.$file['name'].'"';
    $attaches[$i]->encoding = 'base64';
    $attaches[$i]->disposition = 'attachment';
    $attaches[$i]->filename = $file['name'];
    $i++;
}

$parts = array();
if (count($attaches)>0) {
    $parts = array_merge(array($textPart,$htmlPart),$attaches);
    $type = Mime::MULTIPART_MIXED;
}
else{
    $parts = array($textPart, $htmlPart);
    $type = Mime::MULTIPART_ALTERNATIVE ;
}
$body = new \Zend\Mime\Message();
$body->setParts($parts);

$message = new \Zend\Mail\Message();
$message->setFrom('[email protected]');
$message->addTo('[email protected]');
$message->setSubject('subject');
$message->setEncoding("UTF-8");
$message->setBody($body);
$message->getHeaders()->get('content-type')->setType($type);

$smtp->send($message);

If I attach files, it sends files and contents but it shows plain and html text together in receiver inbox:

<p>some html</p>
some text

When I don't attach any files, it shows html text singly:

some html

Any help?

like image 664
Mohammad Mehdi Habibi Avatar asked Jun 12 '13 12:06

Mohammad Mehdi Habibi


2 Answers

Currently there is no easy way in ZF2 (2.2) to combine a multipart/alternative body (html with text alternative for clients that cannot/do-not-want-to use html) with attachments. If you add the 'multipart/alternative' content-type header to the entire message, in some email clients the attachment (link) will not be displayed.

The solution is to split the message in two, the body (text and html) and the attachment:

http://jw-dev.blogspot.com.es/2013/01/zf2-zend-mail-multipartalternative-and.html

an example:

        $content  = new MimeMessage();
        $htmlPart = new MimePart("<html><body><p>Sorry,</p><p>I'm going to be late today!</p></body></html>");
        $htmlPart->type = 'text/html';
        $textPart = new MimePart("Sorry, I'm going to be late today!");
        $textPart->type = 'text/plain';
        $content->setParts(array($textPart, $htmlPart));

        $contentPart = new MimePart($content->generateMessage());        
        $contentPart->type = 'multipart/alternative;' . PHP_EOL . ' boundary="' . $content->getMime()->boundary() . '"';

        $attachment = new MimePart(fopen('/path/to/test.pdf', 'r'));
        $attachment->type = 'application/pdf';
        $attachment->encoding    = Mime::ENCODING_BASE64;
        $attachment->disposition = Mime::DISPOSITION_ATTACHMENT;

        $body = new MimeMessage();
        $body->setParts(array($contentPart, $attachment));

        $message = new Message();
        $message->setEncoding('utf-8')
        ->addTo('[email protected]')
        ->addFrom('[email protected]')
        ->setSubject('will be late')
        ->setBody($body);

        $transport = new SmtpTransport();
        $options   = new SmtpOptions($transportConfig),
        ));

        $transport->setOptions($options);
        $transport->send($message);

For the above you would need the following use statements:

use Zend\Mail\Message;
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mail\Transport\SmtpOptions;
use Zend\Mime\Mime;
use Zend\Mime\Part as MimePart;
use Zend\Mime\Message as MimeMessage;

ZF1 had a _buildBody() method in Zend_Mail_Transport_Abstract which did this automatically.

like image 197
tihe Avatar answered Sep 27 '22 21:09

tihe


I have found it a better solution so I am writing it.

Namespace YourNamesapace;

use Zend\Mail\Message as ZendMessage;
use Zend\Mime\Part as MimePart;
use Zend\Mime\Message as MimeMessage;
use Zend\Mail\Transport\Sendmail;
class Testmail
{
    public static function sendMailWithAttachment($to, $subject, $htmlMsg, $dir, $fileName)
    {
        $fileFullPath = $dir . '/' . $fileName;
        // Render content from template
        $htmlContent = $htmlMsg;
        // Create HTML part
        $htmlPart = new MimePart($htmlContent);
        $htmlPart->type = "text/html";
        // Create plain text part
        $stripTagsFilter = new \Zend\Filter\StripTags();
        $textContent = str_ireplace(array("<br />", "<br>"), "\r\n", $htmlContent);
        $textContent = $stripTagsFilter->filter($textContent);
        $textPart = new MimePart($textContent);
        $textPart->type = "text/plain";

        // Create separate alternative parts object
        $alternatives = new MimeMessage();
        $alternatives->setParts(array($textPart, $htmlPart));
        $alternativesPart = new MimePart($alternatives->generateMessage());
        $alternativesPart->type = "multipart/alternative;\n boundary=\"".$alternatives->getMime()->boundary()."\"";

        $body = new MimeMessage();
        $body->addPart($alternativesPart);


        $attachment = new MimePart( file_get_contents($fileFullPath) );
        $attachment->type = \Zend\Mime\Mime::TYPE_OCTETSTREAM;
        $attachment->filename = basename($fileName);
        $attachment->disposition = \Zend\Mime\Mime::DISPOSITION_ATTACHMENT;
        $attachment->encoding = \Zend\Mime\Mime::ENCODING_BASE64;
        $body->addPart($attachment);
        // Create mail message
        $mailMessage = new ZendMessage();
        $mailMessage->setFrom('[email protected]', 'from Name');
        $mailMessage->setTo($to);
        $mailMessage->setSubject($subject);
        $mailMessage->setBody($body);
        $mailMessage->setEncoding("UTF-8");
        $mailMessage->getHeaders()->get('content-type')->setType('multipart/mixed');
        $transport = new Sendmail();
        $transport->send($mailMessage);
    }
}
like image 27
Amit Garg Avatar answered Sep 27 '22 20:09

Amit Garg