Решение:
['email', 'filter', 'filter' => 'trim'], // trim приводит null к пустой строке
['email', 'email'],
['email', 'unique', 'message' => 'Email уже существует.'],
// либо добавляем правило
['email', 'default', 'value' => null], // по умолчанию ставим null. Важно чтобы это правило было после trim
// либо изменяем trim
['email', 'filter', 'filter' => 'trim', 'skipOnEmpty' => true],
Дока:
When the validate() method is called, it does the following steps to perform validation:
Determine which attributes should be validated by getting the attribute list from yii\base\Model::scenarios() using the current scenario. These attributes are called active attributes.
Determine which validation rules should be used by getting the rule list from yii\base\Model::rules() using the current scenario. These rules are called active rules.
Use each active rule to validate each active attribute which is associated with the rule. The validation rules are evaluated in the order they are listed.