TransWikia.com

How to do string attachment with wp_mail

WordPress Development Asked by Nicautre on November 11, 2021

I’m using a gift card plugin for my woocommerce shop and I would like to add a generated pdf file to allow customers to download the gift card as a pdf.

The idea is to use TCpdf or Fpdf to generate the pdf and output it as a string.

// Close and output PDF document
// This method has several options, check the source code documentation for more information.


echo $pdf->Output('S');

The problem is to get this file as an attachment with wp_mail. Right now, I have this code from the plugin, and i don’t know how to call the pdf :

/**
 * Hooks before the email is sent
 *
 * @since 2.1
 */
do_action( 'kodiak_email_send_before', $this );

$subject = $this->parse_tags( $subject );
$message = $this->parse_tags( $message );
$message = $this->build_email( $message );

$attachments = ??;


$sent = wp_mail( $to, $subject, $message, $this->get_headers(), $attachments );
$log_errors = apply_filters( 'kodiak_log_email_errors', true, $to, $subject, $message );

if( ! $sent && true === $log_errors ) {
  if ( is_array( $to ) ) {
    $to = implode( ',', $to );
  }

  $log_message = sprintf(
    __( "Email from Gift Cards failed to send.nSend time: %snTo: %snSubject: %snn", 'kodiak-giftcards' ),
    date_i18n( 'F j Y H:i:s', current_time( 'timestamp' ) ),
    $to,
    $subject
  );
}

Is someone can help me with this ?

Thank you for the answer !

3 Answers

It is possible to add an attachment using the standard 'wp_mail' function, however you would need to hook into the phpmailer_init action to do so.

Because this will require calling another function where you don't have any context, you may need to register the action function anonymously with the use ( $attachments ) statement, store the attachment content as a global variable or property, or place the attachment generation code into the new function.

I can see that OP's code seems to be in the context of a class method, so I'll try to create an example which should be compatible / consistent.

    // Previous Code...
    
    // Use this action to generate and/or attach files.
    add_filter( 'phpmailer_init', array( $this, 'add_attachments' ) );
    // And/or store the attachments as a property.
    $this->set_attachments( $attachments );
    
    $sent = wp_mail( $to, $subject, $message, $this->get_headers() );

    // Log errors etc...
    if ( ! $sent ) {
        //...
        $this->log_error( $error_message );
    }
}

/**
 * Add attachments to the email.
 *
 * This method must be public in order to work as an action.
 * @param PHPMailerPHPMailerPHPMailer $phpmailer
 */
public function add_attachments( $phpmailer ) {
    // Remove filter to prevent attaching the files to subsequent emails.
    remove_action( 'phpmailer_init', array( $this, 'add_attachments' ) );
    // Get or generate the attachments somehow.
    foreach ( $this->get_attachments() as $filename, $file_contents ) {
        try {
            $phpmailer->addStringAttachment( $file_contents, $filename );
        } catch( Exception $ex ) {
            // An exception may thrown which would prevent the remaining files from being attached, so we'll catch these and log the errors.
            // This email may be sent without attachments. Do not try/catch if you don't want the email to be sent without all the attachments.
            $this->log_error( $ex->getMessage() );
        }
    }
}

/**
 * Abstraction for the logging code to make it reusable.
 * @param string $log_message
 */
protected function log_error( $log_message ) {
    if ( ! $this->log_errors ) {
        return;
    }
    // Log errors here.
}

Answered by Shaun Cockerill on November 11, 2021

This is kind of tricky to do, but it is possible. Write a class which will extend PHPMailer. Override the addAttachment method, so in a certain condition (ex. you make a Boolean class variable) it will call addStringAttachment from the original class and in every other cases the addAttachment class. All you have to do is to set

$attachment = array("your content goes here");

When this is done, make sure that the global $phpmailer variable is an instance of your class and then create the specific condition. wp_mail will call the addAttachment from your class, and together with your special condition the attachment will be sent without saving the file.

Answered by Zsolti on November 11, 2021

Usually I proceed like this

$attachment = array(filepath);

Where filepath is the path to your file.

Answered by Friss on November 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP