Hook into admin_notices after sending mail

This workaround is far from ideal, but it gets the job done.

On $mail_sent == true set a post meta. In the __construct function add a callback to the admin_head action that checks whether the post meta has been set. If yes, delete the post meta and add the admin_notices action with the callback to the desired admin notice.

class Send_mail {
    public function __construct() {
        add_action( 'init', array($this, 'send_mail'), 30 );
        add_action( 'admin_head', array($this,'check_mail_sent') );

    public function send_mail() {
        if (!isset($_POST['send-confirmation-true'])) {

        // wp_mail() functionality
        // returns true on successful send

        if ($mail_sent == true) {
            update_post_meta($campaign_id, 'mail_sent', 'yes');

    public function check_mail_sent() {
        global $post;
        $mail_sent = get_post_meta( $post->ID, 'mail_sent', true );

        if($mail_sent == 'yes') {
            delete_post_meta($post->ID, 'mail_sent');
            add_action('admin_notices', array($this, 'show_admin_notice') );
        } else if ($mail_sent == 'no') {
            // Can handle a mail fail notice here if needed

    public function show_admin_notice() {
        // output admin notice html