WireMailTools / $mail
$mail is the API variable for sending email in ProcessWire
It provides both a
one-call send interface and a fluent builder (WireMail) for composing more complex
messages. If a WireMail module (e.g. WireMailSMTP, WireMailgun) is installed, it is
used automatically in place of ProcessWire's default WireMail (which uses PHP's
built-in mail() function.
$mail is accessible in templates as $mail, or wire()->mail and in modules as $this->wire()->mail. There is also the wireMail() function, which returns
a new WireMail instance.
$mail->send($to, $from, $subject, $body)
Send an email in a single call.
- Arguments:
send(string|array $to, string $from, string $subject, string|array $body = '', array|string $options = []) - Returns:
int— number of addresses successfully sent to (0 on failure) - If no arguments are supplied, returns a new
WireMailinstance instead. $tomay be a single address, a CSV string, or an array.$frommay be a plain address or"Name <email>"format.$bodymay be a plain-text string or an$optionsarray (skipping the text-body argument).
// Simplest form
$mail->send('user@example.com', 'you@example.com', 'Hello', 'Message body');
// Multiple recipients
$mail->send(['a@example.com', 'b@example.com'], 'you@example.com', 'Hi', 'Body');
// Named sender
$mail->send('user@example.com', 'You <you@example.com>', 'Hi', 'Body');
// With options array (HTML + text)
$mail->send('user@example.com', 'you@example.com', 'Hello', [
'body' => 'Plain text version',
'bodyHTML' => '<p>HTML version</p>',
'replyTo' => 'replies@example.com',
'headers' => ['X-Campaign' => 'newsletter-1'],
]);$mail->sendHTML($to, $from, $subject, $bodyHTML)
Like send() but the body argument is treated as HTML. A plain-text version is
auto-generated from the HTML if no body option is provided.
- Arguments:
sendHTML(string|array $to, string $from, string $subject, string $bodyHTML, array $options = []) - Returns:
int
$mail->sendHTML('user@example.com', 'you@example.com', 'Hello',
'<h1>Hello world</h1><p>This is HTML email.</p>'
);$mail->mail($to, $subject, $message)
Drop-in replacement for PHP's mail() function using the same argument order. Useful
when converting existing mail() calls to ProcessWire's mail system.
- Arguments:
mail(string|array $to, string $subject, string|array $message, array|string $headers = []) - Returns:
bool - Pass an array for
$messageto use options (bodyHTML,body,from,replyTo,headers). - The
$headersargument accepts an associative array or a"Name: Value\n"string.
// PHP mail() style
$mail->mail('user@example.com', 'Subject', 'Message body');
// With From header (PHP mail() style)
$mail->mail('user@example.com', 'Subject', 'Body', 'From: hello@example.com');
// With options array (HTML email)
$mail->mail('user@example.com', 'Subject', [
'bodyHTML' => '<h1>Hello</h1>',
'from' => 'hello@example.com',
]);$mail->mailHTML($to, $subject, $messageHTML)
Same as $mail->mail() but the message is treated as HTML with auto-generated text body.
The $headers argument is accepted in the same formats as $mail->mail().
$mail->mailHTML('user@example.com', 'Subject', '<h1>Hello</h1>');For more complex messages, get a WireMail instance and chain method calls.
$mail->new($options)
Get a new WireMail instance, optionally pre-populated with settings.
- Arguments:
new(array|string $options = []) - Returns:
WireMail - Pass
'WireMail'(string) or['module' => 'WireMail']to force PHP'smail()and skip any installed WireMail module. - Any
WireMailproperty (from,fromName,subject, etc.) may be pre-set via$options.
// Returns new WireMail instance
$m = $mail->new();
// Pre-populate with defaults
$m = $mail->new(['from' => 'no-reply@example.com', 'fromName' => 'My Site']);
// Force PHP mail() regardless of installed modules
$m = $mail->new('WireMail');Alternatively, 3.0.113 you can start a chain directly on $mail without calling
new() first — $mail proxies to(), from(), and subject() as shorthand:
// Both are equivalent:
$numSent = $mail->new()->to('user@example.com')->from('you@example.com')
->subject('Hello')->body('World')->send();
$numSent = $mail->to('user@example.com')->from('you@example.com')
->subject('Hello')->body('World')->send();All builder methods return $this (the WireMail instance) for chaining.
->to($email, $name)
Set one or more recipient addresses.
$emailmay be a single address,"Name <email>"string, CSV string, plain array, or associative[email => name]array.- Call multiple times to accumulate recipients.
- Pass
nullto clear all previously set addresses.
$m->to('user@example.com');
$m->to('John Smith <john@example.com>');
$m->to('a@example.com, b@example.com');
$m->to(['a@example.com', 'b@example.com']);
$m->to(['a@example.com' => 'Alice', 'b@example.com' => 'Bob']);
$m->to('user@example.com', 'User Name'); // name as second argument
$m->to(null); // clear all recipients->from($email, $name)
Set the sender address.
- Accepts a plain address or
"Name <email>"string. $nameas second argument is equivalent to callingfromName().
$m->from('you@example.com');
$m->from('You <you@example.com>');
$m->from('you@example.com', 'Your Name');->toName($name), ->fromName($name), ->replyToName($name)
Set display names separately from their email addresses.
toName()applies to the most recently added recipient and requiresto()first.fromName()sets the sender display name.replyToName()updates the reply-to display name and refreshes theReply-Toheader if a reply-to address is already set.
$m->to('user@example.com')->toName('User Name');
$m->from('you@example.com')->fromName('Your Name');
$m->replyTo('replies@example.com')->replyToName('Reply Team');->subject($subject)
Set the email subject.
$m->subject('Welcome to My Site');->body($body)
Set the plain-text body.
$m->body('Hello, thanks for signing up.');->bodyHTML($html)
Set the HTML body. Provide a full HTML document (not just a fragment). When bodyHTML
is set without a body, a plain-text version is auto-generated from the HTML.
$m->bodyHTML('<html><body><h1>Hello</h1><p>Thanks for signing up.</p></body></html>');->attachment($file, $filename)
Attach a file to the email.
$filemust be a full filesystem path to an existing file.$filenameoptionally overrides the name shown in the email.- Call multiple times to attach multiple files.
- Pass
nullto clear all attachments. - Support depends on the installed WireMail module.
$m->attachment('/path/to/report.pdf');
$m->attachment('/path/to/report.pdf', 'Q1-Report.pdf');
$m->attachment(null); // clear all attachments->param($value)
Add extra parameters for PHP's native mail() function, such as an envelope sender.
- Call multiple times to append multiple parameters.
- Pass
nullto clear all parameters. - These parameters only matter when ProcessWire's default
WireMailclass sends through PHPmail(); third-party WireMail modules may ignore them.
$m->param('-f bounce@example.com');
$m->param(null); // clear all params->replyTo($email, $name)
Set the reply-to address.
$m->replyTo('replies@example.com');
$m->replyTo('Replies <replies@example.com>');->header($name, $value)
Set a custom email header.
- Call multiple times to set multiple headers.
- Pass
nullas$valueto remove a header.
$m->header('X-Campaign', 'newsletter-may');
$m->header('X-Mailer', null); // remove header->headers(array $headers)
Set multiple headers at once from an associative array.
$m->headers(['X-Campaign' => 'newsletter-may', 'X-Priority' => '1']);->send()
Send the composed email. Call after all properties are set.
- Returns:
int— number of addresses successfully sent to (0 on failure) - This is a hookable method (
___send()), making it the right place for WireMail modules to override delivery behavior.
$numSent = $m->to('user@example.com')
->from('you@example.com')
->subject('Hello')
->body('Plain text')
->bodyHTML('<p>HTML version</p>')
->send();
if(!$numSent) {
// handle send failure
}Default WireMail settings are set in $config->wireMail in /site/config.php:
// Set a site-wide default from address and name
$config->wireMail('from', 'noreply@example.com');
$config->wireMail('fromName', 'My Site');
// Force a specific WireMail module
$config->wireMail('module', 'WireMailSMTP');
// Set default headers for all outgoing mail
$config->wireMail('headers', ['X-Mailer' => 'My Site']);Any WireMail property may be set as a default here (e.g. from, fromName,
subject, headers). These become the starting values for every $mail->new() call.
Prevent email from being sent to certain addresses, domains, or patterns via
$config->wireMail['blacklist'] in /site/config.php:
$config->wireMail('blacklist', [
'spam@example.com', // exact address
'@bad-host.example.com', // all addresses at this host
'@example.com', // all addresses at this domain
'example.com', // any address ending with example.com
'.example.com', // any subdomain of example.com
'/\+.*@/', // PCRE regex: block addresses with + alias
]);Test an address against the blacklist with $mail->isBlacklistEmail():
$result = $mail->isBlacklistEmail('user@example.com', ['why' => true]);
if($result === false) {
echo "Not blacklisted";
} else {
echo "Blacklisted by rule: $result"; // string describes the matching rule
}When $mail->new() is called, ProcessWire auto-detects any installed module that
extends WireMail (e.g. WireMailSMTP, WireMailgun, WireMailPHPMailer) and uses it
automatically. No code change is required — install the module and it takes over.
To force a specific module in code:
$m = $mail->new(['module' => 'WireMailGmail']);
$m = $mail->new('WireMailGmail'); // shorter aliasTo force PHP's mail() and bypass any installed module:
$m = $mail->new('WireMail');- Source files:
wire/core/WireMail/WireMail.php(builder/sender) andwire/core/WireMail/Wire(Mail Tools.php $mailAPI variable). send()returns the count of addresses emailed, not a boolean. Check$numSent > 0rather than just$numSentwhen the to-list may be empty.- When only
bodyHTMLis set (nobody), a plain-text version is automatically generated from the HTML via the hookablehtmlToText()method. - All builder methods sanitize their input — header names and values are stripped of control characters; email addresses are validated and rejected if invalid or blacklisted.
- The
X-Mailerheader is set automatically. Override it with$m->header('X-Mailer', 'My App'). param()passes additional parameters to PHP'smail()function (e.g. envelope-from-f you@example.com). This has no effect when a WireMail module handles delivery.- A list of WireMail modules can be found here: https://processwire.com/search/?q=WireMail&t=Modules
Below are 2 different ways you can get a new instance of WireMail.
$m = $mail->new(); // option A: use $mail API variable
$m = wireMail(); // option B: use wireMail() functionOnce you have an instance of WireMail ($m), you can use it to send email like in these examples below.
// chained (fluent) method call usage
$m->to('user@domain.com')
->from('you@company.com')
->subject('Message Subject')
->body('Optional message body in plain text')
->bodyHTML('<html><body><p>Optional message body in HTML</p></body></html>')
->send();
// separate method call usage
$m->to('user@domain.com'); // specify CSV string or array for multiple addresses
$m->from('you@company.com');
$m->subject('Message Subject');
$m->body('Message Body');
$m->send();
// optionally specify “from” or “to” names as 2nd argument
$m->to('user@domain.com', 'John Smith');
$m->from('you@company.com', 'Mary Jane');
// other methods or properties you might set (or get)
$m->fromName('Mary Jane');
$m->toName('John Smith');
$m->replyTo('somebody@somewhere.com');
$m->replyToName('Joe Somebody');
$m->attachment('/path/to/file.ext');
$m->header('X-Mailer', 'ProcessWire');
$m->param('-f you@company.com'); // PHP mail() param (envelope from example)
// note that the send() function always returns the quantity of messages sent
$numSent = $m->send();There are 1 WireMail types in the core, plus many more WireMail modules in our directory.
Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the WireMail class also inherits all the methods and properties of: WireData and Wire.
Common
| Name | Return | Summary | |
|---|---|---|---|
$m->body() $m->body(string $body) $m->body(string $body) | $this | Set the email message body (text only) Can also be used as property: $m->body | |
$m->bodyHTML() $m->bodyHTML(string $body) $m->bodyHTML(string $body) | $this | Set the email message body (HTML only) Can also be used as property: $m->bodyHTML | |
$m->from() $m->from(string $email) $m->from(string $email, $name = null) | $this | Set the email 'from' address and optionally name Can also be used as property: $m->from | |
$m->fromName() $m->fromName(string $name) $m->fromName(string $name) | $this | Set the 'from' name Can also be used as property: $m->fromName | |
$m->get() $m->get(string $key) $m->get(string $key) | mixed null | Get property | |
$m->headers() $m->headers(array $headers) $m->headers(array $headers) | $this | Set multiple email headers using associative array Can also be used as property: $m->headers | |
$m->replyTo() $m->replyTo(string $email) $m->replyTo(string $email, $name = null) | $this | Set the 'reply-to' email address and optionally name (where supported) Can also be used as property: $m->replyTo | |
$m->replyToName() $m->replyToName(string $name) $m->replyToName(string $name) | $this | Set the 'reply-to' name (where supported) Can also be used as property: $m->replyToName | |
$m->send() $m->send() $m->send() | int | Send the email | |
$m->set() $m->set(string $key, mixed $value) $m->set(string $key, mixed $value) | this WireData | Set property | |
$m->subject() $m->subject(string $subject) $m->subject(string $subject) | $this | Set the email subject Can also be used as property: $m->subject | |
$m->to() $m->to() $m->to($email = null, string $name = null) | $this | Set the email to address Can also be used as property: $m->to | |
$m->toName() $m->toName(string $name) $m->toName(string $name) | $this | Set the 'to' name Can also be used as property: $m->toName |
Advanced
Additional methods and properties
In addition to the methods and properties above, WireMail also inherits the methods and properties of these classes:
Core WireMail types
API reference based on ProcessWire core version 3.0.261