クラウドにあるメールをローカルサーバに代理受信
組織で利用しているクラウド型のメールサーバーに利用者がメールを残すため容量が足りなくなったことがありました。クラウドの契約を変更して容量を増やしてもらえばいいのですが、なかなか簡単にはいきません。とりあえずの回避策としてローカル環境に別のメールサーバーを設けてクラウド上のメールを代理ですべて受信した際の覚書です。ローカルサーバーにはフリーOSのDebianを利用しています。
SMTPとPOP
クライアントで使うメーラーには無意識にSMTPとPOPサーバーを設定してしまいます。同値である事も多いのであまり意識していませんが、サーバーを立ち上げる際には区別が必要です。
筆者はSMTPはメール送信、POP3は受信と覚えていましたが、SMTPサーバーはサーバー間ではメール受信もしています。SMTPは自分の管轄するアドレス宛のメールを受信すると、ユーザー毎に振り分けて保存します。SMTPが処理するのはそこまでで、以降保存されたメールの操作はPOPやIMAPの役割となります。
SMTPが直接該当のメールアドレスをもつ端末に直接メールを届けないのは、「そういう仕組み」だからなのですが、常時稼働が前提とされていないクライアントにメールを届けるためにはこのような方式が採用されるのは自然な成り行きだと思います。
アプリは通常、さまざまな機能を持ったプログラム群で構成されますが、SMTPやPOPを構成する要素を機能により分別すると次のようになります。
- MUA(Mail User Agent)
OutlookやThunderbirdのようなメールアプリです。
- MTA(Mail Transfer Agent)
SMTPサーバーに存在し、メールをアドレスによって振り分けをする機能です。MDAと一体化されていることがあります。
- MDA(Mail Delivery Agent)
メールを送信する機能です。
- MRA(Mail Retrieval Agant)
保存されているメールを読みだして表示する機能です。利用されるプロトコルにはPOPやIMAPがあります。
これらの機能の説明はASCII.jp:メールを受け取る仕組みはどうなっていますかがわかりやすかったです。
クラウドメールサーバーからすべてメールを受信
メール周辺の仕組みが理解できたので、ツールを使ってクラウドからメールを受信します。ここではフリーOSのDebianサーバーを用意し、getmailというアプリを使います。getmailは先の分類でいくとMUAに当たると思いますが、これに備わった機能を使ってPOP経由で取得したメールデータをMDAで行われる操作と同等のことをします。
まずはアプリをインストールします。
$ su ... # apt update ... # apt install getmail ... # exit
今回利用する構成(Maildir)の場合、getmailはroot権限で実行できないようです。そのためインストール以降はrootではないユーザーで作業をして下さい。設定終了後も、このユーザーの権限でメールを受信することになります。
debian.org:リモートメールの取得および転送ユーティリティーに使用の仕方がかいてあります。
先のページで提供されているスクリプトに筆者による解説をしたものが次になります。この内容でgetmail.shファイルとして作成し、管理者による実行権限を付与します。
#!/bin/sh
#パイプやサブシェルでエラーになったら、シェルを停止させるオプションを設定しています。
set -e
# 稼働チェックにrunningというファイルを使い、
# すでにスクリプトが起動しているようなら
# pgrep でプロセスIDを表示して終了します。
# echo メッセージは標準エラー出力にも出力し
# ています(>&2)
if [ -f $HOME/.getmail/running ]; then
echo "getmail is already running ... (if not, remove $HOME/.getmail/running)" >&2
pgrep -l "getmai[l]"
exit 1
else
echo "getmail has not been running ... " >&2
fi
# stopという名前のファイルを置くことで、
# スクリプトを実行しないようにすることができます。
# 自動起動を一時的に止めたい場合に利用します。
# 解除するにはファイルを削除します。
if [ -f $HOME/.getmail/stop ]; then
echo "do not run getmail ... (if not, remove $HOME/.getmail/stop)" >&2
exit
fi
# 引数に -lを付けた場合は状態確認だけで終了します。
if [ "x$1" = "x-l" ]; then
exit
fi
# $HOME/.getmail/config/に配置してい
# るメール受信用ファイルを取り出して、
# rcfiles文字列に格納しています。
rcfiles="/usr/bin/getmail"
for file in $HOME/.getmail/config/* ; do
rcfiles="$rcfiles --rcfile $file"
done
# runningファイルを作成して重複起動を避けます。
# date -uでファイル内に時刻を入れています。
date -u > $HOME/.getmail/running
# rcfilesに格納した文字列をevalによってコマンド
# として解釈します。
# $@にはスクリプト起動時の引数が入ります。
eval "$rcfiles $@"
#処理が終了後runningファイルを削除します。
rm $HOME/.getmail/running
スクリプト中の$HOMEはユーザーのホームディレクトリになります。(/home/user等)
$ chmod 744 getmail.sh
スクリプトに指定したルートディレクトリに移動して、次のコマンドを用いて作業ディレクトリを作成します。
$ mkdir -m 0700 $HOME/.getmail
$ mkdir -m 0700 $HOME/.getmail/config
$ mkdir -m 0700 $HOME/.getmail/log
作成したconfigディレクトリに対象のユーザー名と同じファイルを作成し、受信時の設定を入力します。書式は次の通りです。
[retriever]
type = SimplePOP3SSLRetriever
server = [クラウド上のPOP3サーバーのアドレス]
username = [ユーザー名]
password = [パスワード]
[destination]
#type = MDA_external
#path = /usr/bin/maildrop
#unixfrom = True
type = Maildir
path = /var/mdir/[ユーザー名]/
[options] verbose = 0
delete = True
delivered_to = False
message_log = ~/.getmail/log/getmail.all.log
先のDebianのページのサンプルではMDAであるmaildropにデータを渡す設定でしたが、ここではMaildir形式で保存するようにtypeの値を変更します。
type=Maildirでは、pathにユーザー毎に保存するディレクトリを指定します。この指定は/で終わるようにしてください。またディレクトリの中には、cu、new、tmpという名前のサブディレクトリが必要です。
ここで設定するファイルには、パスワード情報が含まれるので権限は600にするようにしましょう。
またメールを保存するディレクトリは権限を770にして、所有権は[保存するメールの宛先ユーザー]:mailusersにしましょう。そしてスクリプトを起動するユーザーをmailusersグループに加えましょう。後で書きますが、メールを利用するユーザーはすべてここで設定sたmailusersグループに所属させます。
# addgroup mailusers
# adduser [スクリプト実行ユーザー] mailusers
記述を終えたら、getmail.shスクリプトを実行してみて、設定したフォルダにメールが受信できるか確認します。
dovecot
クラウドからの受信に問題がなければ、今度は各クライアントがメールを受信する際の設定をします。POP/IMAPサーバーアプリであるdovecotをインストールします。
$su ... #apt update ... #apt install dovecot-core dovecot-pop3d
/etc/dovecot/dovecot.confの記述を変更します。listen = * とだけにすることでIPv6には対応させません。
/etc/dovecot/conf-d/10-auth.confの記述を変更します。組織内にのみ公開するサーバーなのでdisable_plaintext_auth = noをとしてプレーンテキストの認証を許可します。また、認証方法であるauth_mechanismsをauth_mechanisms=plain loginとします。
... disable_plaintext_auth = no ... auth_mechanisms=plain login ...
/etc/dovecot/conf-d/10-ssl.confの記述を変更します。組織内にのみ公開するサーバーなのでssl = noをとしてとします。秘密鍵と証明書の部分もコメントアウトします。
... ssl = no ... #ssl_cert=... #ssl_key=... ...
/etc/dovecot/conf-d/10-mail.confの記述を変更します。デフォルトだとmbox形式になっているものをmaildirに変えて保存場所も先にgetmailで指定したディレクトリとなるように変更します。
... mail_location = maildir:/var/mdir/%u ...
dovecotの認証は10-auth.confに設定されています。初期設定では!include auth-system.conf.extの記述によりPAM認証が用いられます。PAMの設定は/etc/pam.d/dovecotに記述されています。この初期設定はDebianのユーザー認証となっていました。
つまり、Debianにユーザー=dovecotのユーザーとなります。そこでDebianにdovecot用のユーザーを次のように作成します。
# /sbin/useradd [ユーザー名] -g [ユーザーグループ] -d [ホームディレクトリ] -s /usr/sbin/nologin
# passwd [ユーザー名]
...パスワードを設定
ユーザー名はlinuxのユーザー命名規則に基づいた名前を推奨します。使っていい文字はアルファベット(大小)、数値、アンダーバー(_)です。古いバージョンをに対応するなら8字までで、そうでなければ32字までとなっています。
ユーザーグループは先に設定したグループに設定します。先の通り各ユーザーのディレクトリは同一グループなら読み書き可能ですが、ここで作るユーザーはシェルにログインできないので他人のメールを読み書きすることはできません。
ホームディレクトリには先ほど設定した/var/mdir/ユーザー名を指定してください。
-s /usr/sbin/nologinとすることで、作成したユーザーはdovecot専用のユーザーとさせています。(シェルにログインさせません)
getmail.shの修正
ここまでで、dovecotの設定は終了しました。本来ならクライアントのメーラーの設定を今回作成したサーバーに設定すれば、getmail.shで受信したメールを受信できるのですが、まだひとつ問題があります
それは内部に保存されるメールの所有権がすべてgetmail.shの起動ユーザーになってしまうことです。
そのためメーラーからの受信処理はメールが読み取れずにエラーとなります。それに対応するためにスクリプトを修正します。
sudo
ファイルの所有権を変更するには管理者権限が必要になります。しかしユーザー権限からしかgetmailは起動させられないので、sodoというアプリを使って所有権の変更の部分だけ管理者権限で実行します。sudoをインストールしていない場合はインストールしてください。
#$su ... #apt update ... #apt install sudo ...
/etc/sudoersに次の設定を記述します。直接編集してもいいですが、書式のエラー時に警告を出してくれるvisudo経由で書き込みをした方が安全です。
sudoersファイルの記述方法は別ページでも詳しく説明していますので合わせてお読みいただけると幸いです。
[getmail.sh実行ユーザー] ALL=(ALL:ALL) NOPASSWD: /user/bin/chown
この記述で、指定のユーザーは、すべてのホストから、すべてのユーザー:グループの権限で、パスワードなしで/usr/bin/chownコマンドをsudo経由で実行できるようになります。
sudoの設定ができたらgetmail.shスクリプトの最後に次の記述を付け加えます。ディレクトリ名をユーザー名にした意味はここでユーザー名を取得するためです。
files="/var/mdir/*"
for filepath in $files; do
if [ -d $filepath ]; then
#ディレクトリだったら
username=`basename $filepath`
sudo chown -R $username:mailusers $filepath
fi
done
getmail.shスクリプト実行するユーザーにスクリプトをタスクであるcronに登録し定期的に実行させます。時間の間隔は好きなように設定してください。
クォータ(quota)
ディスクの容量や他のPC資源を管理する際に用いる制限のことをクォータ(quota)といいます。この場合はディスク容量になりますが、ローカルサーバの方が容量は多いとはいえ無限にあるわけではないので、ユーザー毎にサイズ制限をかけます。
dovecot:Quotaを読んでみると、dovecotにもquotaは拡張機能として存在しているようですが、postfix用に用意されているみたいでした。
getmail受信時は制御できなさそうなのでスクリプト側で対応することにしました。
まず制限をオーバーしたユーザー名のファイルを入れるlimitoverディレクトリを.getmailディレクトリに作成して権限を777にします。容量制限を超えたユーザーがいたらユーザー名を書き出して、新規メールを受信させないようにしました。ローカルのメール容量制限を超え、かつクラウドの容量制限も超えた場合にメール受信が完全に止まる二重構成です。
rcfiles="/usr/bin/getmail"以降のfor~doneを次のように書き換えます。
# ディレクトリ容量制限 Mbytes
LIMITSIZEM=500
# 容量オーバーリストをいったん削除
if [ -n "$(ls $HOME/.getmail/limitover/)" ]; then
rm $HOME/.getmail/limitover/*
fi
rcfiles="/usr/bin/getmail"
for file in $HOME/.getmail/config/* ; do
username=`basename $file`
filepath=/var/mdir/$username
filesize=`sudo du -ms $filepath | sed -r 's/^([0-9]*).*$/\1/'`
if [ $LIMITSIZEM -lt $filesize ]; then
touch $HOME/.getmail/limitover/$username
else
rcfiles="$rcfiles --rcfile $file"
fi
done
ディレクトリのサイズを得るduコマンドもchown同様に権限を付与してください。
次回は、dovecotをIMAPに対応させて、Roundecubeと連携してみたいと思います。