Category Archives: PHP

Setup Mailtrap with WordPress

Mailtrap is a service that captures all mail sent by your site and prevents it from arriving at the intended┬árecipient. It’s really useful for testing and debugging mail without having to write manual checks to ensure your users don’t get spammed with tests.

Setting up Mailtrap with WordPress is pretty straightforward, because all we need to do is overwrite the default SMTP server in the PHPMailer, which is what WordPress uses to send mail. It’s important to note that it will also trap mail sent from plugins like Contact Form 7.

Add the following hook in your theme’s functions.php file or throw this in a plugin:

1
2
3
4
5
6
7
8
9
10
function mailtrap($phpmailer) {
    $phpmailer->isSMTP();
    $phpmailer->Host = 'mailtrap.io';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 25;
    $phpmailer->Username = 'username';
    $phpmailer->Password = 'password';
}
 
add_action('phpmailer_init', 'mailtrap');
function mailtrap($phpmailer) {
    $phpmailer->isSMTP();
    $phpmailer->Host = 'mailtrap.io';
    $phpmailer->SMTPAuth = true;
    $phpmailer->Port = 25;
    $phpmailer->Username = 'username';
    $phpmailer->Password = 'password';
}

add_action('phpmailer_init', 'mailtrap');

Be sure to replace the username and password with your personal ones, which can be found by clicking on your inbox in Mailtrap. Look for the SMTP credentials.

Once the hook is in place, you’re done. Give it a go!

WordPress Upgrade: Peer certificate cannot be authenticated with known CA certificates

I was trying to upgrade WordPress on one of my servers, but kept receiving an SSL-related error:

Peer certificate cannot be authenticated with known CA certificates.

I verified the SSL certificate on the server and there are no issues with it as far as I can tell, but I’d be curious to know if someone else figures out the actual cause.

That said, and as a quick work-around, you can prevent cURL from verifying the certificate just during WordPress upgrades:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
add_action(
    'load-upgrade.php',
    'my_load_upgrade_php'
);
 
function my_load_upgrade_php() {
    add_filter(
        'http_request_args',
        'my_http_request_args',
        10,
        2
    );
}
 
function my_http_request_args($args, $url) {
    $args['sslverify'] = false;
    return $args;
}
add_action(
	'load-upgrade.php',
	'my_load_upgrade_php'
);

function my_load_upgrade_php() {
	add_filter(
		'http_request_args',
		'my_http_request_args',
		10,
		2
	);
}

function my_http_request_args($args, $url) {
	$args['sslverify'] = false;
	return $args;
}

What this will do is set CURLOPT_SSL_VERIFYPEER to false:

1
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false );

Prevent WordPress from automatically purging trash from custom post type

Preface

WordPress has a constant called EMPTY_TRASH_DAYS that it automatically sets to 30. What that means is that WordPress will automatically delete all posts, pages, custom post types, etc, that have been in the trash for 30 or more days.

1
2
3
4
5
6
7
8
// wp-includes/default-constants.php
 
function wp_functionality_constants( ) {
    ...
    if ( !defined( 'EMPTY_TRASH_DAYS' ) )
        define( 'EMPTY_TRASH_DAYS', 30 );
    ...
}
// wp-includes/default-constants.php

function wp_functionality_constants( ) {
	...
	if ( !defined( 'EMPTY_TRASH_DAYS' ) )
		define( 'EMPTY_TRASH_DAYS', 30 );
	...
}

Whenever you trash a post, WordPress creates a meta field called _wp_trash_meta_time containing the time it was trashed.

1
2
3
4
5
6
7
// wp-includes/post.php
 
function wp_trash_post($post_id = 0) {
    ...
    add_post_meta($post_id,'_wp_trash_meta_time', time());
    ...
}
// wp-includes/post.php

function wp_trash_post($post_id = 0) {
	...
	add_post_meta($post_id,'_wp_trash_meta_time', time());
	...
}

WordPress has a daily event scheduled…

1
2
3
4
// wp-admin/admin.php
 
if ( !wp_next_scheduled('wp_scheduled_delete') && !defined('WP_INSTALLING') )
    wp_schedule_event(time(), 'daily', 'wp_scheduled_delete');
// wp-admin/admin.php

if ( !wp_next_scheduled('wp_scheduled_delete') && !defined('WP_INSTALLING') )
	wp_schedule_event(time(), 'daily', 'wp_scheduled_delete');

…that will run a function called wp_scheduled_delete to permanently delete all expired posts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// wp-includes/functions.php
 
function wp_scheduled_delete() {
    global $wpdb;
 
    $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
 
    $posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
 
    foreach ( (array) $posts_to_delete as $post ) {
        $post_id = (int) $post['post_id'];
        if ( !$post_id )
            continue;
 
        $del_post = get_post($post_id);
 
        if ( !$del_post || 'trash' != $del_post->post_status ) {
            delete_post_meta($post_id, '_wp_trash_meta_status');
            delete_post_meta($post_id, '_wp_trash_meta_time');
        } else {
            wp_delete_post($post_id);
        }
    }
    ...
}
// wp-includes/functions.php

function wp_scheduled_delete() {
	global $wpdb;

	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );

	$posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);

	foreach ( (array) $posts_to_delete as $post ) {
		$post_id = (int) $post['post_id'];
		if ( !$post_id )
			continue;

		$del_post = get_post($post_id);

		if ( !$del_post || 'trash' != $del_post->post_status ) {
			delete_post_meta($post_id, '_wp_trash_meta_status');
			delete_post_meta($post_id, '_wp_trash_meta_time');
		} else {
			wp_delete_post($post_id);
		}
	}
	...
}

Continue reading