Postfix + MySQL (MariaDB)でメール転送の設定をする

## はじめに
持っているドメインでメールを受信したいのだけど、自分でメールサーバ立ててIMAPして、っていうとスパム対策どうしようとか、メールクライアント使わないととかいろいろと面倒、かといってGoogle AppsやOffice365などだと有償になってしまい、そこまでガッツリ使うわけでもないからなと躊躇してしまう、そんなことはありませんか。ありますよね。

そんなときは、とりあえず無償のGmailのメアドに全部転送できればいいよね楽だよね、ということで、Postfixでメール受けるサーバを立ててすべからく転送するように設定してしまおうということで、その設定をまとめてみました。

Postfixはテキストファイルだけでも設定できるのですが、ここはせっかくなのでバックエンドにMySQLを使ってみようということで、MySQLを使ってみます（CentOS7でyumで入れたので実際はMariaDBですが）。

設定自体は複雑ではないのですが、いくつかのファイルに分かれてちょっと混乱する気がするので、出来るだけわかりやすくまとめてみます。

## 今回の実現したいこと
* foo@example.org へ届いたメールを foo-example-org@gmail.com へ転送する設定をする
* PostfixとMySQLを使って設定する

## 構成
CentOS7を使いました。

* CentOS 7
* Postfix 2.10.1
* MariaDB 5.5.41

## インストール
PostfixをMySQLに対応させる場合、ググるとSRPMを云々というのが出てきたりしますが、CentOS7の場合はyum でpostfixをインストールすれば、はじめからMySQLが使える状態になっています。

```bash
% postconf -m 
```
とすれば、ルックアップテーブルにどんな形式がつかえるかが確認できます。これで mysql と表示されていればOKです。

## Postfixの設定(1) main.cf
Postfixの設定ファイル /etc/postfix/main.cf を編集します。設定内容は以下のようにしました。

```main.cf
myhostname = host.example.com   
mydomain = host.example.com 
myorigin = $mydomain 
inet_interfaces = all
mynetworks=127.0.0.0/8 #このサーバのみを信頼する（中継しない）
virtual_alias_domains = mysql:/etc/postfix/virtual_alias_domains.mysql #転送用に受信するドメイン名
virtual_alias_maps = mysql:/etc/postfix/virtual_alias_maps.mysql #転送先のマッピング
```

virtual_alias_domains は、転送するメール受信するドメインを指定する項目です。
mysql: の部分でmysqlを参照するように指定しています。その後のパスの指定でmysqlへの接続情報が書かれた設定ファイルが指定されています。

virtual_alias_maps は、メールアドレスごとの転送先を指定する項目です。これも同様にmysqlへの接続情報のパスが指定されています。

## Postfixの設定(2) mysqlへの接続情報
以下のように設定しました。

```virtual_alias_domains.mysql
hosts = localhost
user = postfixuser
password = postfixpass
dbname = postfix
query = select name from domains where name = '%s'

```
```virtual_alias_map.mysql
hosts = localhost
user = postfixuser
password = postfixpass
dbname = postfix
query = select fwdaddr from virtual_maps where name = '%s'

```
内容は説明しなくてもだいたいわかると思いますが、 query の SQL で抽出条件、結果のカラムを指定してます。 %sが問い合わせのキーが入ることになります。 サニタイズなどのSQLインジェクション対策はなされているようです。結果が複数カラム、複数レコードを返す場合は、, で結合されて返ってくるようです。

Postfix側はこれで終了です。今度はMySQL(MariaDB)側になります。

## MySQLの設定
こちらは以下の様なかんじです、そんなに説明いらないですよね

```SQL
> create database postfix;
> grant all on postfix.* to postfixuser@localhost identified by 'postfixpass';
> create table domains (name varchar(253) not null unique);
> create table virtual_maps (name varchar(254) not null unique, fwdaddr varchar(254) not null);
```

## MySQLへのデータ登録
次にデータを入れます。上で書いたように foo@example.org へ届いたメールを foo-example-org@gmail.com に転送するので、ドメインとして example.org を登録し、その上で、foo@example.org に対して foo-example-org@gmail.com をマッピングします。

```SQL
> insert into domains (name) values ('example.org');
> insert into virtual_maps (name, fwdaddr) values ('foo@example.org', 'foo-example-org@gmail.com');
```

これだけですね。ここでちょっと脱線すると、 example.orgに来た foo 以外のメールを全て catch-all-example-org@gmail.comに転送する場合は、このようにすればよいです。

```SQL
> insert into virtual_maps (name, fwdaddr) values ('@example.org', 'catchall-example-org@gmail.com');
```

*みたいにワイルドカードをつけるのではなく、@から始めることでうまく動作します。

MySQL側はこんなかんじです。


## 動作確認
postfixを再起動して動作確認してみましょう。

```bash
% sudo systemctl restart postfix
% sudo tail -f /var/log/maillog 
```

このようにしてメールログを垂れ流しつつ、 foo@example.org にメールを送ると、ログでメールを受信し、その後転送しているのがわかると思います。実際メールが gmailまで届いたら成功です。

## 参考URL
以下の記事を参考にしました。ありがとうございます。

* [ドメイン名のしくみ](https://www.nic.ad.jp/ja/dom/system.html) 
* [Postfix から MySQL を使う](http://tmtms.hatenablog.com/entry/2014/12/15/postfix-mysql)