Display inline image attachments with wp_mail

痴心易碎 提交于 2021-01-21 04:39:25

问题


I have a problem.

I would like to attach an image to an email and also display it inline, with some other php-generated content. The problem is I don't have the slightest ideea how to use inline a file attachment array used by wp_mail to attach.

My solution was to encode the images in base64 and put them inline the HTML like this:

<img alt="The Alt" src="data:image/png;base64,*etc*etc*etc" />

But the problem is that Gmail / Outlook remove the src data from the image. So it lands as

<img alt="The Alt" />

Any clues what to modify (headers to work with base64) or how to use attachment to embed them inline?


回答1:


wp_mail uses the PHPMailer class. This class has all the functionality needed for inline attachments. To change the phpmailer object before wp_mail() sends the email you could use the filter phpmailer_init.

$body = '
Hello John,
checkout my new cool picture.
<img src="cid:my-cool-picture-uid" width="300" height="400">

Thanks, hope you like it ;)';

That was an example of how to insert the picture in you email body.

$file = '/path/to/file.jpg'; //phpmailer will load this file
$uid = 'my-cool-picture-uid'; //will map it to this UID
$name = 'file.jpg'; //this will be the file name for the attachment

global $phpmailer;
add_action( 'phpmailer_init', function(&$phpmailer)use($file,$uid,$name){
    $phpmailer->SMTPKeepAlive = true;
    $phpmailer->AddEmbeddedImage($file, $uid, $name);
});

//now just call wp_mail()
wp_mail('test@example.com','Hi John',$body);

That's all.




回答2:


If you get an unexpected T_FUNCTION error, it is due to the PHP version < 5.3. In that case, create a function to do it in a more traditional way:

function attachInlineImage() {  
  global $phpmailer;  
  $file = '/path/to/file.jpg'; //phpmailer will load this file  
  $uid = 'my-cool-picture-uid'; //will map it to this UID  
  $name = 'file.jpg'; //this will be the file name for the attachment  
  if (is_file($file)) {  
    $phpmailer->AddEmbeddedImage($file, $uid, $name);  
  }  
}  

add_action('phpmailer_init','attachInlineImage');  



回答3:


I needed this in a small better way because I'm sending multiple mails in one step and not all mails should have the same embedded images. So I'm using this solution from Constantin but with my Modifications :-)

wp_mail('test@example.org', 'First mail without attachments', 'Test 1');

$phpmailerInitAction = function(&$phpmailer) {
    $phpmailer->AddEmbeddedImage(__DIR__ . '/img/header.jpg', 'header');
    $phpmailer->AddEmbeddedImage(__DIR__ . '/img/footer.png', 'footer');
};
add_action('phpmailer_init', $phpmailerInitAction);
wp_mail('test@example.org', 'Mail with embedded images', 'Example <img src="cid:header" /><br /><img src="cid:footer" />', [
    'Content-Type: text/html; charset=UTF-8'
], [
    __DIR__ . '/files/terms.pdf'
]);
remove_action('phpmailer_init', $phpmailerInitAction);

wp_mail('test@example.org', 'Second mail without attachments', 'Test 2');

The first wp_mail will be without attachments. The second wp_mail will contain embedded images. The third wp_mail will be without attachments.

It's working fine for now 😎




回答4:


I created this class to manage adding an image to email body and clean up after itself.

Also if you define SENDGRID_PASSWORD, it will use Sendgrid instead of your server to send emails

This article is a step by step guid on how to embed images in email body using wordpress

https://codewriteups.com/embed-images-in-email-body-using-wp_mail-and-phpmailer

<?php

/*
 * Send HTML Emails with inline images
 */
class Custom_Mailer
{
    public $email_attachments = [];

    public function send($to, $subject, $body, $headers, $attachments)
    {
        /* Used by "phpmailer_init" hook to add attachments directly to PHPMailer  */
        $this->email_attachments = $attachments;

        /* Setup Before send email */
        add_action('phpmailer_init', [$this, 'add_attachments_to_php_mailer']);
        add_filter('wp_mail_content_type', [$this, 'set_content_type']);
        add_filter('wp_mail_from', [$this, 'set_wp_mail_from']);
        add_filter('wp_mail_from_name', [$this, 'wp_mail_from_name']);
        
        /* Send Email */
        $is_sent = wp_mail($to, $subject, $body, $headers);
        
        /* Cleanup after send email */
        $this->email_attachments = [];
        remove_action('phpmailer_init', [$this, 'add_attachments_to_php_mailer']);
        remove_filter('wp_mail_content_type', [$this, 'set_content_type']);
        remove_filter('wp_mail_from', [$this, 'set_wp_mail_from']);
        remove_filter('wp_mail_from_name', [$this, 'wp_mail_from_name']);

        return $is_sent;
    }

    public function add_attachments_to_php_mailer(&$phpmailer)
    {
        $phpmailer->SMTPKeepAlive=true;
        
        /* Sendgrid */
        if (defined('SENDGRID_PASSWORD')) {
            $phpmailer->IsSMTP();
            $phpmailer->Host="smtp.sendgrid.net";
            $phpmailer->Port = 587;
            $phpmailer->SMTPAuth = true;
            $phpmailer->SMTPSecure = 'tls';
            $phpmailer->Username="apikey";
            $phpmailer->Password = SENDGRID_PASSWORD;   /* api key from sendgrid */
        }

        /* Add attachments to mail */
        foreach ($this->email_attachments as $attachment) {
            if (file_exists($attachment['path'])) {
                $phpmailer->AddEmbeddedImage($attachment['path'], $attachment['cid']);
            }
        }
    }

    public function set_content_type()
    {
        return "text/html";
    }
    
    public function set_wp_mail_from($email)
    {
        //Make sure the email is from the same domain
        //as your website to avoid being marked as spam.
        return strip_tags(get_option('admin_email'));
    }

    public function wp_mail_from_name($name)
    {
        return get_bloginfo('name');
    }
}

Usage:

/* Set mail parameters */
$to = 'test@example.com';
$subject = 'Inline Img';
$body = '<h1>Image:</h1> <img src="cid:my_img_cid"/>';
$headers = "";
$my_attachments = [
    [
        "cid" => "my_img_cid", /* used in email body */
        "path" => plugin_dir_path(__FILE__) . '/my_img.png',
    ],
];

$custom_mailer = new Custom_Mailer();
$custom_mailer->send($to, $subject, $body, $headers, $my_attachments);



回答5:


AddEmbeddedImage only accepts two parameters, so be sure to not include the $name parameter as in the example.




回答6:


Add below code into functions.php to include your image in all the emails (like a signature logo).

function attachInlineLogo() {
    global $phpmailer;
    if (!( $phpmailer instanceof PHPMailer )) {
        require_once ABSPATH . WPINC . '/class-phpmailer.php';
        require_once ABSPATH . WPINC . '/class-smtp.php';
        $phpmailer = new PHPMailer(true);
    }
    $strFilePath = 'ABSOLUTE LOGO PATH';
    $strFileUID  = 'UNIQUE-UID'; //UID TO USE IN HTML TEMPLATE
    $strFileName = 'LOGO NAME';
    if (is_file($strFilePath)) {
        $phpmailer->SMTPKeepAlive = true;
        $phpmailer->AddEmbeddedImage($strFilePath, $strFileUID, $strFileName);
    }
}

add_action('phpmailer_init', 'attachInlineLogo');

In your HTML code

<img src='cid:UNIQUE-UID' />


来源:https://stackoverflow.com/questions/15646187/display-inline-image-attachments-with-wp-mail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!