label */ public static function mailers() { return (array) apply_filters( 'ajsm_mailers', array( 'php' => __( 'Default (PHP mail)', '007aj-smtp-mailer' ), 'smtp' => __( 'Other SMTP', '007aj-smtp-mailer' ), ) ); } /** * Mailer used for the current message (add-ons may route). * * @return string */ public static function active() { $m = (string) Options::get( 'mailer', 'php' ); $m = (string) apply_filters( 'ajsm_active_mailer', $m ); return array_key_exists( $m, self::mailers() ) ? $m : 'php'; } /** * SMTP presets. * * @return array */ public static function presets() { return array( 'fastmail' => array( 'label' => 'Fastmail', 'host' => 'smtp.fastmail.com', 'port' => 465, 'enc' => 'ssl', 'note' => __( 'Create an app password in Fastmail (Settings > Privacy & Security > App passwords, access: SMTP). Username is your full Fastmail address. From Email must be that address or a verified alias.', '007aj-smtp-mailer' ) ), 'gmail' => array( 'label' => 'Gmail (app password)', 'host' => 'smtp.gmail.com', 'port' => 465, 'enc' => 'ssl', 'note' => __( 'Turn on 2-Step Verification, then create an app password at myaccount.google.com/apppasswords. Username is your Gmail address.', '007aj-smtp-mailer' ) ), 'outlook' => array( 'label' => 'Outlook.com / Hotmail', 'host' => 'smtp-mail.outlook.com', 'port' => 587, 'enc' => 'tls', 'note' => __( 'Use your Outlook.com address. If two-step verification is on, use an app password.', '007aj-smtp-mailer' ) ), 'yahoo' => array( 'label' => 'Yahoo Mail', 'host' => 'smtp.mail.yahoo.com', 'port' => 465, 'enc' => 'ssl', 'note' => __( 'Generate an app password in Yahoo Account Security.', '007aj-smtp-mailer' ) ), 'zoho' => array( 'label' => 'Zoho Mail', 'host' => 'smtp.zoho.com', 'port' => 465, 'enc' => 'ssl', 'note' => __( 'EU accounts use smtp.zoho.eu. Use an app-specific password if two-factor login is on.', '007aj-smtp-mailer' ) ), 'icloud' => array( 'label' => 'iCloud Mail', 'host' => 'smtp.mail.me.com', 'port' => 587, 'enc' => 'tls', 'note' => __( 'Create an app-specific password at appleid.apple.com. Username is your iCloud address.', '007aj-smtp-mailer' ) ), 'office365' => array( 'label' => 'Office 365 / GoDaddy', 'host' => 'smtp.office365.com', 'port' => 587, 'enc' => 'tls', 'note' => __( 'SMTP AUTH must be enabled for the mailbox by your Microsoft 365 admin.', '007aj-smtp-mailer' ) ), 'cpanel' => array( 'label' => 'cPanel / hosting mailbox', 'host' => 'mail.' . self::site_domain(), 'port' => 465, 'enc' => 'ssl', 'note' => __( 'Use the mailbox address and password from your hosting control panel. Your host may use a different server name.', '007aj-smtp-mailer' ) ), ); } /** * Site domain without www. * * @return string */ public static function site_domain() { $h = (string) wp_parse_url( home_url(), PHP_URL_HOST ); return preg_replace( '/^www\./', '', $h ); } /** * Filter From email. * * @param string $email Current. * @return string */ public static function from_email( $email ) { $mine = sanitize_email( (string) Options::get( 'from_email', '' ) ); if ( '' === $mine || ! is_email( $mine ) ) { return $email; } $default = 0 === strpos( (string) $email, 'wordpress@' ); return ( Options::get( 'force_from_email' ) || $default ) ? $mine : $email; } /** * Filter From name. * * @param string $name Current. * @return string */ public static function from_name( $name ) { $mine = (string) Options::get( 'from_name', '' ); if ( '' === $mine ) { return $name; } return ( Options::get( 'force_from_name' ) || 'WordPress' === $name ) ? $mine : $name; } /** * Configure PHPMailer. * * @param \PHPMailer\PHPMailer\PHPMailer $phpmailer Instance. */ public static function configure( $phpmailer ) { $s = Options::all(); if ( ! empty( $s['return_path'] ) && is_email( $phpmailer->From ) ) { $phpmailer->Sender = $phpmailer->From; } $reply = sanitize_email( (string) $s['reply_to'] ); if ( $reply && is_email( $reply ) && ! $phpmailer->getReplyToAddresses() ) { $phpmailer->addReplyTo( $reply ); } $mailer = self::active(); if ( 'smtp' === $mailer && '' !== (string) $s['smtp_host'] ) { $phpmailer->isSMTP(); $phpmailer->Host = (string) $s['smtp_host']; $phpmailer->Port = (int) $s['smtp_port']; $enc = (string) $s['smtp_encryption']; $phpmailer->SMTPSecure = in_array( $enc, array( 'ssl', 'tls' ), true ) ? $enc : ''; $phpmailer->SMTPAutoTLS = 'none' === $enc ? (bool) $s['smtp_autotls'] : true; $phpmailer->SMTPAuth = (bool) $s['smtp_auth']; $phpmailer->Timeout = (int) apply_filters( 'ajsm_smtp_timeout', 20 ); if ( $phpmailer->SMTPAuth ) { $phpmailer->Username = (string) $s['smtp_user']; $phpmailer->Password = Options::secret( 'smtp_pass' ); } } elseif ( 'php' === $mailer ) { $phpmailer->isMail(); } if ( null !== self::$transcript ) { $phpmailer->SMTPDebug = 3; $phpmailer->Debugoutput = array( __CLASS__, 'capture' ); } do_action( 'ajsm_phpmailer_configured', $phpmailer, $mailer ); } /** * Capture a debug line. * * @param string $line Line. */ public static function capture( $line ) { if ( null !== self::$transcript && count( self::$transcript ) < 400 ) { self::$transcript[] = rtrim( (string) $line ); } } /** * Record a failure. * * @param \WP_Error $error Error from wp_mail. */ public static function failed( $error ) { if ( ! is_wp_error( $error ) ) { return; } $data = (array) $error->get_error_data(); Options::log_error( $error->get_error_message(), array( 'to' => isset( $data['to'] ) ? $data['to'] : array(), 'subject' => isset( $data['subject'] ) ? $data['subject'] : '', 'mailer' => isset( $data['ajsm_mailer'] ) ? $data['ajsm_mailer'] : self::active(), ) ); } /** * Send a test email. * * @param string $to Recipient. * @param bool $html HTML or plain. * @return array { ok, error, title, advice, transcript } */ public static function send_test( $to, $html = true ) { self::$transcript = array(); $err = ''; $catch = function ( $e ) use ( &$err ) { $err = $e->get_error_message(); }; add_action( 'wp_mail_failed', $catch, 1 ); $type = function () use ( $html ) { return $html ? 'text/html' : 'text/plain'; }; add_filter( 'wp_mail_content_type', $type, 999 ); /* translators: %s: site name */ $subject = sprintf( __( '007AJ SMTP Mailer test email from %s', '007aj-smtp-mailer' ), wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) ); $body = $html ? '

' . esc_html__( 'Congratulations, your WordPress site can send email with 007AJ SMTP Mailer.', '007aj-smtp-mailer' ) . '

' . esc_html( home_url() ) . '

' : __( 'Congratulations, your WordPress site can send email with 007AJ SMTP Mailer.', '007aj-smtp-mailer' ) . "\n\n" . home_url(); $ok = wp_mail( $to, $subject, $body, array( 'X-AJSM-Test: 1' ) ); remove_filter( 'wp_mail_content_type', $type, 999 ); remove_action( 'wp_mail_failed', $catch, 1 ); $lines = self::$transcript; self::$transcript = null; $transcript = Options::mask( implode( "\n", $lines ) ); $out = array( 'ok' => (bool) $ok, 'error' => Options::mask( $err ), 'title' => '', 'advice' => '', 'transcript' => $transcript, ); if ( ! $ok ) { $d = Diagnosis::explain( $err . "\n" . $transcript ); $out['title'] = $d['title']; $out['advice'] = $d['advice']; } return $out; } }