「Azure で postfix のインストールを試す」
https://qiita.com/nanbuwks/items/38b54aaf8c3ecfdbb3cc
「Azure で Dovecot をインストール、telnet でメールを読む」
https://qiita.com/nanbuwks/items/c3f180fc44fa08f91820
では最低限のインストールと確認を行いました。
ここで、メール受信してメールサーバに蓄えられているメールメッセージの形式は、mailbox (mbox) 形式と Maildir 形式があります。以下の特徴があります
mailbox (mbox) 形式
- レガシーな形式
- ユーザごとにすべてのメールが1ファイルになっている
- 対障害性低
- メールスプールディレクトリ (ex., /var/mail や /var/spool/mail ) に1ユーザ1ファイルで保管
- メールをサーバに大量に保管している場合はパフォーマンスが低下
Maildir 形式
- メール1通ごとに1ファイル
- ユーザごとのディレクトリ ~/Maildir 内 cur,new,tmp ディレクトリに既読、未読、配送中メールが保管される
- 対障害性Up
- メールをサーバに大量に保管しても mailbox 形式よりパフォーマンスの低下が抑えられる
デフォルトでは mailbox 形式でインストールされていますが、Maildir 形式に変更します。
準備
azureuser@test-azure-gen:~$ sudo systemctl stop postfix
azureuser@test-azure-gen:~$ sudo systemctl stop dovecot
mbox2maildir というユーティリティが mailscripts に含まれているのでそれをインストールしておきます。
azureuser@test-azure-gen:~$ sudo apt install mailscripts
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
build-essential cpp cpp-11 dctrl-tools devscripts dh-elpa-helper diffstat dpkg-dev dput elpa-notmuch emacsen-common fakeroot
fontconfig-config fonts-dejavu-core g++ g++-11 gcc gcc-11 gcc-11-base gettext intltool-debian javascript-common
libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libaliased-perl libapt-pkg-perl libarchive-zip-perl
libarray-intspan-perl libasan6 libatomic1 libauthen-sasl-perl libb-hooks-endofscope-perl libb-hooks-op-check-perl
libc-dev-bin libc-devtools libc6-dev libcapture-tiny-perl libcc1-0 libclass-data-inheritable-perl
libclass-method-modifiers-perl libclass-xsaccessor-perl libclone-perl libcommon-sense-perl libconfig-tiny-perl
libconst-fast-perl libcontextual-return-perl libcpanel-json-xs-perl libcrypt-dev libdata-dpath-perl libdata-dump-perl
libdata-messagepack-perl libdata-optlist-perl libdata-validate-domain-perl libdata-validate-ip-perl libdata-validate-uri-perl
libdeflate0 libdevel-callchecker-perl libdevel-globaldestruction-perl libdevel-size-perl libdevel-stacktrace-perl
libdistro-info-perl libdpkg-perl libdynaloader-functions-perl libemail-address-xs-perl libencode-locale-perl
libexception-class-perl libexporter-tiny-perl libfakeroot libfile-basedir-perl libfile-chdir-perl libfile-dirlist-perl
libfile-fcntllock-perl libfile-find-rule-perl libfile-homedir-perl libfile-listing-perl libfile-remove-perl
libfile-touch-perl libfile-which-perl libfont-afm-perl libfont-ttf-perl libfontconfig1 libgcc-11-dev libgd3
libgit-wrapper-perl libgitlab-api-v4-perl libgmime-3.0-0 libgomp1 libhash-fieldhash-perl libhtml-form-perl
libhtml-format-perl libhtml-html5-entities-perl libhtml-parser-perl libhtml-tagset-perl libhtml-tree-perl
libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl libhttp-message-perl libhttp-negotiate-perl
libhttp-tiny-multipart-perl libimport-into-perl libio-html-perl libio-interactive-perl libio-prompt-tiny-perl
libio-prompter-perl libio-pty-perl libio-socket-ssl-perl libio-string-perl libio-stringy-perl libipc-run-perl
libipc-run3-perl libipc-system-simple-perl libisl23 libiterator-perl libiterator-util-perl libitm1 libjbig0 libjpeg-turbo8
libjpeg8 libjs-jquery libjs-sphinxdoc libjs-underscore libjson-maybexs-perl libjson-perl libjson-xs-perl liblist-compare-perl
liblist-moreutils-perl liblist-moreutils-xs-perl liblist-someutils-perl liblist-someutils-xs-perl liblist-utilsby-perl
liblog-any-adapter-screen-perl liblog-any-perl liblsan0 liblwp-mediatypes-perl liblwp-protocol-https-perl libmail-box-perl
libmail-message-perl libmail-transport-perl libmailtools-perl libmarkdown2 libmath-base85-perl libmime-types-perl
libmodule-implementation-perl libmodule-runtime-perl libmoo-perl libmoox-aliases-perl libmoox-struct-perl libmouse-perl
libmpc3 libnamespace-autoclean-perl libnamespace-clean-perl libnet-domain-tld-perl libnet-http-perl libnet-ipv6addr-perl
libnet-netmask-perl libnet-smtp-ssl-perl libnet-ssleay-perl libnetaddr-ip-perl libnotmuch5 libnsl-dev libnumber-compare-perl
libobject-id-perl libobject-realize-later-perl libpackage-stash-perl libpackage-stash-xs-perl libparams-classify-perl
libparams-util-perl libpath-iterator-rule-perl libpath-tiny-perl libperlio-gzip-perl libperlio-utf8-strict-perl
libpod-constants-perl libpod-parser-perl libquadmath0 libre-engine-re2-perl libre2-9 libreadonly-perl libref-util-perl
libref-util-xs-perl libregexp-pattern-license-perl libregexp-pattern-perl librole-tiny-perl libsereal-decoder-perl
libsereal-encoder-perl libset-intspan-perl libsexp1 libsocket6-perl libsort-versions-perl libstdc++-11-dev libstrictures-perl
libstring-copyright-perl libstring-escape-perl libstring-shellquote-perl libsub-exporter-perl
libsub-exporter-progressive-perl libsub-identify-perl libsub-install-perl libsub-name-perl libsub-quote-perl
libsyntax-keyword-try-perl libtext-glob-perl libtext-levenshteinxs-perl libtext-markdown-discount-perl libtext-xslate-perl
libtiff5 libtime-duration-perl libtime-moment-perl libtimedate-perl libtirpc-dev libtry-tiny-perl libtsan0 libtype-tiny-perl
libtype-tiny-xs-perl libtypes-serialiser-perl libubsan1 libunicode-utf8-perl liburi-perl libuser-identity-perl
libvariable-magic-perl libwant-perl libwebp7 libwww-perl libwww-robotrules-perl libxapian30 libxml-libxml-perl
libxml-namespacesupport-perl libxml-parser-perl libxml-sax-base-perl libxml-sax-expat-perl libxml-sax-perl libxpm4
libxs-parse-keyword-perl libyaml-libyaml-perl licensecheck lintian linux-libc-dev lto-disabled-list lzip lzop make
manpages-dev notmuch patchutils perl-openssl-defaults python3-argcomplete python3-decorator python3-gpg python3-gssapi
python3-pgpy python3-pgpy-doc python3-unidiff python3-xdg rpcsvc-proto t1utils unzip wdiff
Suggested packages:
cpp-doc gcc-11-locales debtags adequate at autopkgtest bls-standalone check-all-the-things cvs-buildpackage debhelper
diffoscope disorderfs dose-extra duck elpa-devscripts faketime gnuplot how-can-i-help libdbd-pg-perl
.
.
.
0 upgraded, 259 newly installed, 0 to remove and 4 not upgraded.
Need to get 78.1 MB of archives.
After this operation, 257 MB of additional disk space will be used.
Do you want to continue? [Y/n]
おっ結構使いますね・・・このままインストールしてしまいます。
メールスプールの変換
メールスプールを確認します。
azureuser@test-azure-gen:~$ ls -alh /var/mail
total 16K
drwxrwsr-x 2 root mail 4.0K Apr 9 07:09 .
drwxr-xr-x 14 root root 4.0K Apr 7 14:36 ..
-rw------- 1 azureuser mail 0 Apr 8 06:13 azureuser
-rw------- 1 example mail 849 Apr 9 05:38 example
-rw------- 1 root mail 1.2K Apr 9 04:48 root
ユーザごとに mailbox ファイルが作られています。このユーザごとに変換作業を行います。
まず azureuser から。
azureuser@test-azure-gen:~$ mbox2maildir /var/mail/azureuser ~/Mailbox
azureuser@test-azure-gen:~$ ls ~/Mailbox
cur new tmp
次に root 。
azureuser@test-azure-gen:~$ sudo bash -
root@test-azure-gen:/home/azureuser# mbox2maildir /var/mail/user ~/Mailbox
root@test-azure-gen:/home/azureuser# ls /root
Mailbox snap
最後に example ユーザ。
root@test-azure-gen:/home/azureuser# su - example
example@test-azure-gen:~$ mbox2maildir /var/mail/example ~/Mailbox
example@test-azure-gen:~$ ls -alh
total 44K
drwxr-x--x 5 example example 4.0K Apr 9 07:09 .
drwxr-xr-x 4 root root 4.0K Apr 8 04:09 ..
-rw------- 1 example example 335 Apr 9 04:48 .bash_history
-rw-r--r-- 1 example example 220 Apr 8 04:09 .bash_logout
-rw-r--r-- 1 example example 3.7K Apr 8 04:09 .bashrc
-rw-r--r-- 1 example example 807 Apr 8 04:09 .profile
-rw------- 1 example example 1.3K Apr 8 04:17 .viminfo
drwx------ 5 example example 4.0K Apr 9 07:09 Mailbox
drwx------ 3 example example 4.0K Apr 9 05:34 mail
-rw------- 1 example example 817 Apr 8 06:14 mbox
drwxrwxr-x 2 example example 4.0K Apr 8 04:17 public_html
example@test-azure-gen:~$ exit
logout
変換を確認
先の実験
「Azure で Dovecot をインストール、telnet でメールを読む」
https://qiita.com/nanbuwks/items/c3f180fc44fa08f91820
で、 example ユーザにメールデータが残っている状態だったので、/home/example/Mailbox の変換結果に反映しているかどうか確認してみます。
root@test-azure-gen:/home/azureuser# ls /home/example/Mailbox
cur new tmp
root@test-azure-gen:/home/azureuser# ls /home/example/Mailbox/new
1681024194.M840509P34975Q1.test-azure-gen
root@test-azure-gen:/home/azureuser# cat /home/example/Mailbox/new/1681024194.M840509P34975Q1.test-azure-gen
Return-Path: <azureuser@test-azure-gen.d5vkxbztwwse1dua0e2ybepgyg.phxx.internal.cloudapp.net>
X-Original-To: example
Delivered-To: example@test-azure-gen.d5vkxbztwwse1dua0e2ybepgyg.phxx.internal.cloudapp.net
Received: by test-azure-gen.d5vkxbztwwse1dua0e2ybepgyg.phxx.internal.cloudapp.net (Postfix, from userid 1000)
id 646BD3F9B3; Sun, 9 Apr 2023 05:36:36 +0000 (UTC)
Message-Id: <20230409053636.646BD3F9B3@test-azure-gen.d5vkxbztwwse1dua0e2ybepgyg.phxx.internal.cloudapp.net>
Date: Sun, 9 Apr 2023 05:36:36 +0000 (UTC)
From: Ubuntu <azureuser@test-azure-gen.d5vkxbztwwse1dua0e2ybepgyg.phxx.internal.cloudapp.net>
X-IMAPbase: 1681018471 0000000001
X-UID: 1
Status: RO
Hello Dovecot
無事変換できているみたいです。
他のユーザの Maildir を作る
(2023/7/10 追記:)
上記以外のユーザの Maildir を作ります。
それぞれのユーザ権限で、以下のように作業をします。
$ mkdir ~/Maildir
$ chmod 700 ~/Maildir
また、新規ユーザに自動で Maildir が作られるように、以下のように設定しておきます。
$ sudo mkdir /etc/skel/Maildir
$ sudo chmod 700 /etc/skel/Maildir
postfix 設定変更
postfix の設定は、/etc/postfix/main.cf
で行いますが、
「Azure で postfix のインストールを試す」
https://qiita.com/nanbuwks/items/38b54aaf8c3ecfdbb3cc
でインストールした状態では、/etc/postfix/main.cf
は作られていません。
/etc/postfix/main.cf
が無かったり、あるけどそこで指定された項目以外の設定値は、デフォルト値が用いられます(デフォルト値はpostconf -d
コマンドで確認できます)。
デフォルト値では、postfix は mailbox を使う設定になっているので Maildir を使う設定だけを書き込んだ /etc/postfix/main.cf
を作成します。
以下の内容で /etc/postfix/main.cf
を作成します。
home_mailbox = Maildir/
setgid_group = postdrop
なお、設定値については /etc/postfix/main.cf.proto
に詳細が説明されています。
# DELIVERY TO MAILBOX
#
# The home_mailbox parameter specifies the optional pathname of a
# mailbox file relative to a user's home directory. The default
# mailbox file is /var/spool/mail/user or /var/mail/user. Specify
# "Maildir/" for qmail-style delivery (the / is required).
#
#home_mailbox = Mailbox
#home_mailbox = Maildir/
.
.
.
設定変更を反映します
azureuser@test-azure-gen:~$ sudo systemctl start postfix
postfix の動作確認
メールを送ります。
azureuser@test-azure-gen:~$ echo "Hello Maildir" | sendmail example
example に配送されているでしょうか?
azureuser@test-azure-gen:~$ ls /home/example/Maildir/new
ls: cannot access '/home/example/Maildir/new': Permission denied
エラーが出るので、sudo をつけてメールスプールを読みます。
azureuser@test-azure-gen:~$ sudo ls /home/example/Maildir/new
1681026269.V801I3fda9M274685.test-azure-gen
azureuser@test-azure-gen:~$ sudo cat /home/example/Maildir/new/1681026269.V801I3fda9M274685.test-azure-gen
Return-Path: <azureuser@test-azure-gen.localdomain>
X-Original-To: example
Delivered-To: example@test-azure-gen.localdomain
Received: by test-azure-gen.localdomain (Postfix, from userid 1000)
id 3B55E3FDA7; Sun, 9 Apr 2023 07:44:29 +0000 (UTC)
Message-Id: <20230409074429.3B55E3FDA7@test-azure-gen.localdomain>
Date: Sun, 9 Apr 2023 07:44:29 +0000 (UTC)
From: Ubuntu <azureuser@test-azure-gen.localdomain>
Hello Maildir
さて、先に azureuser だと エラーが出ました。これは Maildir がユーザーディレクトリ内にあるので、適切な権限がないとメールスプールファイルが読めないからです。
main.cf に設定した setgid_group = postdrop
の項目は、 postfix が Maildir にアクセスするときに使用するアクセス権を持つためのものです。
dovecot 設定変更
/etc/dovecot/conf.d/10-mail.conf
の冒頭部分
##
## Mailbox locations and namespaces
##
# Location for users' mailboxes. The default is empty, which means that Dovecot
# tries to find the mailboxes automatically. This won't work if the user
# doesn't yet have any mail, so you should explicitly tell Dovecot the full
# location.
#
# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u)
# isn't enough. You'll also need to tell Dovecot where the other mailboxes are
# kept. This is called the "root mail directory", and it must be the first
# path given in the mail_location setting.
#
# There are a few special variables you can use, eg.:
#
# %u - username
# %n - user part in user@domain, same as %u if there's no domain
# %d - domain part in user@domain, empty if there's no domain
# %h - home directory
#
# See doc/wiki/Variables.txt for full list. Some examples:
#
# mail_location = maildir:~/Maildir
# mail_location = mbox:~/mail:INBOX=/var/mail/%u
# mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
# <doc/wiki/MailLocation.txt>
#
mail_location = mbox:~/mail:INBOX=/var/mail/%u
この、mail_location
の項目を以下のように変更します。
mail_location = maildir:~/Maildir
変更を反映します。
azureuser@test-azure-gen:~$ sudo systemctl start dovecot
なお、postfix の設定では Maildir にアクセスする gid の設定も行う必要がありました。
dovecot の場合同じファイルには以下のようにあるのですが、これは最初から有効になっているようです。
# Group to enable temporarily for privileged operations. Currently this is
# used only with INBOX when either its initial creation or dotlocking fails.
# Typically this is set to "mail" to give access to /var/mail.
mail_privileged_group = mail
dovecpt の 動作確認
先の実験と同様に手元のPCから telnet でアクセスします。
$ telnet example.com 110
Trying 123.456.789.012...
Connected to example.com.
Escape character is '^]'.
+OK Dovecot (Ubuntu) ready.
user example
+OK
PASS hogehogefugafuga
+OK Logged in.
LIST
+OK 1 messages:
1 434
.
RETR 1
+OK 434 octets
Return-Path: <azureuser@test-azure-gen.localdomain>
X-Original-To: example
Delivered-To: example@test-azure-gen.localdomain
Received: by test-azure-gen.localdomain (Postfix, from userid 1000)
id 3B55E3FDA7; Sun, 9 Apr 2023 07:44:29 +0000 (UTC)
Message-Id: <20230409074429.3B55E3FDA7@test-azure-gen.localdomain>
Date: Sun, 9 Apr 2023 07:44:29 +0000 (UTC)
From: Ubuntu <azureuser@test-azure-gen.localdomain>
Hello Maildir
.
うまく読めていますね。今回はこのメールを削除して、Maildir へのアクセス権がちゃんと設定できているかどうか確認してみます。
DELE 1
+OK Marked to be deleted.
QUIT
+OK Logging out, messages deleted.
Connection closed by foreign host.
再度アクセス
$ telnet example.com 110
Trying 123.456.789.123...
Connected to example.com.
Escape character is '^]'.
+OK Dovecot (Ubuntu) ready.
USER example
+OK
PASS hogehogefugafuga
+OK Logged in.
LIST
+OK 0 messages:
.
QUIT
+OK Logging out.
Connection closed by foreign host.
先程読んだメールは削除されていました。設定はうまくいっているようです。
mail コマンドを Maildir に対応させる
(2023/07/09 追記)
上記のように telnet で Dovecot にアクセスするとメールが読めましたが、ローカルで mail コマンドを使うと届いたメールが読めなくなってました。
$ mail
No mail for example
調べてみると、歴史的な本来の mail コマンドは、いまどきは mailx というプログラムに置き換わっていて、 mail コマンドを呼ぶと mailx が動作するらしい。そして mailx はいくつもの実装があるらしい。
- bsd-mailx
- heirloom-mailx
- GNU Mailutils
そうして以前は Maildir 形式をサポートしたりしていなかったりだったらしいが・・・ 今使用している mailx は何だろう?
$ which mail
/usr/bin/mail
$ ls -alh /usr/bin/mail
lrwxrwxrwx 1 root root 22 Jul 2 05:01 /usr/bin/mail -> /etc/alternatives/mail
$ mail --version
mail (GNU Mailutils) 3.7
Copyright (C) 2007-2019 Free Software Foundation, inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
GNU Mailutils が入っているらしいです。なお、以下のようにして確かめてみたらその他の mailx のパッケージは用意されているようですが・・・
$ apt-cache search bsd-mailx
bsd-mailx - simple mail user agent
devscripts - scripts to make the life of a Debian Package maintainer easier
$ apt-cache search heirloom-mailx
t-prot - display filter for Internet messages
以下の設定ではスイッチできない模様。
$ sudo update-alternatives --config mailx
There is only one alternative in link group mailx (providing /usr/bin/mailx): /usr/bin/mail.mailutils
Nothing to configure.
さて、この GNU Mailutils ですが、以下のように環境変数を設定したら Maildir が読めるようです。
$ MAIL=~/Maildir
$ echo $MAIL
/home/example/Maildir
確認してみます。
$ mail
"/home/example/Maildir": 5 messages 5 unread
>U 1 Ubuntu 10/634
U 2 Ubuntu 10/632
U 3 Ubuntu 10/634
U 4 azureuser@test-azu 11/670
U 5 Ubuntu 10/634
? q
Held 5 messages in /home/example/Maildir
読めるようになりました
全員に反映するには、以下の一行を /etc/profile の末尾に足しておきます。
MAIL=~/Maildir