├── composer.json ├── README.md ├── readme.txt └── global-smtp.php /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rohmann/global-smtp", 3 | "description": "Utility plugin to setup SMTP mail via constants in wp-config.php", 4 | "keywords": ["wordpress", "smtp", "multisite"], 5 | "homepage": "https://github.com/rohmann/global-smtp", 6 | "license": "GPLv2", 7 | "authors": [ 8 | { 9 | "name": "Alexander Rohmann", 10 | "email": "alexander@rohmann.us", 11 | "homepage": "https://rohmann.us" 12 | } 13 | ], 14 | "type": "wordpress-muplugin", 15 | "require": { 16 | "php": ">=5.3.0", 17 | "composer/installers": "~1.0" 18 | } 19 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Global SMTP 2 | ================= 3 | 4 | Global SMTP is a utility plugin designed to easily configure SMTP for WordPress by adding a set of constants to your `wp-config.php` file. 5 | 6 | When used with multisite, the configuration is applied network wide. This is often handy to install as a "must use" plugin. 7 | 8 | Getting started 9 | --------------- 10 | First install as a WordPress pluing. Optionally, you could install as a "must use" plugin by placing `smtp.php` in `wp-content/mu-plugins`. 11 | 12 | Once the plugin is installing installed, add the constants to `wp-config.php` 13 | 14 | The minimum requirement is setting the host, username, and password. Everything else will be assumed from some defaults. 15 | ``` 16 | define('GLOBAL_SMTP_HOST','mail.example.com'); 17 | define('GLOBAL_SMTP_USER','admin@example.com'); 18 | define('GLOBAL_SMTP_PASSWORD','password'); 19 | ``` 20 | 21 | Assumed defaults: 22 | * From and From Name: WordPress defaults (or possibly overriden by your mail server) 23 | * Port -> 587 24 | * Secure -> tls 25 | 26 | You can specify your own with these statements: 27 | ``` 28 | define('GLOBAL_SMTP_FROM','you@example.com'); 29 | define('GLOBAL_SMTP_FROM_NAME','Your Name'); 30 | define('GLOBAL_SMTP_PORT',465); // use SSL 31 | define('GLOBAL_SMTP_SECURE;','ssl'); 32 | ``` 33 | 34 | You can also specify some other values for the SMTP mailer: 35 | 36 | `GLOBAL_SMTP_RETURN_PATH` - Bounce address 37 | `GLOBAL_SMTP_REPLYTO_FROM` - Email address for client side replies 38 | `GLOBAL_SMTP_REPLYTO_FROM_NAME` - Name for client side replies 39 | 40 | `GLOBAL_SMTP_AUTH_TYPE` - Can be `'LOGIN'`, `'PLAIN'`, `'NTLM'` (defaults to `'LOGIN'`) 41 | 42 | Environment Specific Settings 43 | ----------------------------- 44 | Because all the configuration happens via PHP constants, you can have different configurations depending on what kind of server environment is being used. For example, you could set up staging email addresses, and have your staging environment isolated from the production environment. 45 | 46 | `define('GLOBAL_SMTP_DISABLE',true);` 47 | 48 | That will prevent Global SMTP from initializing at all; quite useful for development environments. 49 | 50 | Debugging 51 | --------- 52 | 53 | This plugin will trigger warnings if you've done something wrong. Just be sure to have [WP_DEBUG](http://codex.wordpress.org/Debugging_in_WordPress#WP_DEBUG "Title") enabled. 54 | 55 | You can turn on SMTP debug by including this statement: 56 | 57 | `define('GLOBAL_SMTP_DEBUG',true);` 58 | 59 | This will display debug output from the PHP Mailer class when combined with the [http://wordpress.org/plugins/check-email/](http://wordpress.org/plugins/check-email/ "Check Email") plugin. This allows you to send a test message and troubleshoot any connectivity problems. 60 | 61 | Have any ideas for improvement? Pull requests are welcome! :) 62 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === Plugin Name === 2 | Contributors: alexanderrohmann 3 | Tags: email, smtp, multisite 4 | Requires at least: 4.1 5 | Tested up to: 4.3 6 | Stable tag: 1.0 7 | License: GPLv2 8 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 9 | 10 | Setup SMTP via wp-config.php. 11 | 12 | == Description == 13 | 14 | Global SMTP is a utility plugin designed to easily configure SMTP for WordPress by adding a set of constants to your `wp-config.php` file. 15 | 16 | When used with multisite, the configuration is applied network wide. This is often handy to install as a "must use" plugin. 17 | 18 | == Installation == 19 | 20 | = Quick Setup = 21 | 22 | 1. Install the plugin, optionall as an mu plugin. 23 | 2. Visit 'Settings > Global SMTP Setup' in your dashboard. 24 | 3. Copy and paste the sample configuraiton to `wp-config.php` and update with your SMTP credentials. 25 | 4. (optional) Add additional statements to complete the configuration for your smtp server. 26 | 27 | = Available Constants = 28 | 29 | **Required** 30 | `GLOBAL_SMTP_HOST` - The FQDN of the mail server (supplied by your SMTP provider) 31 | `GLOBAL_SMTP_USER` - Username for accessing the mail server (most often your email address). 32 | `GLOBAL_SMTP_PASSWORD` - Password to authenticate your email account. 33 | 34 | **Optional** 35 | `GLOBAL_SMTP_FROM` - Email address to use for outgoing mail. Uses WordPress defaults when not set. Many hosts will force this to be the same as the username. 36 | `GLOBAL_SMTP_FROM_NAME` - Name set in the From header for outgoing mail. Uses WordPress defaults when not set. 37 | `GLOBAL_SMTP_PORT` - Port number for SMTP connection. Assumed as 587 (for tls). 38 | `GLOBAL_SMTP_SECURE` - Encryption type. Assumed to be 'tls'. Can be 'ssl', 'tls', or 'none'. 39 | `GLOBAL_SMTP_AUTH_TYPE` - Authentication type. Defaults to 'LOGIN', can also be 'PLAIN' or 'NTLM'. 40 | 41 | `GLOBAL_SMTP_RETURN_PATH` - Address to send bounced emails. 42 | 43 | `GLOBAL_SMTP_REPLYTO_FROM` - Email address shown in recipients mail client when clicking "Reply" 44 | 45 | `GLOBAL_SMTP_DISABLE` - Set to true to prevent this plugin from hooking into `wp_mail`. This is useful for environment specific configurations. 46 | 47 | = Troubleshooting = 48 | 49 | For troubleshooting, we recommend that you install the check email plugin: 50 | https://wordpress.org/plugins/check-email/ 51 | 52 | If you add this statement to `wp-config.php` you will see debug output when sending a test email via that plugin. 53 | 54 | `define('GLOBAL_SMTP_DEBUG',true);` 55 | 56 | == Frequently Asked Questions == 57 | 58 | = What does this plugin do? = 59 | 60 | It allows you to configure WordPress to send email via an SMTP account. You can use gmail for example. 61 | 62 | = How does this plugin work? = 63 | 64 | Global SMTP hooks into the existing PHP Mailer class in WordPress and switches it to use SMTP mode. It then provides the mailer class with SMTP credentials using values that you place in `wp-config.php` 65 | 66 | 67 | == Changelog == 68 | 69 | = 1.0 = 70 | * Initial release. 71 | * Absorb original wp-multsite-smtp plugin, and make available as a standard plugin in additon to an mu plugin. 72 | 73 | == Upgrade Notice == 74 | 75 | = 1.0 = 76 | Initial release. 77 | -------------------------------------------------------------------------------- /global-smtp.php: -------------------------------------------------------------------------------- 1 | prepare_settings(); 31 | $this->errors = $this->validate(); 32 | $this->cancel = array( 'from' => false, 'from_name' => false ); 33 | 34 | if( !empty( $this->errors ) ) { 35 | $this->is_multisite = is_multisite(); 36 | $this->title = __( 'Global SMTP Setup', 'global-smtp' ); 37 | add_action( ( $this->is_multisite ) ? 'network_admin_menu' : 'admin_menu', array( $this, 'register_admin_menu' ) ); 38 | } else { 39 | add_action( 'phpmailer_init', array( $this, 'mailer' ) ); 40 | } 41 | 42 | 43 | // Filter the from name and address early, allowing them to be set in a constant but also overriden by plugins. 44 | 45 | if ( defined( 'GLOBAL_SMTP_FROM' ) ) { 46 | add_filter( 'wp_mail_from', array( $this, 'get_from' ), -999 ); 47 | } 48 | 49 | if ( defined( 'GLOBAL_SMTP_FROM_NAME' ) ) { 50 | add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ), -999 ); 51 | } 52 | 53 | 54 | add_filter( 'wp_mail', array( $this, 'check_headers') ); 55 | 56 | unset( $this->validations ); 57 | 58 | } 59 | 60 | /** 61 | * Self Instantiate 62 | * Note: Plugin can be disable internally by setting GLOBAL_SMTP_DISABLE to true. 63 | * This is useful if you have different needs between staging and production environments. 64 | */ 65 | public static function launch() { 66 | self::$instance = ( defined( 'GLOBAL_SMTP_DISABLE' ) && GLOBAL_SMTP_DISABLE ) ? null : new self(); 67 | } 68 | 69 | /** 70 | * Get this plugin's main class instance 71 | * @return object 72 | */ 73 | public static function instance() { 74 | return self::$instance; 75 | } 76 | 77 | /** 78 | * Register our admin menu in the correct context. 79 | * @return none 80 | */ 81 | public function register_admin_menu() { 82 | $parent = ( $this->is_multisite ) ? 'settings.php' : 'options-general.php'; 83 | $capability = ( $this->is_multisite ) ? 'manage_network_options' : 'manage_options'; 84 | add_submenu_page( $parent, $this->title, $this->title, $capability, 'global-smtp', array( $this, 'render_admin_page' ) ); 85 | } 86 | 87 | /** 88 | * Display the admin page 89 | * @return none 90 | */ 91 | public function render_admin_page() { 92 | 93 | $minimum = "define('GLOBAL_SMTP_HOST','smtp.gmail.com');\n" . 94 | "define('GLOBAL_SMTP_USER','user@example.com');\n" . 95 | "define('GLOBAL_SMTP_PASSWORD','**********')"; 96 | 97 | $optional = "define('GLOBAL_SMTP_FROM','you@example.com');\n" . 98 | "define('GLOBAL_SMTP_FROM_NAME','Your Name');\n" . 99 | "define('GLOBAL_SMTP_PORT', 465);\n" . 100 | "define('GLOBAL_SMTP_SECURE', 'ssl');"; 101 | 102 | ?> 103 | 104 | 105 |
106 |

