Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Configure WordPress wp_mail function to send through SMTP server http://b.utler.co/Y3
<?php
/*
* Set the following constants in wp-config.php
* These should be added somewhere BEFORE the
* constant ABSPATH is defined.
*/
define( 'SMTP_USER', 'user@example.com' ); // Username to use for SMTP authentication
define( 'SMTP_PASS', 'smtp password' ); // Password to use for SMTP authentication
define( 'SMTP_HOST', 'smtp.example.com' ); // The hostname of the mail server
define( 'SMTP_FROM', 'website@example.com' ); // SMTP From email address
define( 'SMTP_NAME', 'e.g Website Name' ); // SMTP From name
define( 'SMTP_PORT', '25' ); // SMTP port number - likely to be 25, 465 or 587
define( 'SMTP_SECURE', 'tls' ); // Encryption system to use - ssl or tls
define( 'SMTP_AUTH', true ); // Use SMTP authentication (true|false)
define( 'SMTP_DEBUG', 0 ); // for debugging purposes only set to 1 or 2
/**
* This function will connect wp_mail to your authenticated
* SMTP server. This improves reliability of wp_mail, and
* avoids many potential problems.
*
* Values are constants set in wp-config.php. Be sure to
* define the using the wp_config.php example in this gist.
*
* Author: Chad Butler
* Author URI: http://butlerblog.com
*
* For more information and instructions, see:
* http://b.utler.co/Y3
*/
add_action( 'phpmailer_init', 'send_smtp_email' );
function send_smtp_email( $phpmailer ) {
if ( ! is_object( $phpmailer ) ) {
$phpmailer = (object) $phpmailer;
}
$phpmailer->Mailer = 'smtp';
$phpmailer->Host = SMTP_HOST;
$phpmailer->SMTPAuth = SMTP_AUTH;
$phpmailer->Port = SMTP_PORT;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
$phpmailer->SMTPSecure = SMTP_SECURE;
$phpmailer->From = SMTP_FROM;
$phpmailer->FromName = SMTP_NAME;
}
@mikeritter

This comment has been minimized.

Copy link

mikeritter commented Sep 5, 2016

I'd recomment against hard coding the credentials into this file and for adding them to wpconfig.php

You do not want these credentials in your functions.php file or (as arguably, this shoud be a plugin) in a plugin file.

@s-light

This comment has been minimized.

Copy link

s-light commented Sep 28, 2016

@mikeritter: that seams logical!
could i just add this snippet to my wpconfig.php file?!
in the theme functions.php it has nothing to do - because i think it has nothing to do with a theme!
and adding a 'about empty' plugin for this is also over complex i think. --> but if i have to do it this way can you link to some documentation how to use the wpconfig.php for the configuration parameters and receive theme in the plugins funciton.php?
(i know there are ready build plugins out there - but hey i want to learn this stuff :-) )

@butlerblog

This comment has been minimized.

Copy link
Owner Author

butlerblog commented Oct 17, 2016

@mikeritter - the security difference between putting credentials in functions.php vs wp-config.php is negligible. In most cases, if your functions.php file is compromised, so is your wp-config.php (which in many cases means your database is also compromised). The ideal situation is to store them as a db entry, and use a configuration that restricts db access by IP (or similar security) so that the db credentials in wp-config.php do not necessarily allow access to the database. But that is outside the scope of this snippet.

@jordanambra

This comment has been minimized.

Copy link

jordanambra commented Apr 14, 2017

@butlerblog, that's not necessarily true. People who have admin access to your WP installation would be able to see functions.php, but you may not want them to have the ability to change or see the credentials. wp-config.php keeps it away from users, if that's your goal.

@DavidIfeanyichukwu

This comment has been minimized.

Copy link

DavidIfeanyichukwu commented May 3, 2018

@mikeritter, can I use this to send mail for SENDGRID?
If yes, that means I will have to copy the contents of the first file and paste in my wp_config.php, where do I necessarily need to put these files?

@leepeterson

This comment has been minimized.

Copy link

