wp_mail() │ WP 1.2.1
Отправляет письмо на почту. Похожа на mail() в PHP.
Имя отправителя по умолчанию: WordPress, а email по умолчанию: wordpress@yoursite.com. Их можно переписать изменив заголовок письма на:
From: Example User <email@example.com>
Функция использует фильтры wp_mail_from и wp_mail_from_name , которые влияют на адрес email'a и имя отправителя, соответственно, при этом поле From (от кого) собирается заново. Если только wp_mail_from (email) возвращает значение, то имя указываться не будет вообще: (From: email@example.com)
Тип письма по умолчанию text/plain, а значит в теле письма нельзя использовать html теги. Изменить тип письма можно через фильтр wp_mail_content_type или указав заголовок: content-type: text/html.
Кодировка по умолчанию соответствует кодировке блога (обычно utf-8). Кодировка устанавливается через фильтр wp_mail_charset .
Для работы этой функции сервер должен работать с SMTP и должен быть установлен smtp_port в php.ini.
Pluggable функция — эту функцию можно заменить из плагина. Это значит, что она будет работать (подключается) только после подключения всех плагинов, а до этого момента функция еще не определена... Поэтому нельзя вызывать эту и зависящие от неё функции прямо из кода плагина. Их нужно вызывать через хук plugins_loaded или позднее, например хук init .
Замена функции (переопределение) — в must-use или обычном плагине можно создать функцию с таким же названием, тогда она заменит текущую функцию.
Возвращает
true|false. true — удалось отправить письмо. false — не удалось.
true не означает, что письмо дошло до адресата, а означает только то, что функция проделала всю процедуру отправки письма без ошибок.
Использование
wp_mail( $to, $subject, $message, $headers, $attachments, $embeds );
$to(строка/массив) (обязательный)
email получателя письма. Несколько получателей указываются в массиве или через запятую в строке.
$subject(строка) (обязательный)
Тема письма (заголовок).
$message(строка) (обязательный)
Тело письма (содержание, контент).
$headers(строка/массив)
Заголовки письма, указывающие на его атрибуты. Для продвинутого использования. Может быть:
from - от кого. Пр. webmaster@example.com
content-type - text/html , text/plain
cc - some@gmail.com — точная копия (carbon copy) — вторичные получатели письма, которым направляется копия. Они видят и знают о наличии друг друга.
bcc - some@gmail.com — скрытая точная копия (blind carbon copy) — скрытые получатели письма - их адреса не показываются другим получателям.
reply-to - FromEmail@example.com
и любые другие произвольные параметры.
По умолчанию: ''
$attachments(строка/массив)
Файлы, которые следует прикрепить к письму. Указываем полный путь до файла (название файла включительно). Если нужно прикрепить несколько файлов указываем их названия в массиве или в строке через перенос строки.
По умолчанию: array()
Примеры
#1 Пример использования массива для указания заголовков письма:
$to = 'me@example.com';
$subject = 'The subject';
$message = 'The message.';
// удалим фильтры, которые могут изменять заголовок $headers
// remove_all_filters( 'wp_mail_from' );
// remove_all_filters( 'wp_mail_from_name' );
$headers = array(
'From: Me Myself <me@example.net>',
'content-type: text/html',
'cc: John Q Codex <jqc@wordpress.org>',
'cc: John2 Codex <j2qc@wordpress.org>',
'bcc: iluvwp@wordpress.org', // тут можно использовать только простой email адрес
);
wp_mail( $to, $subject, $message, $headers );
#2 Изменим тип письма на html
Этот пример показывает как изменить тип письма на html, используя фильтр wp_mail_content_type:
add_filter( 'wp_mail_content_type', function( $content_type ){
return "text/html";
} );
wp_mail( 'me@example.com', 'The subject', '<p>The <em>HTML</em> message</p>');
#3 Укажем свой адрес email в заголовке письма:
add_filter( 'wp_mail_from', 'vortal_wp_mail_from' );
function vortal_wp_mail_from( $email_address ){
return 'xxx@yyy.com';
}
// получим заголовок: WordPress <xxx@yyy.com>
#4 Пример отправки письма
Отправим письмо от My Name <myname@mydomain.com> с прикрепленным файлом attach.zip:
На некоторых серверах (хостингах) в поле FROM (в части email) обязательно должен фигурировать домен сайта, иначе, например, яндекс почта не получит письмо. Проверял на хостинге Бегет.
Т.е. в этом случае лучше не указывать From: , а изменить только часть этого поля, только имя, через фильтр:
add_filter( 'wp_mail_from_name', function($from_name){
return 'Мое имя, а не WordPress'; // тут можно указать свою почту: asd@asd.ru
} );
// удалим фильтры, которые могут изменять заголовок $headers
// remove_all_filters( 'wp_mail_from' );
// remove_all_filters( 'wp_mail_from_name' );
$attachments = array(WP_CONTENT_DIR . '/uploads/attach.zip');
$headers = 'From: My Name <myname@mydomain.com>' . "\r\n";
wp_mail('test@test.com', 'Тема', 'Содержание', $headers, $attachments);
// test@test.com - кому отправляем.
#5 Отправим письмо двум пользователям сразу и зададим формат письма html:
$multiple_to_recipients = array(
'recipient1@example.com',
'recipient2@foo.example.com'
);
add_filter( 'wp_mail_content_type', 'set_html_content_type' );
wp_mail( $multiple_to_recipients, 'The subject', '<p>The <em>HTML</em> message</p>' );
// Сбросим content-type, чтобы избежать возможного конфликта
remove_filter( 'wp_mail_content_type', 'set_html_content_type' );
function set_html_content_type() {
return 'text/html';
}
#6 Укажем имя в заголовке письма:
add_filter( 'wp_mail_from_name', 'vortal_wp_mail_from_name' );
function vortal_wp_mail_from_name( $email_from ){
return 'XXX';
}
// получим заголовок: XXX <wordpress@yoursite.com>
#7 Дебаг wp_mail: Как перехватить ошибки возникшие при отправке письма
Чтобы перехватить ошибки и посмотреть полезные сообщения которые может отправить SMTP сервер или сам WordPress. Можно использовать следующих хук:
add_action( 'wp_mail_failed', 'mail_failed_error_log' );
function mail_failed_error_log( \WP_Error $wp_error ) {
global $phpmailer;
$err_data = json_encode( $wp_error->get_error_data(), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE );
$msg = <<<MSG
wp_email() Error:
- PHPMailer ErrorInfo: {$phpmailer->ErrorInfo}
- WP_Error Message: {$wp_error->get_error_message()}
- WP_Error Error Data: {$err_data}
MSG;
error_log( $msg );
}
Этот хук нужно добавить до того, как будет использована функция wp_mail().
Добавить свой пример
Заметки
Global. PHPMailer\PHPMailer\PHPMailer. $phpmailer
Список изменений
С версии 1.2.1
Введена.
С версии 5.5.0
is_email() is used for email validation, instead of PHPMailer's default validator.
С версии 6.9.0
Added $embeds parameter.
С версии 6.9.0
Improved Content-Type header handling for multipart messages.
Код wp_mail() wp mail
WP 6.9
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array(), $embeds = array() ) {
// Compact the input, apply the filters, and extract them back out.
/**
* Filters the wp_mail() arguments.
*
* @since 2.2.0
*
* @param array $args {
* Array of the `wp_mail()` arguments.
*
* @type string|string[] $to Array or comma-separated list of email addresses to send message.
* @type string $subject Email subject.
* @type string $message Message contents.
* @type string|string[] $headers Additional headers.
* @type string|string[] $attachments Paths to files to attach.
* @type string|string[] $embeds Paths to files to embed.
* }
*/
$atts = apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments', 'embeds' ) );
/**
* Filters whether to preempt sending an email.
*
* Returning a non-null value will short-circuit {@see wp_mail()}, returning
* that value instead. A boolean return value should be used to indicate whether
* the email was successfully sent.
*
* @since 5.7.0
*
* @param null|bool $return Short-circuit return value.
* @param array $atts {
* Array of the `wp_mail()` arguments.
*
* @type string|string[] $to Array or comma-separated list of email addresses to send message.
* @type string $subject Email subject.
* @type string $message Message contents.
* @type string|string[] $headers Additional headers.
* @type string|string[] $attachments Paths to files to attach.
* @type string|string[] $embeds Paths to files to embed.
* }
*/
$pre_wp_mail = apply_filters( 'pre_wp_mail', null, $atts );
if ( null !== $pre_wp_mail ) {
return $pre_wp_mail;
}
if ( isset( $atts['to'] ) ) {
$to = $atts['to'];
}
if ( ! is_array( $to ) ) {
$to = explode( ',', $to );
}
if ( isset( $atts['subject'] ) ) {
$subject = $atts['subject'];
}
if ( isset( $atts['message'] ) ) {
$message = $atts['message'];
}
if ( isset( $atts['headers'] ) ) {
$headers = $atts['headers'];
}
if ( isset( $atts['attachments'] ) ) {
$attachments = $atts['attachments'];
}
if ( ! is_array( $attachments ) ) {
$attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
}
if ( isset( $atts['embeds'] ) ) {
$embeds = $atts['embeds'];
}
if ( ! is_array( $embeds ) ) {
$embeds = explode( "\n", str_replace( "\r\n", "\n", $embeds ) );
}
global $phpmailer;
// (Re)create it, if it's gone missing.
if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
require_once ABSPATH . WPINC . '/class-wp-phpmailer.php';
$phpmailer = new WP_PHPMailer( true );
$phpmailer::$validator = static function ( $email ) {
return (bool) is_email( $email );
};
}
// Headers.
$cc = array();
$bcc = array();
$reply_to = array();
if ( empty( $headers ) ) {
$headers = array();
} else {
if ( ! is_array( $headers ) ) {
/*
* Explode the headers out, so this function can take
* both string headers and an array of headers.
*/
$tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
} else {
$tempheaders = $headers;
}
$headers = array();
// If it's actually got contents.
if ( ! empty( $tempheaders ) ) {
// Iterate through the raw headers.
foreach ( (array) $tempheaders as $header ) {
if ( ! str_contains( $header, ':' ) ) {
if ( false !== stripos( $header, 'boundary=' ) ) {
$parts = preg_split( '/boundary=/i', trim( $header ) );
$boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
}
continue;
}
// Explode them out.
list( $name, $content ) = explode( ':', trim( $header ), 2 );
// Cleanup crew.
$name = trim( $name );
$content = trim( $content );
switch ( strtolower( $name ) ) {
// Mainly for legacy -- process a "From:" header if it's there.
case 'from':
$bracket_pos = strpos( $content, '<' );
if ( false !== $bracket_pos ) {
// Text before the bracketed email is the "From" name.
if ( $bracket_pos > 0 ) {
$from_name = substr( $content, 0, $bracket_pos );
$from_name = str_replace( '"', '', $from_name );
$from_name = trim( $from_name );
}
$from_email = substr( $content, $bracket_pos + 1 );
$from_email = str_replace( '>', '', $from_email );
$from_email = trim( $from_email );
// Avoid setting an empty $from_email.
} elseif ( '' !== trim( $content ) ) {
$from_email = trim( $content );
}
break;
case 'content-type':
if ( str_contains( $content, ';' ) ) {
list( $type, $charset_content ) = explode( ';', $content );
$content_type = trim( $type );
if ( false !== stripos( $charset_content, 'charset=' ) ) {
$charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
} elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
$boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
$charset = '';
if ( preg_match( '~^multipart/(\S+)~', $content_type, $matches ) ) {
$content_type = 'multipart/' . strtolower( $matches[1] ) . '; boundary="' . $boundary . '"';
}
}
// Avoid setting an empty $content_type.
} elseif ( '' !== trim( $content ) ) {
$content_type = trim( $content );
}
break;
case 'cc':
$cc = array_merge( (array) $cc, explode( ',', $content ) );
break;
case 'bcc':
$bcc = array_merge( (array) $bcc, explode( ',', $content ) );
break;
case 'reply-to':
$reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
break;
default:
// Add it to our grand headers array.
$headers[ trim( $name ) ] = trim( $content );
break;
}
}
}
}
// Empty out the values that may be set.
$phpmailer->clearAllRecipients();
$phpmailer->clearAttachments();
$phpmailer->clearCustomHeaders();
$phpmailer->clearReplyTos();
$phpmailer->Body = '';
$phpmailer->AltBody = '';
/*
* Reset encoding to 8-bit, as it may have been automatically downgraded
* to 7-bit by PHPMailer (based on the body contents) in a previous call
* to wp_mail().
*
* See https://core.trac.wordpress.org/ticket/33972
*/
$phpmailer->Encoding = PHPMailer\PHPMailer\PHPMailer::ENCODING_8BIT;
// Set "From" name and email.
// If we don't have a name from the input headers.
if ( ! isset( $from_name ) ) {
$from_name = 'WordPress';
}
/*
* If we don't have an email from the input headers, default to wordpress@$sitename
* Some hosts will block outgoing mail from this address if it doesn't exist,
* but there's no easy alternative. Defaulting to admin_email might appear to be
* another option, but some hosts may refuse to relay mail from an unknown domain.
* See https://core.trac.wordpress.org/ticket/5007.
*/
if ( ! isset( $from_email ) ) {
// Get the site domain and get rid of www.
$sitename = wp_parse_url( network_home_url(), PHP_URL_HOST );
$from_email = 'wordpress@';
if ( null !== $sitename ) {
if ( str_starts_with( $sitename, 'www.' ) ) {
$sitename = substr( $sitename, 4 );
}
$from_email .= $sitename;
}
}
/**
* Filters the email address to send from.
*
* @since 2.2.0
*
* @param string $from_email Email address to send from.
*/
$from_email = apply_filters( 'wp_mail_from', $from_email );
/**
* Filters the name to associate with the "from" email address.
*
* @since 2.3.0
*
* @param string $from_name Name associated with the "from" email address.
*/
$from_name = apply_filters( 'wp_mail_from_name', $from_name );
try {
$phpmailer->setFrom( $from_email, $from_name );
} catch ( PHPMailer\PHPMailer\Exception $e ) {
$mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
$mail_error_data['phpmailer_exception_code'] = $e->getCode();
/** This filter is documented in wp-includes/pluggable.php */
do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
return false;
}
// Set mail's subject and body.
$phpmailer->Subject = $subject;
$phpmailer->Body = $message;
// Set destination addresses, using appropriate methods for handling addresses.
$address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
foreach ( $address_headers as $address_header => $addresses ) {
if ( empty( $addresses ) ) {
continue;
}
foreach ( (array) $addresses as $address ) {
try {
// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>".
$recipient_name = '';
if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
if ( count( $matches ) === 3 ) {
$recipient_name = $matches[1];
$address = $matches[2];
}
}
switch ( $address_header ) {
case 'to':
$phpmailer->addAddress( $address, $recipient_name );
break;
case 'cc':
$phpmailer->addCC( $address, $recipient_name );
break;
case 'bcc':
$phpmailer->addBCC( $address, $recipient_name );
break;
case 'reply_to':
$phpmailer->addReplyTo( $address, $recipient_name );
break;
}
} catch ( PHPMailer\PHPMailer\Exception $e ) {
continue;
}
}
}
// Set to use PHP's mail().
$phpmailer->isMail();
// Set Content-Type and charset.
// If we don't have a Content-Type from the input headers.
if ( ! isset( $content_type ) ) {
$content_type = 'text/plain';
}
/**
* Filters the wp_mail() content type.
*
* @since 2.3.0
*
* @param string $content_type Default wp_mail() content type.
*/
$content_type = apply_filters( 'wp_mail_content_type', $content_type );
$phpmailer->ContentType = $content_type;
// Set whether it's plaintext, depending on $content_type.
if ( 'text/html' === $content_type ) {
$phpmailer->isHTML( true );
}
// If we don't have a charset from the input headers.
if ( ! isset( $charset ) ) {
$charset = get_bloginfo( 'charset' );
}
/**
* Filters the default wp_mail() charset.
*
* @since 2.3.0
*
* @param string $charset Default email charset.
*/
$phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
// Set custom headers.
if ( ! empty( $headers ) ) {
foreach ( (array) $headers as $name => $content ) {
// Only add custom headers not added automatically by PHPMailer.
if ( ! in_array( $name, array( 'MIME-Version', 'X-Mailer' ), true ) ) {
try {
$phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
} catch ( PHPMailer\PHPMailer\Exception $e ) {
continue;
}
}
}
}
if ( ! empty( $attachments ) ) {
foreach ( $attachments as $filename => $attachment ) {
$filename = is_string( $filename ) ? $filename : '';
try {
$phpmailer->addAttachment( $attachment, $filename );
} catch ( PHPMailer\PHPMailer\Exception $e ) {
continue;
}
}
}
if ( ! empty( $embeds ) ) {
foreach ( $embeds as $key => $embed_path ) {
/**
* Filters the arguments for PHPMailer's addEmbeddedImage() method.
*
* @since 6.9.0
*
* @param array $args {
* An array of arguments for `addEmbeddedImage()`.
* @type string $path The path to the file.
* @type string $cid The Content-ID of the image. Default: The key in the embeds array.
* @type string $name The filename of the image.
* @type string $encoding The encoding of the image. Default: 'base64'.
* @type string $type The MIME type of the image. Default: empty string, which lets PHPMailer auto-detect.
* @type string $disposition The disposition of the image. Default: 'inline'.
* }
*/
$embed_args = apply_filters(
'wp_mail_embed_args',
array(
'path' => $embed_path,
'cid' => (string) $key,
'name' => basename( $embed_path ),
'encoding' => 'base64',
'type' => '',
'disposition' => 'inline',
)
);
try {
$phpmailer->addEmbeddedImage(
$embed_args['path'],
$embed_args['cid'],
$embed_args['name'],
$embed_args['encoding'],
$embed_args['type'],
$embed_args['disposition']
);
} catch ( PHPMailer\PHPMailer\Exception $e ) {
continue;
}
}
}
/**
* Fires after PHPMailer is initialized.
*
* @since 2.2.0
*
* @param PHPMailer $phpmailer The PHPMailer instance (passed by reference).
*/
do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
$mail_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
// Send!
try {
$send = $phpmailer->send();
/**
* Fires after PHPMailer has successfully sent an email.
*
* The firing of this action does not necessarily mean that the recipient(s) received the
* email successfully. It only means that the `send` method above was able to
* process the request without any errors.
*
* @since 5.9.0
*
* @param array $mail_data {
* An array containing the email recipient(s), subject, message, headers, and attachments.
*
* @type string[] $to Email addresses to send message.
* @type string $subject Email subject.
* @type string $message Message contents.
* @type string[] $headers Additional headers.
* @type string[] $attachments Paths to files to attach.
* @type string[] $embeds Paths to files to embed.
* }
*/
do_action( 'wp_mail_succeeded', $mail_data );
return $send;
} catch ( PHPMailer\PHPMailer\Exception $e ) {
$mail_data['phpmailer_exception_code'] = $e->getCode();
/**
* Fires after a PHPMailer\PHPMailer\Exception is caught.
*
* @since 4.4.0
*
* @param WP_Error $error A WP_Error object with the PHPMailer\PHPMailer\Exception message, and an array
* containing the mail recipient, subject, message, headers, and attachments.
*/
do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_data ) );
return false;
}
}
Cвязанные функции