title; ?>

107 |

check email plugin', 'global-smtp' ), 'https://wordpress.org/plugins/check-email/' ); ?>. 108 |

109 | 110 |
111 | errors as $error ) : ?> 112 |

get_error_message(); ?>

113 | 114 |
115 |

Example of minimum configuration (example for gmail)', 'global-smtp' ) ?>

116 |

117 |

118 |
119 |

120 |

121 |

122 |
123 | 124 | validations = new stdClass; 134 | $this->validations->required = array( 'GLOBAL_SMTP_HOST', 'GLOBAL_SMTP_USER', 'GLOBAL_SMTP_PASSWORD' ); 135 | $this->validations->is_email = array( 'GLOBAL_SMTP_RETURN_PATH', 'GLOBAL_SMTP_REPLYTO_FROM' ); 136 | $this->validations->is_int = array( 'GLOBAL_SMTP_PORT', 'GLOBAL_SMTP_TIMEOUT' ); 137 | $this->validations->should_be = array( 'GLOBAL_SMTP_SECURE' => array( 'ssl', 'tls', 'none' ), 'GLOBAL_SMTP_AUTH_TYPE' => array( 'LOGIN', 'PLAIN', 'NTLM' ) ); 138 | 139 | //Assume any undefined settings 140 | $assume = array( 141 | 'GLOBAL_SMTP_PORT' => 587, 142 | 'GLOBAL_SMTP_SECURE' => 'tls', 143 | 'GLOBAL_SMTP_TIMEOUT' => 10, 144 | 'GLOBAL_SMTP_FROM' => '', 145 | 'GLOBAL_SMTP_FROM_NAME' => '', 146 | 'GLOBAL_SMTP_AUTH_TYPE' => 'LOGIN', 147 | ); 148 | 149 | foreach ( $assume as $setting => $default ) { 150 | if( !defined( $setting ) ) { 151 | define( $setting, $default ); 152 | } 153 | } 154 | } 155 | 156 | /** 157 | * Callback for wp_mail_from filter. 158 | * Applies the from address constant if a 159 | * "From" header was not present. 160 | * @return string from email address 161 | */ 162 | public function get_from( $from ) { 163 | $value = ( $this->cancel['from'] ) ? $from : GLOBAL_SMTP_FROM; 164 | $this->cancel['from'] = false; 165 | return $value; 166 | } 167 | 168 | /** 169 | * Callback for wp_mail_from_name filter 170 | * Applies the from name constant if a 171 | * "From" header was not present. 172 | * @return string from email address 173 | */ 174 | public function get_from_name( $from_name ) { 175 | $value = ( $this->cancel['from_name'] ) ? $from_name : GLOBAL_SMTP_FROM_NAME; 176 | $this->cancel['from_name'] = false; 177 | return $value; 178 | } 179 | 180 | /** 181 | * Validate Configuration to ensure things are setup correctly 182 | * @return bool|WP_Error Returns true if successful, else WP_Error with message 183 | */ 184 | protected function validate() { 185 | 186 | $errors = array(); 187 | 188 | foreach ( $this->validations->required as $setting ) { 189 | if( !defined( $setting ) ) { 190 | $errors[] = new WP_Error( 'global-smtp', sprintf( __( '%s is required for Multisite SMTP. Please define this in wp-config.php.', 'global-smtp' ), $setting ) ); 191 | } 192 | } 193 | 194 | foreach ( $this->validations->is_email as $setting ) { 195 | if ( defined( $setting ) && !is_email( constant( $setting ) ) ) { 196 | $errors[] = new WP_Error( 'global-smtp', sprintf( __( 'Value of %s is not a valid email address. Check wp-config.php, or ensure a valid fallback is available.', 'global-smtp' ), $setting ) ); 197 | } 198 | } 199 | 200 | foreach ( $this->validations->is_int as $setting ) { 201 | if( defined( $setting ) && !is_int( constant( $setting ) ) ) { 202 | $errors[] = new WP_Error( 'global-smtp', sprintf( __( '%s should be a number', 'global-smtp' ), $setting ) ); 203 | } 204 | } 205 | 206 | foreach ( $this->validations->should_be as $setting => $allowed ) { 207 | if( defined( $setting ) && !in_array( constant( $setting ), $allowed ) ) { 208 | $errors[] = new WP_Error( 'global-smtp', sprintf( __( '%s is invalid. It should be one of these values: "%s"', 'global-smtp' ), $setting, implode('" , "', $allowed ) ) ); 209 | } 210 | } 211 | 212 | return $errors; 213 | 214 | } 215 | 216 | /** 217 | * Filter for `wp_mail` used for introspection 218 | * @param array $atts Arguments passed into wp_mail 219 | * @return array Unmodified $atts 220 | */ 221 | public function check_headers( $atts ) { 222 | 223 | // Detect from headers in string based headers 224 | if ( is_string( $atts['headers'] ) && strpos( $atts['headers'], 'From: ' ) !== false ) { 225 | $this->cancel['from'] = true; 226 | $this->cancel['from_name'] = true; 227 | } 228 | 229 | // Detect from headers in array based headers 230 | if ( is_array( $atts['headers'] ) ) { 231 | foreach ( $atts['headers'] as $header) { 232 | if ( is_string( $header ) && strpos( $header, 'From: ' ) !== false ) { 233 | $this->cancel['from'] = true; 234 | $this->cancel['from_name'] = true; 235 | } 236 | } 237 | } 238 | 239 | // Passthough original values unchanged. 240 | return $atts; 241 | 242 | } 243 | 244 | /** 245 | * Hook PHP Mailer to use our SMTP settings 246 | */ 247 | public function mailer( $phpmailer ) { 248 | 249 | // Allow debug output to be displayed 250 | if ( defined('GLOBAL_SMTP_DEBUG') && GLOBAL_SMTP_DEBUG && is_admin() && ( !defined('DOING_AJAX') || !DOING_AJAX ) ) { 251 | 252 | $phpmailer->SMTPDebug = true; 253 | 254 | // There's no way to close this
 without plugging wp_mail, which this project aims to avoid
