function
wp_mail(
$to
,
$subject
,
$message
,
$headers
=
''
,
$attachments
=
array
() ) {
$atts
= apply_filters(
'wp_mail'
, compact(
'to'
,
'subject'
,
'message'
,
'headers'
,
'attachments'
) );
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
) );
}
global
$phpmailer
;
if
( ! (
$phpmailer
instanceof
PHPMailer ) ) {
require_once
ABSPATH . WPINC .
'/class-phpmailer.php'
;
require_once
ABSPATH . WPINC .
'/class-smtp.php'
;
$phpmailer
=
new
PHPMailer( true );
}
$cc
=
$bcc
=
$reply_to
=
array
();
if
(
empty
(
$headers
) ) {
$headers
=
array
();
}
else
{
if
( !
is_array
(
$headers
) ) {
$tempheaders
=
explode
(
"\n"
,
str_replace
(
"\r\n"
,
"\n"
,
$headers
) );
}
else
{
$tempheaders
=
$headers
;
}
$headers
=
array
();
if
( !
empty
(
$tempheaders
) ) {
foreach
( (
array
)
$tempheaders
as
$header
) {
if
(
strpos
(
$header
,
':'
) === false ) {
if
( false !==
stripos
(
$header
,
'boundary='
) ) {
$parts
= preg_split(
'/boundary=/i'
, trim(
$header
) );
$boundary
= trim(
str_replace
(
array
(
"'"
, '"
' ), '
',
$parts
[1] ) );
}
continue
;
}
list(
$name
,
$content
) =
explode
(
':'
, trim(
$header
), 2 );
$name
= trim(
$name
);
$content
= trim(
$content
);
switch
(
strtolower
(
$name
) ) {
case
'from'
:
$bracket_pos
=
strpos
(
$content
,
'<'
);
if
(
$bracket_pos
!== false ) {
if
(
$bracket_pos
> 0 ) {
$from_name
=
substr
(
$content
, 0,
$bracket_pos
- 1 );
$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
);
}
elseif
(
''
!== trim(
$content
) ) {
$from_email
= trim(
$content
);
}
break
;
case
'content-type'
:
if
(
strpos
(
$content
,
';'
) !== false ) {
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
=
''
;
}
}
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
:
$headers
[trim(
$name
)] = trim(
$content
);
break
;
}
}
}
}
$phpmailer
->clearAllRecipients();
$phpmailer
->clearAttachments();
$phpmailer
->clearCustomHeaders();
$phpmailer
->clearReplyTos();
if
( !isset(
$from_name
) )
$from_name
=
'WordPress'
;
if
( !isset(
$from_email
) ) {
$sitename
=
strtolower
(
$_SERVER
[
'SERVER_NAME'
] );
if
(
substr
(
$sitename
, 0, 4 ) ==
'www.'
) {
$sitename
=
substr
(
$sitename
, 4 );
}
$from_email
=
'wordpress@'
.
$sitename
;
}
$from_email
= apply_filters(
'wp_mail_from'
,
$from_email
);
$from_name
= apply_filters(
'wp_mail_from_name'
,
$from_name
);
try
{
$phpmailer
->setFrom(
$from_email
,
$from_name
, false );
}
catch
( phpmailerException
$e
) {
$mail_error_data
= compact(
'to'
,
'subject'
,
'message'
,
'headers'
,
'attachments'
);
$mail_error_data
[
'phpmailer_exception_code'
] =
$e
->getCode();
do_action(
'wp_mail_failed'
,
new
WP_Error(
'wp_mail_failed'
,
$e
->getMessage(),
$mail_error_data
) );
return
false;
}
$phpmailer
->Subject =
$subject
;
$phpmailer
->Body =
$message
;
$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
{
$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
( phpmailerException
$e
) {
continue
;
}
}
}
$phpmailer
->isMail();
if
( !isset(
$content_type
) )
$content_type
=
'text/plain'
;
$content_type
= apply_filters(
'wp_mail_content_type'
,
$content_type
);
$phpmailer
->ContentType =
$content_type
;
if
(
'text/html'
==
$content_type
)
$phpmailer
->isHTML( true );
if
( !isset(
$charset
) )
$charset
= get_bloginfo(
'charset'
);
$phpmailer
->CharSet = apply_filters(
'wp_mail_charset'
,
$charset
);
if
( !
empty
(
$headers
) ) {
foreach
( (
array
)
$headers
as
$name
=>
$content
) {
$phpmailer
->addCustomHeader( sprintf(
'%1$s: %2$s'
,
$name
,
$content
) );
}
if
( false !==
stripos
(
$content_type
,
'multipart'
) && !
empty
(
$boundary
) )
$phpmailer
->addCustomHeader( sprintf(
"Content-Type: %s;\n\t boundary=\"%s\""
,
$content_type
,
$boundary
) );
}
if
( !
empty
(
$attachments
) ) {
foreach
(
$attachments
as
$attachment
) {
try
{
$phpmailer
->addAttachment(
$attachment
);
}
catch
( phpmailerException
$e
) {
continue
;
}
}
}
do_action_ref_array(
'phpmailer_init'
,
array
( &
$phpmailer
) );
try
{
return
$phpmailer
->send();
}
catch
( phpmailerException
$e
) {
$mail_error_data
= compact(
'to'
,
'subject'
,
'message'
,
'headers'
,
'attachments'
);
$mail_error_data
[
'phpmailer_exception_code'
] =
$e
->getCode();
do_action(
'wp_mail_failed'
,
new
WP_Error(
'wp_mail_failed'
,
$e
->getMessage(),
$mail_error_data
) );
return
false;
}
}
To send HTML formatted mail, you also can specify the Content-Type HTTP header in the
$headers
parameter:$to
=
'sendto@example.com'
;
$subject
=
'The subject'
;
$body
=
'The email body content'
;
$headers
=
array
(
'Content-Type: text/html; charset=UTF-8'
);
wp_mail(
$to
,
$subject
,
$body
,
$headers
);
Example using the array form of
$headers
:<?php
// assumes $to, $subject, $message have already been defined earlier...
$headers
[] =
'From: Me Myself <me@example.net>'
;
$headers
[] =
'Cc: John Q Codex <jqc@wordpress.org>'
;
$headers
[] =
'Cc: iluvwp@wordpress.org'
;
// note you can just use a simple email address
wp_mail(
$to
,
$subject
,
$message
,
$headers
);
?>
Here’s an example of a basic configuration for SMTP (so phpmailer will be used instead of php’s mail()):
add_action(
'phpmailer_init'
,
'mailer_config'
, 10, 1);
function
mailer_config(PHPMailer
$mailer
){
$mailer
->IsSMTP();
$mailer
->Host =
"mail.telemar.it"
;
// your SMTP server
$mailer
->Port = 25;
$mailer
->SMTPDebug = 2;
// write 0 if you don't want to see client/server communication in page
$mailer
->CharSet =
"utf-8"
;
}
Here’s an example of a basic error logging:
add_action(
'wp_mail_failed'
,
'log_mailer_errors'
, 10, 1);
function
log_mailer_errors(){
$fn
= ABSPATH .
'/mail.log'
;
// say you've got a mail.log file in your server root
$fp
=
fopen
(
$fn
,
'a'
);
fputs
(
$fp
,
"Mailer Error: "
.
$mailer
->ErrorInfo .
"\n"
);
fclose(
$fp
);
}
Then use wp_mail() to send your mail.
If you’re using it for sending a form and your form’s action is the page’s permalink, you can do some basic checking for $_POST lenght/count to see if the page comes from a form submission.
if
(
count
(
$_POST
) != 0){
// on top of page
// Then collect form data and try to send the form and write messages and so on...
// Note: set $mailer->SMTPDebug to 0 to prevent it to write server messages on the page
}
NOTE: if you are using MAMP PRO to test from your local server, you should:
– go to the Postfix panel
– write your current virtual server as the ‘domain of outgoing email’
– activate ‘use a smart host for routing’
– write your provider’s smtp server (the same you are using in your mail client config)
– Eventually add authentication (then you should also setup the credentials in the phpmailer_init action)
Combining Content-Type(HTML) and From (Site name and “from” email)
$to
=
'emailsendto@example.com'
;
$subject
=
'The subject'
;
$body
=
'The email body content'
;
$headers
=
array
(
'Content-Type: text/html; charset=UTF-8'
,
'From: My Site Name <support@example.com'
);
wp_mail(
$to
,
$subject
,
$body
,
$headers
);
Basic usage example:
<?php wp_mail(
'me@example.net'
,
'The subject'
,
'The message'
); ?>
Add attachment and
From
header:<?php
$attachments
=
array
( WP_CONTENT_DIR .
'/uploads/file_to_attach.zip'
);
$headers
=
'From: My Name <myname@example.com>'
.
"\r\n"
;
wp_mail(
'test@example.org'
,
'subject'
,
'message'
,
$headers
,
$attachments
);
?>
Switch to HTML formatted email (using the
wp_mail_content_type
filter):<?php
add_filter(
'wp_mail_content_type'
,
'wpdocs_set_html_mail_content_type'
);
$to
=
'sendto@example.com'
;
$subject
=
'The subject'
;
$body
=
'The email body content'
;
wp_mail(
$to
,
$subject
,
$body
);
// Reset content-type to avoid conflicts -- https://core.trac.wordpress.org/ticket/23578
remove_filter(
'wp_mail_content_type'
,
'wpdocs_set_html_mail_content_type'
);
function
wpdocs_set_html_mail_content_type() {
return
'text/html'
;
}
?>
Expand full source code
Sending to multiple recipients:
<?php
$multiple_recipients
=
array
(
'recipient1@example.com'
,
'recipient2@foo.example.com'
);
$subj
=
'The email subject'
;
$body
=
'This is the body of the email'
;
wp_mail(
$multiple_recipients
,
$subj
,
$body
);
?>
If you need to set the Reply-To address, note that the syntax which PHPMailer needs is pretty specific. The email address must be enclosed within
<>
characters. It’s also advisable to set the “reply to” name.$headers
=
array
(
'Reply-To: Person Name <person.name@example.com>'
,
);
Having spent nearly a day banging my head against this one, I would strongly recommend that the doc for wp_mail() include the tip that many servers will require that a mail user account be created with the email address of wordpress@domain.com before this function will work. I would have NEVER figured that one out without many hours of google searches.
As of 4.6 header from can’t be a post variable, need to be set before otherwise your site will show php error “Fatal error: Uncaught exception ‘phpmailerException’ with message ‘Invalid address: (setFrom)”
This is due to ‘from email’ being set as variable and is not yet being passed by form submit.
$headers
=
"From: $name <$email>"
.
"\r\n"
;
Fix by predefining a variable for both $name and $email that will be overwritten after submit(ex.1), or set hardcoded(ex.2).
ex.1
$name
=
"Site name"
;
$email
=
"info@sitename.com"
;
if
(isset
$_POST
[
"name"
]){
$name
= sanitize_text_field(
$_POST
[
"name"
]);
$email
= sanitize_email(
$_POST
[
"email"
]);
}
ex.2
$headers
=
"From: Site name <info@sitename.com>"
.
"\r\n"
;
It’s important to know that this function might fail if you specify an empty body, even if using a SMTP.
wp_mail(
'email@provider.com'
,
'Subject'
,
''
);
// returns false, the email was not sent
wp_mail(
'email@provider.com'
,
'Subject'
,
'Body'
);
// returns true (if everything else is working)
<?php
//combining in one header the From and content-type
$headers[] = 'Content-Type: text/html; charset=UTF-8';
$headers[] = 'From: Wishio Team ' . "\r\n";
wp_mail( $to, $subject, $message, $headers);
?>