'digest',
'recipient' => ITSEC_Notification_Center::R_USER_LIST_ADMIN_UPGRADE,
'schedule' => array(
'min' => ITSEC_Notification_Center::S_DAILY,
'max' => ITSEC_Notification_Center::S_WEEKLY,
),
'subject_editable' => true,
'optional' => true,
);
return $notifications;
}
/**
* Get the digest notification strings.
*
* @return array
*/
public function notification_strings() {
$description = esc_html__( 'During periods of heavy attack, iThemes Security can generate a LOT of email.', 'better-wp-security' );
if ( ITSEC_Core::is_pro() ) {
$features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts, file change detection scans, and privilege escalations.' );
} else {
$features = esc_html__( 'The Security Digest reduces the number of emails sent so you can receive a summary of lockouts and file change detection scans.' );
}
return array(
'label' => esc_html__( 'Security Digest', 'better-wp-security' ),
'description' => $description . ' ' . $features,
'subject' => esc_html__( 'Daily Security Digest', 'better-wp-security' ), // Default schedule is Daily
);
}
/**
* Send the daily digest email.
*
* @since 2.6.0
*
* @param bool $sent
* @param int $last_sent
* @param array $data
*
* @return bool
*/
public function send_daily_digest( $sent, $last_sent, $data ) {
/** @var ITSEC_Lockout $itsec_lockout */
global $itsec_lockout;
$send_email = false;
$df = get_option( 'date_format' );
$nc = ITSEC_Core::get_notification_center();
switch ( $nc->get_schedule( 'digest' ) ) {
case ITSEC_Notification_Center::S_DAILY:
$title = esc_html__( 'Daily Security Digest', 'better-wp-security' );
$banner_title = sprintf( esc_html__( 'Your Daily Security Digest for %s', 'better-wp-security' ), '' . date_i18n( $df ) . '' );
break;
case ITSEC_Notification_Center::S_WEEKLY:
$period = sprintf(
'%s - %s',
ITSEC_Lib::date_format_i18n_and_local_timezone( $last_sent, $df ),
ITSEC_Lib::date_format_i18n_and_local_timezone( ITSEC_Core::get_current_time_gmt(), $df )
);
$title = esc_html__( 'Weekly Security Digest', 'better-wp-security' );
$banner_title = sprintf( esc_html__( 'Your Weekly Security Digest for %s', 'better-wp-security' ), '' . $period . '' );
break;
case ITSEC_Notification_Center::S_MONTHLY:
$this_day = (int) date( 'j', ITSEC_Core::get_current_time_gmt() );
if ( $this_day <= 3 ) {
$period = date_i18n('F Y', $last_sent );
} else {
$period = sprintf(
'%s - %s',
ITSEC_Lib::date_format_i18n_and_local_timezone( $last_sent, $df ),
ITSEC_Lib::date_format_i18n_and_local_timezone( ITSEC_Core::get_current_time_gmt(), $df )
);
}
$title = esc_html__( 'Monthly Security Digest', 'better-wp-security' );
$banner_title = sprintf( esc_html__( 'Your Monthly Security Digest for %s', 'better-wp-security' ), '' . $period . '' );
break;
default:
$period = sprintf(
'%s - %s',
ITSEC_Lib::date_format_i18n_and_local_timezone( $last_sent, $df ),
ITSEC_Lib::date_format_i18n_and_local_timezone( ITSEC_Core::get_current_time_gmt(), $df )
);
$title = esc_html__( 'Security Digest', 'better-wp-security' );
$banner_title = sprintf( esc_html__( 'Your Security Digest for %s', 'better-wp-security' ), '' . $period . '' );
break;
}
$data_proxy = new ITSEC_Notify_Data_Proxy( $data );
$mail = $nc->mail( 'digest' );
$mail->add_header( $title, $banner_title );
$mail->start_group( 'intro' );
$mail->add_info_box( sprintf( esc_html__( 'The following is a summary of security related activity on your site: %s', 'better-wp-security' ), '' . $mail->get_display_url() . '' ) );
$mail->end_group();
$content = $mail->get_content();
/**
* Fires before the main content of the Security Digest is added.
*
* @param ITSEC_Mail $mail
* @param ITSEC_Notify_Data_Proxy $data_proxy
* @param int $last_sent
*/
do_action( 'itsec_security_digest_before', $mail, $data_proxy, $last_sent );
if ( $content !== $mail->get_content() ) {
$send_email = true;
}
$mail->add_section_heading( esc_html__( 'Lockouts', 'better-wp-security' ), 'lock' );
$user_count = $itsec_lockout->get_lockouts( 'user', array( 'after' => $last_sent, 'current' => false, 'return' => 'count' ) );
$host_count = $itsec_lockout->get_lockouts( 'host', array( 'after' => $last_sent, 'current' => false, 'return' => 'count' ) );
if ( $host_count > 0 || $user_count > 0 ) {
$mail->add_lockouts_summary( $user_count, $host_count );
$send_email = true;
} else {
$mail->add_text( esc_html__( 'No lockouts since the last email check.', 'better-wp-security' ) );
}
if ( $data_proxy->has_message( 'file-change' ) ) {
$mail->add_section_heading( esc_html__( 'File Changes', 'better-wp-security' ), 'folder' );
$mail->add_text( esc_html__( 'File changes detected on the site.', 'better-wp-security' ) );
$send_email = true;
}
if ( ! $send_email ) {
$content = $mail->get_content();
}
/**
* Fires when additional info should be attached to the Security Digest.
*
* @since 3.9.0
*
* @param ITSEC_Mail $mail
* @param ITSEC_Notify_Data_Proxy $data_proxy
* @param int $last_sent
*/
do_action( 'itsec_security_digest_attach_additional_info', $mail, $data_proxy, $last_sent );
if ( ! $send_email && $content !== $mail->get_content() ) {
$send_email = true;
}
$messages = $this->get_general_messages( $data );
if ( $messages ) {
$mail->add_section_heading( esc_html__( 'Messages', 'better-wp-security' ), 'message' );
foreach ( $messages as $message ) {
$mail->add_text( $message );
}
$send_email = true;
}
if ( ! $send_email ) {
return true;
}
$mail->add_details_box( sprintf(
esc_html__( 'For more details, %1$svisit your security logs%2$s', 'better-wp-security' ),
'',
''
) );
if ( apply_filters( 'itsec_security_digest_include_security_check', true ) ) {
$mail->add_divider();
$mail->add_large_text( esc_html__( 'Is your site as secure as it could be?', 'better-wp-security' ) );
$mail->add_text( esc_html__( 'Ensure your site is using recommended settings and features with a security check.', 'better-wp-security' ) );
$mail->add_button( esc_html__( 'Run a Security Check ✓', 'better-wp-security' ), ITSEC_Mail::filter_admin_page_url( ITSEC_Core::get_security_check_page_url() ) );
}
$mail->add_footer();
return $nc->send( 'digest', $mail );
}
/**
* Get general digest messages.
*
* @param array $data
*
* @return string[]
*/
private function get_general_messages( $data ) {
$messages = array();
foreach ( $data as $datum ) {
if ( ! is_array( $datum ) || ! isset( $datum['message'] ) ) {
continue;
}
if ( isset( $datum['type'] ) && 'general' !== $datum['type'] ) {
continue;
}
$messages[] = $datum['message'];
}
return $messages;
}
/**
* Used by the File Change Detection module to tell the notification system about found file changes.
*
* @since 2.6.0
*
* @return null
*/
public function register_file_change() {
_deprecated_function( __METHOD__, '3.9.0', 'ITSEC_Notification_Center::enqueue_data' );
ITSEC_Core::get_notification_center()->enqueue_data( 'digest', array( 'type' => 'file-change' ) );
}
/**
* Set HTML content type for email
*
* @since 4.5
*
* @return string html content type
*/
public function wp_mail_content_type() {
return 'text/html';
}
}
class ITSEC_Notify_Data_Proxy {
/** @var array */
private $data;
/**
* ITSEC_Notify_Data_Proxy constructor.
*
* @param array $data
*/
public function __construct( $data ) { $this->data = $data; }
/**
* Check for a queued message.
*
* @param string $type
*
* @return array|null
*/
public function has_message( $type ) {
foreach ( $this->data as $datum ) {
if ( ! is_array( $datum ) ) {
continue;
}
if ( isset( $datum['type'] ) && $type === $datum['type'] ) {
return $datum;
}
}
return null;
}
/**
* Get all messages of a given type.
*
* @param string $type
*
* @return array
*/
public function get_messages_of_type( $type ) {
$of_type = array();
foreach ( $this->data as $datum ) {
if ( ! is_array( $datum ) ) {
continue;
}
if ( isset( $datum['type'] ) && $type === $datum['type'] ) {
$of_type[] = $datum;
}
}
return $of_type;
}
}