leepeterson commented Jul 13, 2018

If anyone has had issues using this gist, the $phpmailer->isSMTP(); line may be throwing an error.

Change $phpmailer->isSMTP(); to $phpmailer->Mailer = 'smtp'; and pass $phpmailer as the function's arg. It also wouldn't hurt to ensure $phpmailer is, in fact, an object in the event some other code has turned it into an array.

In full, the function should be:

add_action( 'phpmailer_init', function( $phpmailer ) {
	if ( !is_object( $phpmailer ) ) 
		$phpmailer = (object) $phpmailer;
	
	$phpmailer->Mailer     = 'smtp';
	$phpmailer->Host       = SMTP_HOST;
	$phpmailer->SMTPAuth   = SMTP_AUTH;
	$phpmailer->Port       = SMTP_PORT;
	$phpmailer->Username   = SMTP_USER;
	$phpmailer->Password   = SMTP_PASS;
	$phpmailer->SMTPSecure = SMTP_SECURE;
	$phpmailer->From       = SMTP_FROM;
	$phpmailer->FromName   = SMTP_NAME;
});
@timendez

This comment has been minimized.

Copy link

timendez commented Aug 7, 2018

Is it possible to do without auth credentials (like in Nodemailer)?

@timnolte

This comment has been minimized.

Copy link

timnolte commented Sep 25, 2019

I'll reiterate that this functionality does NOT belong in a theme's functions.php file. This is site functionality which should never be put in a theme. Themes should only be for site styling and UX.

@progress44

This comment has been minimized.

Copy link

progress44 commented Oct 12, 2019

Hi all.

I would also add the following filters

add_filter('wp_mail_from', 'set_wp_mail_from');
function set_wp_mail_from($current_from) {
	if (SMTP_FROM) { 
		return SMTP_FROM;
	}
	
	if ($current_from) {
		return $current_from;
	}
	
	return get_bloginfo('admin_email');
}

add_filter('wp_mail_from_name', 'set_wp_mail_from');
function set_wp_mail_from_name($current_from_name) {
	if (SMTP_NAME) {
		return SMTP_NAME;	
	}
	
	if ($current_from_name) {
		return $current_from_name;
	}

	return get_bloginfo('name');
}

The reason for this is that, the phpmailer_init hook won't even be fired if FROM isn't set before, because the WordPress code will throw an error before even reaching do_action saying that from_email is invalid, unless somehow it is valid.

@butlerblog

This comment has been minimized.

Copy link
Owner Author

butlerblog commented Oct 14, 2019

@progress44 - In a standard install of WP, that would be unnecessary. From and FromName are always set with defaults (with a caveat noted below*).

If these two values are not set in the headers, wp_mail() defines defaults for $from_mail and $from_name. As you've noted, it then hits the wp_mail_from and wp_mail_from_name filter hooks respectively, but those hooks are filtering the already generated default values.

If they are not filtered, the defaults are "wordpress@yoursitename.com" and "WordPress", which will be set in as $phpMailer->From and $phpMailer->FromName when $phpmailer->setFrom() is run immediately following the filter hooks. Those values will be changed when the phpmailer_init hook is fired and the send_smtp_email() function in this gist is run.

*There is a caveat to this (which could be the case which prompted your comment): wp_mail() IS a pluggable function. As such, it can be entirely replaced by a plugin (or other customization), in which case there is no guarantee that the email and name were given a default value. But neglecting a default value in a plugged (customized) wp_mail() function would be bad form on the part of that developer, IMO. If you're running into a situation that requires this, I would recommend reviewing what plugins are active and if any of them may possibly redefine the wp_mail() function (then determine if that plugin is actually necessary).

@MKJJJ

This comment has been minimized.

Copy link

MKJJJ commented Jan 10, 2020

Thanks for sharing. I tried the code, but the emails are still sent via phpmailer. Using the very same credentials in a plugin like "WP Mail SMTP" everything works just fine. I would really avoid a plugin for such a simple task, but have not idea what's going wrong. Anybody any ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.