Setting up Symfony Mailer for WordPress Email Functionalities in Sage

To override WordPress’s default email functionality and use Symfony Mailer with your own SMTP settings for features like password resets, contact forms, and comments, and even intergration with other smtp servers or even set wordpress to easily work with mailhog or mailtrap for email testing follow these steps:

Step 1: Install Symfony Mailer

composer require symfony/mailer

Step2: Create a Mail Service Provider

In sage you can do this fast and easy using the wp acorn command: wp acorn make:provider MailServiceProvider

If you not using acorn in the app/Providers directory of your sage theme project, create a new file named MailServiceProvider.php. This will handle the configuration and integration of Symfony Mailer.

namespace App\Providers;

use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mime\Email;
use Illuminate\Support\ServiceProvider;

class MailServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton('mailer', function () {
            $dsn = sprintf('%s://%s:%s@%s:%s', 
                env('SMTP_TRANSPORT', 'smtp'), 
                env('SMTP_USER', ''), 
                env('SMTP_PASS', ''), 
                env('SMTP_HOST', ''), 
                env('SMTP_PORT', '')
            );
            $transport = Transport::fromDsn($dsn);
            return new Mailer($transport);
        });
    }

    public function boot(): void
    {
        add_action('admin_menu', [$this, 'add_smtp_settings_page']);
        add_action('admin_init', [$this, 'register_smtp_settings']);
        add_action('admin_post_send_test_email', [$this, 'send_test_email']);

        add_filter('wp_mail', function ($args) {
            $mailer = resolve('mailer');
            try {
                $message = (new Email())
                    ->from($args['from'])
                    ->to($args['to'])
                    ->subject($args['subject'])
                    ->html($args['message']);
                $mailer->send($message);
                return $args;
            } catch (\Exception $e) {
                error_log("Mailer error: " . $e->getMessage());
                return false;
            }
        });

        add_filter('phpmailer_init', function ($phpmailer) {
            $phpmailer->isSMTP();
            $phpmailer->Host = env('SMTP_HOST');
            $phpmailer->SMTPAuth = true;
            $phpmailer->Username = env('SMTP_USER');
            $phpmailer->Password = env('SMTP_PASS');
            $phpmailer->SMTPSecure = env('SMTP_ENCRYPTION', 'tls');
            $phpmailer->Port = env('SMTP_PORT');
        });
    }

    public function add_smtp_settings_page()
    {
        add_options_page('SMTP Settings', 'SMTP Settings', 'manage_options', 'smtp-settings', [$this, 'render_smtp_settings_page']);
    }

    public function render_smtp_settings_page()
    {
        ?>
        <div class="wrap">
            <h1>SMTP Settings</h1>
            <form method="post" action="options.php">
                <?php
                    settings_fields('smtp_settings_group');
                    do_settings_sections('smtp-settings');
                ?>
                <table class="form-table">
                    <tr valign="top">
                        <th scope="row"><label for="smtp_host">SMTP Host</label></th>
                        <td><input type="text" name="smtp_host" value="<?php echo esc_attr(get_option('smtp_host')); ?>" /></td>
                    </tr>
                    <tr valign="top">
                        <th scope="row"><label for="smtp_user">SMTP Username</label></th>
                        <td><input type="text" name="smtp_user" value="<?php echo esc_attr(get_option('smtp_user')); ?>" /></td>
                    </tr>
                    <tr valign="top">
                        <th scope="row"><label for="smtp_pass">SMTP Password</label></th>
                        <td><input type="password" name="smtp_pass" value="<?php echo esc_attr(get_option('smtp_pass')); ?>" /></td>
                    </tr>
                    <tr valign="top">
                        <th scope="row"><label for="smtp_port">SMTP Port</label></th>
                        <td><input type="text" name="smtp_port" value="<?php echo esc_attr(get_option('smtp_port')); ?>" /></td>
                    </tr>
                    <tr valign="top">
                        <th scope="row"><label for="smtp_encryption">SMTP Encryption</label></th>
                        <td>
                            <select name="smtp_encryption">
                                <option value="tls" <?php selected(get_option('smtp_encryption'), 'tls'); ?>>TLS</option>
                                <option value="ssl" <?php selected(get_option('smtp_encryption'), 'ssl'); ?>>SSL</option>
                                <option value="none" <?php selected(get_option('smtp_encryption'), 'none'); ?>>None</option>
                            </select>
                        </td>
                    </tr>
                </table>
                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }

    public function register_smtp_settings()
    {
        register_setting('smtp_settings_group', 'smtp_host');
        register_setting('smtp_settings_group', 'smtp_user');
        register_setting('smtp_settings_group', 'smtp_pass');
        register_setting('smtp_settings_group', 'smtp_port');
        register_setting('smtp_settings_group', 'smtp_encryption');
    }

    public function send_test_email()
    {
        $to = sanitize_email($_POST['test_email']);
        $mailer = resolve('mailer');
        try {
            $message = (new Email())
                ->from(env('SMTP_FROM_EMAIL'))
                ->to($to)
                ->subject('Test Email')
                ->html('<p>This is a test email from your WordPress SMTP configuration.</p>');
            $mailer->send($message);
            wp_redirect(add_query_arg('status', 'success', wp_get_referer()));
        } catch (\Exception $e) {
            wp_redirect(add_query_arg('status', 'failure', wp_get_referer()));
        }
        exit;
    }
}

Step 3: Register the Service Provider

In sage you can do this either in the functions.php , ThemeServiceProvider or in the config/app.php for as I will in this example:

'providers' => [
    // Other service providers...
    App\Providers\MailServiceProvider::class,
],

Step 4: Configure Your SMTP Settings

Now, you need to configure the SMTP settings in your .env file. Add the following variables to specify the SMTP settings:

SMTP_TRANSPORT=smtp
SMTP_HOST=smtp.yourmailserver.com
SMTP_PORT=587
SMTP_USER=your_smtp_username
SMTP_PASS=your_smtp_password
SMTP_ENCRYPTION=tls
SMTP_FROM_EMAIL=your_email@example.com
SMTP_FROM_NAME=Your Site Name

Now you can test if everything is working by mimicking a forgot password scenario.

All the best and hopefully you find this intresting, give this post a like to let me know atleast you found this helpful you can as well ask questions if this was cumbersome.

@Log1x has demonstrated another way of achieving this by using Acorn Mail here: Announcing Acorn Mail Hopefully you find that helpful too