255 | 			// It will make the PHPMailer output more readable, but only when used with: https://wordpress.org/plugins/check-email/
256 | 			if ( isset( $_GET['page'] ) && 'checkemail' == $_GET['page'] )
257 | 			  echo '
';
258 | 
259 | 		}
260 | 
261 | 		//preset
262 | 		$phpmailer->Mailer = "smtp";
263 | 		$phpmailer->SMTPAuth = true;
264 | 
265 | 		//required
266 | 		$phpmailer->Host = GLOBAL_SMTP_HOST;
267 | 		$phpmailer->Username = GLOBAL_SMTP_USER;
268 | 		$phpmailer->Password = GLOBAL_SMTP_PASSWORD;
269 | 
270 | 		//assumed
271 | 		$phpmailer->Port = (int) GLOBAL_SMTP_PORT;
272 | 		$phpmailer->SMTPSecure = GLOBAL_SMTP_SECURE;
273 | 		$phpmailer->AuthType = GLOBAL_SMTP_AUTH_TYPE;
274 | 
275 | 		//Optional
276 | 		$phpmailer->Sender = defined('GLOBAL_SMTP_RETURN_PATH') ? GLOBAL_SMTP_RETURN_PATH : $phpmailer->From;
277 | 
278 | 		if ( defined('GLOBAL_SMTP_REPLYTO_FROM') ) {
279 | 			$phpmailer->AddReplyTo(GLOBAL_SMTP_REPLYTO_FROM, defined('GLOBAL_SMTP_REPLYTO_FROM_NAME') ? GLOBAL_SMTP_REPLYTO_FROM_NAME : $phpmailer->FromName );
280 | 		}
281 | 
282 | 	}
283 | 
284 | }
285 | 
286 | /**
287 | * Fire it up.
288 | */
289 | Global_SMTP_Mailer::launch();
290 | 


--------------------------------------------------------------------------------