How to send an automated user ‘inactivity’ email?

There are three main parts to your question:

  1. Log the user last login time
  2. Schedule a cron event
  3. Send email if contributors and authors haven’t logged in within 20 days

The first step is adding user meta to track the last login. WordPress does not track the last time a user logs in, so we’re going to have to do it manually.

//* Add action on login to update the last_login user meta
add_action( 'wp_login', 'wpse_207422_user_last_login', 10, 2 );
function wpse_207422_user_last_login( $user_login, $user ) {
  update_user_meta( $user->ID, 'last_login', time() );
}

Next, we check to see if our event is scheduled and if it isn’t, schedule it. This should only run once, but you never know, another plugin might accidentally disable it.

//* Schedule a daily cron event
if( ! wp_next_scheduled( 'wpse_207422_inactivity_reminder' ) ) {
  wp_schedule_event( time(), 'daily', 'wpse_207422_inactivity_reminder' );
}

Finally, add an action for our cron event. The callback will perform a user query targeting contributors and authors and the meta value last_login. The comparison makes sure that the last_login is older than 20 days.

//* Add action to daily cron event
add_action( 'wpse_207422_inactivity_reminder', 'wpse_207422_inactivity_reminder' );
function wpse_207422_inactivity_reminder() {
  //* Get the contributors and authors who haven't logged in in 20 days
  $users = new \WP_User_Query( [
    'role'         => [ 'contributor', 'author', ],
    'meta_key'     => 'last_login',
    'meta_value'   => strtotime( '-20 days' ),
    'meta_compare' => '<',
  ] );
  foreach( $users->get_results() as $user ) {
    wp_mail(
      $user->user_email,
      __( 'Inactivity Notice', 'wpse-207422' ),
      __( 'We notice you have not logged in for 20 days.' ,'wpse-207422' )
    );
  }
}