简体   繁体   中英

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' => 'user@myserver.com',
        '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('user@myserver.com');
$message->addTo('receiver@myserver.com');
$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?

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('mywife@home.com')
        ->addFrom('myself@office.com')
        ->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.

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('noreply@example.com', '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);
    }
}

Set the type from :

$attaches[$i]->type = $file['type'].'; name="'.$file['name'].'"';

To:

$attaches[$i]->type = \Zend\Mime\Mime::TYPE_OCTETSTREAM;

You will also want to confirm that if you are using an SMTP service that they allow attachements through the protocol.

E-Mail Messages with Attachments

$mail = new Zend\Mail\Message();
// build message...
$mail->createAttachment($someBinaryString);
$mail->createAttachment($myImage,
                        'image/gif',
                        Zend\Mime\Mime::DISPOSITION_INLINE,
                        Zend\Mime\Mime::ENCODING_BASE64);

If you want more control over the MIME part generated for this attachment you can use the return value of createAttachment() to modify its attributes. The createAttachment() method returns a Zend\\Mime\\Part object:

$mail = new Zend\Mail\Message();

$at = $mail->createAttachment($myImage);
$at->type        = 'image/gif';
$at->disposition = Zend\Mime\Mime::DISPOSITION_INLINE;
$at->encoding    = Zend\Mime\Mime::ENCODING_BASE64;
$at->filename    = 'test.gif';

$mail->send();

An alternative is to create an instance of Zend\\Mime\\Part and add it with addAttachment():

$mail = new Zend\Mail\Message();

$at = new Zend\Mime\Part($myImage);
$at->type        = 'image/gif';
$at->disposition = Zend\Mime\Mime::DISPOSITION_INLINE;
$at->encoding    = Zend\Mime\Mime::ENCODING_BASE64;
$at->filename    = 'test.gif';

$mail->addAttachment($at);

$mail->send();

Reference1 Reference2 Reference3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM