How to send email via Gmail SMTP in Yii2 framework
Tags: gmail, smtp, yii2, php
Published: 2020-07-09 20:20:09

---
title: How to send email via Gmail SMTP in Yii2 framework
published: true
description: How to overcome the Gmail ban on the mailing domain and still send emails to @gmail.com accounts from the Yii2 framework in PHP.
tags: gmail,smtp,Yii2,php
cover_image: https://mybroadband.co.za/news/wp-content/uploads/2017/09/Google-evil.jpg
---

One of my sites has been flooded with spam bots and as a result - Gmail gave my mailing domain a **bad score** and I cannot send emails to `@gmail` addresses anymore, not from my email, not from my system, not from any of other domains and websites I host...

## Gmail won't unblock your domain... thanks Google

I did remove all the spambots activity from one of my sites, appealed the decision via Gmail support forums, but still, I'm blocked from contacting my customers that has mailboxes at `@gmail.com` and there seems to be no way to change the domain score back to where it was.

It's been almost 2 weeks and my domain score is stuck at **bad** in [https://postmaster.google.com/](https://postmaster.google.com/)

Thanks @Google :(

## How to send emails to @gmail.com boxes anyway?

As a result, I had to figure way out to send purchases, expired licenses, and other notifications to my customers.

I'm using PHP [Yii2 framework](https://www.yiiframework.com/) and it turns out it was a breeze.

## 1. Setup a helper @gmail.com account

We need a @gmail.com account to send the notifications. One thing is important. After you create the account, you need to enable **Less Secure Apps Access** option:

![Gmail options](https://devanswers.co/wp-content/uploads/2017/02/gmail-allow-less-secure-apps.png)

It allows us to send emails via Gmail SMTP server.

## 2. Add custom component in your configuration file

In your Yii2 framework directory, modify your configuration file `/common/config/Main.php` (I'm using Advanced Theme) and include custom mailing component (name it however you want):

```php
<?php
return [
	'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',

	...

	'components' => [

		'mailerGmail' => [
			'class' => 'yii\swiftmailer\Mailer',
			'viewPath' => '@common/mail',
			'useFileTransport' => false,

			'transport' => [
				'class' => 'Swift_SmtpTransport',
				'host' => 'smtp.gmail.com',
				'username' => 'gmail.helper.account',
				'password' => 'PUT-YOUR-PASSWORD-HERE',
				'port' => '587',
				'encryption' => 'tls',
			],
		],
    ],
];
```

## 3. Add helper function

I have added a helper function to one of my components registered as `Yii::$app->Custom`. It returns default mailer instance depending on the delivery email domain name.

I have also updated the code to detect the cases where the email doesn't contain `@gmail.com` string in it but still is using Gmail `MX` servers to handle emailing.

Detection is based on checking domain mailing server records using PHP built-in function `getmxrr()` and if that fails I send remote `GET` query to Google DNS service API to check the `MX` records.

```php
////////////////////////////////////////////////////////////////////////////////
//
// get default mailer depending on the provided email address
//
////////////////////////////////////////////////////////////////////////////////

public function getMailer($email)
{
	// detect if the email or domain is using Gmail to send emails
	if (Yii::$app->params['forwardGmail'])
	{
		// detect @gmail.com domain first
		if (str_ends_with($email, "@gmail.com"))
		{
			return Yii::$app->mailerGmail;
		}

		// extract domain name
		$parts = explode('@', $email);
		$domain = array_pop($parts);

		// check DNS using local server requests to DNS
		// if it fails query Google DNS service API (might have limits)
		if (getmxrr($domain, $mx_records))
		{
			foreach($mx_records as $record)
			{
				if (stripos($record, "google.com") !== false || stripos($record, "googlemail.com") !== false)
				{
					return Yii::$app->mailerGmail;
				}
			}

			// return default mailer (if there were records detected but NOT google)
			return Yii::$app->mailer;
		}

		// make DNS request
		$client = new Client();

		$response = $client->createRequest()
			->setMethod('GET')
			->setUrl('https://dns.google.com/resolve')
			->setData(['name' => $domain, 'type' => 'MX'])
			->setOptions([
				'timeout' => 5, // set timeout to 5 seconds for the case server is not responding
			])
			->send();

		if ($response->isOk)
		{
			$parser = new JsonParser();

			$data = $parser->parse($response);

			if ($data && array_key_exists("Answer", $data))
			{
				foreach ($data["Answer"] as $key => $value)
				{
					if (array_key_exists("name", $value) && array_key_exists("data", $value))
					{
						if (stripos($value["name"], $domain) !== false)
						{
							if (stripos($value["data"], "google.com") !== false || stripos($value["data"], "googlemail.com") !== false)
							{
								return Yii::$app->mailerGmail;
							}
						}
					}
				}
			}
		}
	}

	// return default mailer
	return Yii::$app->mailer;
}
```

If the domain ends with `@gmail.com` or the domain is using Gmail mailing systems the `mailerGmail` instance is used, otherwise the default mailing component `Yii::$app->mailer` is used.

## 4. Usage

```php
    /**
     * Sends an email to the specified email address using the information collected by this model.
     *
     * @return boolean whether the email was sent
     */
    public function sendEmail()
    {
		// find all active subscribers
		$message = Yii::$app->Custom->getMailer($this->email)->compose();
	
		$message->setTo([$this->email => $this->name]);
		$message->setFrom([\Yii::$app->params['supportEmail'] => "Bartosz Wójcik"]);
		$message->setSubject($this->subject);
		$message->setTextBody($this->body);
	
		$headers = $message->getSwiftMessage()->getHeaders();
	
		// message ID header (hide admin panel)
		$msgId = $headers->get('Message-ID');
		$msgId->setId(md5(time()) . '@pelock.com');
	
		$result = $message->send();
	
		return $result;
    }
```

## 5. Know the limits

This is only the temporary solution and you need to be aware you won't be able to send bulk mail with this method, Gmail enforces some limitations on fresh mailboxes too.

## 6. Gmail is not your friend

It seems if your domain lands on that **bad reputation** scale there isn't any easy way out of it. I read on Gmail support forums, some people [wait for more than a month](https://support.google.com/mail/thread/10570288?hl=en) for Gmail to unlock their domains without any result and communication back. My domain is not listed in any other blocked RBL lists (spam lists), it's only Gmail blocking it, but it's enough to understand how influential Google is, it can ruin your business in a second without a chance to fix it...

## 7. Google like to make things harder...

A small update. Now in 2021 you need to also enable access to unverified devices in order to make it work, go to:

https://accounts.google.com/b/0/DisplayUnlockCaptcha

And enable it.

Other solution is to enable 2-Step Verification and then generating  so called "App Password", more information about it in this tutorial:

https://medium.com/graymatrix/using-gmail-smtp-server-to-send-email-in-laravel-91c0800f9662