OCI上でローカルユーザベースのメールサーバ構築

postfix/dovecotを使ったIMAPメールサーバをOracle Linux 9.6上でOracle Cloud上のFree Tierで構築してみた

2025/10/30時点の状況としては、以下の問題が出て常用には難しい状態で、限定された用途にしか使えない、という感じとなった。

・OCIのFree TierではIPv4/IPv6アドレスに対する逆引き(PTR)が設定できないため gmailにメールが拒否される
・OCI上の仮想マシンから、外部のIPv4アドレスのポート25に対して通信が通らない。IPv6アドレスのポート25なら通る。(OCIの仕様)

準備1: 一般的な前準備

準備1-1: 日本時間にする

日本に住んでいる場合、日本時間表記の方が使いやすいので、OSも日本時間表示に設定する。

$ sudo timedatectl set-timezone Japan
$ 

手順1-2: swap追加

EPELレポジトリを追加した場合、メモリ1GB構成の場合、swapは5GB程度ないとdnfコマンドが正常に動作しないので、swapを増量する

/var/oled パーテーションに ファイルスワップを作成

$ sudo fallocate -l 4G /var/oled/swapfile
$ ls -l /var/oled/swapfile 
-rw-r--r--. 1 root root 4294967296 Sep  9 13:35 /var/oled/swapfile
$ sudo chmod 600 /var/oled/swapfile 
$ ls -l /var/oled/swapfile 
-rw-------. 1 root root 4294967296 Sep  9 13:35 /var/oled/swapfile
$ sudo mkswap /var/oled/swapfile 
Setting up swapspace version 1, size = 4 GiB (4294963200 bytes)
no label, UUID=bdd4f7a6-1dcc-43c8-bb2d-8f42ac2faf3f
$ 

作成したファイルをスワップとして登録

$ sudo swapon /var/oled/swapfile 
$ swapon --show
NAME               TYPE SIZE   USED PRIO
/.swapfile         file 951M 161.6M   -2
/var/oled/swapfile file   4G   8.2M   -3
$ cat /proc/swaps 
Filename                                Type            Size            Used            Priority
/.swapfile                              file            973820          165524          -2
/var/oled/swapfile                      file            4194300         8412            -3
$ 

/etc/fstab にスワップファイルの記述「/var/oled/swapfile none swap sw 0 0」を追加

$ sudo vi /etc/fstab
$ cat /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Thu Jun 12 01:18:32 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
/dev/mapper/ocivolume-root /                       xfs     defaults        0 0
UUID=dd88872e-0527-4193-8282-b8281f1ae6fd /boot                   xfs     defaults        0 0
UUID=AE3C-806E          /boot/efi               vfat    defaults,uid=0,gid=0,umask=077,shortname=winnt 0 2
/dev/mapper/ocivolume-oled /var/oled               xfs     defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults,nodev,nosuid,noexec      0 0
######################################
## ORACLE CLOUD INFRASTRUCTURE CUSTOMERS
##
## If you are adding an iSCSI remote block volume to this file you MUST
## include the '_netdev' mount option or your instance will become
## unavailable after the next reboot.
## SCSI device names are not stable across reboots; please use the device UUID instead of /dev path.
##
## Example:
## UUID="94c5aade-8bb1-4d55-ad0c-388bb8aa716a"   /data1    xfs       defaults,noatime,_netdev      0      2
##
## More information:
## https://docs.us-phoenix-1.oraclecloud.com/Content/Block/Tasks/connectingtoavolume.htm
/.swapfile      none    swap    sw      0       0
/var/oled/swapfile      none    swap    sw      0       0
$

準備2-3: パッケージを最新へアップデート

現時点での最新へアップデートする

$ sudo dnf update -y
<略>
$ sudo reboot

手順1-4: 日本語Locale対応

ja_JP.UTF-8など日本語Localeで設定した際、「Failed to set locale, defaulting to C.UTF-8」というメッセージが出力される場合があります。

その場合は日本語Localeを追加インストールします。

$ sudo dnf install langpacks-ja
<略>
$

手順1-5: kdump無効化

どうせ使わないのでkdumpを無効化

$ sudo systemctl disable kdump.service
Removed '/etc/systemd/system/multi-user.target.wants/kdump.service'.
$

手順2: EPELレポジトリの追加

EPELレポジトリを登録

$ sudo dnf config-manager --set-enabled ol10_u0_developer_EPEL
$  dnf repolist --all
repo id                                                                       repo name                                                                                                       status
ol9_MODRHCK                                                                   Latest RHCK with fixes from Oracle for Oracle Linux 9 (x86_64)                                                  disabled
ol9_RDMA                                                                      Oracle Linux 9 (x86_64) RDMA                                                                                    disabled
ol9_UEKR7                                                                     Oracle Linux 9 UEK Release 7 (x86_64)                                                                           disabled
ol9_UEKR8                                                                     Oracle Linux 9 UEK Release 8 (x86_64)                                                                           enabled
ol9_addons                                                                    Oracle Linux 9 Addons (x86_64)                                                                                  enabled
ol9_appstream                                                                 Oracle Linux 9 Application Stream Packages (x86_64)                                                             enabled
ol9_baseos_latest                                                             Oracle Linux 9 BaseOS Latest (x86_64)                                                                           enabled
ol9_codeready_builder                                                         Oracle Linux 9 CodeReady Builder (x86_64) - (Unsupported)                                                       disabled
ol9_developer                                                                 Oracle Linux 9 Development Packages (x86_64)                                                                    disabled
ol9_developer_EPEL                                                            Oracle Linux 9 EPEL Packages for Development (x86_64)                                                           enabled
ol9_developer_UEKR7                                                           Developer Preview of UEK Release 7 (x86_64)                                                                     disabled
ol9_developer_kvm_utils                                                       Oracle Linux 9 KVM Utilities for Development and test (x86_64)                                                  disabled
ol9_distro_builder                                                            Oracle Linux 9 Distro Builder (x86_64) - (Unsupported)                                                          disabled
ol9_ksplice                                                                   Ksplice for Oracle Linux 9 (x86_64)                                                                             enabled
ol9_kvm_utils                                                                 Oracle Linux 9 KVM Utilities (x86_64)                                                                           disabled
ol9_oci_included                                                              Oracle Linux 9 OCI Included Packages (x86_64)                                                                   enabled
ol9_u0_baseos_base                                                            Oracle Linux 9 BaseOS GA (x86_64)                                                                               disabled
ol9_u1_baseos_base                                                            Oracle Linux 9.1 BaseOS (x86_64)                                                                                disabled
ol9_u2_baseos_base                                                            Oracle Linux 9.2 BaseOS (x86_64)                                                                                disabled
ol9_u3_baseos_base                                                            Oracle Linux 9.3 BaseOS (x86_64)                                                                                disabled
ol9_u3_security_validation                                                    Oracle Linux 9 Update 3 (x86_64) Security Validations                                                           disabled
ol9_u4_baseos_base                                                            Oracle Linux 9.4 BaseOS (x86_64)                                                                                disabled
ol9_u5_baseos_base                                                            Oracle Linux 9.5 BaseOS (x86_64)                                                                                disabled
ol9_u6_baseos_base                                                            Oracle Linux 9.6 BaseOS (x86_64)                                                                                disabled
ol9_x86_64_userspace_ksplice                                                  Ksplice aware userspace packages for Oracle Linux 9 (x86_64)                                                    disabled
$

手順3: インターネット公開用設定

手順3-1: fail2ban導入

公開サーバは各種のアタックにさらされます。管理用sshポートにもやってきます。

多少なりとも軽減するためにEPELレポジトリ収録のfail2banを使用します。

$ sudo dnf install fail2ban -y
<略>
$

カスタム設定は/etc/fail2ban/jail.local に対して行います。

$ sudo vi /etc/fail2ban/jail.local 
$ cat /etc/fail2ban/jail.local 
[DEFAULT]
# 86400秒=24時間以内に5回不審なアクセスがあったら24時間BAN
bantime  = 86400
findtime  = 86400
maxretry = 5
# 259200秒=3日以内に5回不審なアクセスがあったら3日間BAN
#bantime  = 259200
#findtime  = 259200
#maxretry = 5
# 除外IP
ignoreip = 127.0.0.1 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
[sshd]
enabled = true
banaction = firewallcmd-ipset
$ 

上記設定では24時間BANにしていますが、まぁ、3日BANでもかまわないとは思います。(本当に間違えた場合に困るのでほどほどにしておくとよい)

fail2banをOS起動時に実行する設定と、今すぐfail2banを起動するコマンドを実行します。

$ sudo systemctl enable --now fail2ban
Created symlink '/etc/systemd/system/multi-user.target.wants/fail2ban.service' → '/usr/lib/systemd/system/fail2ban.service'.
$

以降、アタックがあると /var/log/fail2ban.log にログが出ます。

手順3-2: メールサーバ用ポート公開設定

初期設定では dhcpv6-client と ssh が許可されています。

$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources: 
  services: dhcpv6-client ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
$

とりあえずは smtp port 25, smtp-submission 587, imap 143 を開けます

[opc@ocimail ~]$ sudo firewall-cmd --permanent --add-service=smtp
success
[opc@ocimail ~]$ sudo firewall-cmd --permanent --add-service=smtp-submission
success
[opc@ocimail ~]$ sudo firewall-cmd --permanent --add-service=imap
success
[opc@ocimail ~]$ sudo firewall-cmd --reload
success
[opc@ocimail ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources: 
  services: dhcpv6-client imap smtp smtp-submission ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
[opc@ocimail ~]$ 

手順3-3: SSL更新用ポート

後述するのだが、SSLはLet’s Encryptを使う。

その際に、http ポート80と、https ポート 443が必要となるため、設定する

[opc@ocimail ~]$ sudo firewall-cmd --permanent --add-service=http
success
[opc@ocimail ~]$ sudo firewall-cmd --permanent --add-service=https
success
[opc@ocimail ~]$ sudo firewall-cmd --reload
success
[opc@ocimail ~]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources: 
  services: dhcpv6-client http https imap smtp smtp-submission ssh
  ports: 
  protocols: 
  forward: yes
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
[opc@ocimail ~]$ 

手順4: ソフトウェアインストール

postfixとdovecotをインストールします。

[opc@ocimail ~]$ sudo dnf install postfix dovecot -y
Last metadata expiration check: 2:15:42 ago on Wed 29 Oct 2025 03:42:39 AM GMT.
Dependencies resolved.
======================================================================================================================================================================================================
 Package                                     Architecture                         Version                                                           Repository                                   Size
======================================================================================================================================================================================================
Installing:
 dovecot                                     x86_64                               1:2.3.16-15.el9                                                   ol9_appstream                               5.2 M
 postfix                                     x86_64                               2:3.5.25-1.el9                                                    ol9_appstream                               1.7 M
Installing dependencies:
 clucene-core                                x86_64                               2.3.3.4-42.20130812.e8e3d20git.el9                                ol9_appstream                               594 k
 libexttextcat                               x86_64                               3.4.5-11.el9                                                      ol9_appstream                               382 k

Transaction Summary
======================================================================================================================================================================================================
Install  4 Packages

Total download size: 7.8 M
Installed size: 24 M
Downloading Packages:
(1/4): libexttextcat-3.4.5-11.el9.x86_64.rpm                                                                                                                          1.9 MB/s | 382 kB     00:00    
(2/4): clucene-core-2.3.3.4-42.20130812.e8e3d20git.el9.x86_64.rpm                                                                                                     1.8 MB/s | 594 kB     00:00    
(3/4): dovecot-2.3.16-15.el9.x86_64.rpm                                                                                                                                12 MB/s | 5.2 MB     00:00    
(4/4): postfix-3.5.25-1.el9.x86_64.rpm                                                                                                                                6.0 MB/s | 1.7 MB     00:00    
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                                                  16 MB/s | 7.8 MB     00:00     
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                                                                              1/1 
  Installing       : libexttextcat-3.4.5-11.el9.x86_64                                                                                                                                            1/4 
  Installing       : clucene-core-2.3.3.4-42.20130812.e8e3d20git.el9.x86_64                                                                                                                       2/4 
  Running scriptlet: dovecot-1:2.3.16-15.el9.x86_64                                                                                                                                               3/4 
  Installing       : dovecot-1:2.3.16-15.el9.x86_64                                                                                                                                               3/4 
  Running scriptlet: dovecot-1:2.3.16-15.el9.x86_64                                                                                                                                               3/4 
  Running scriptlet: postfix-2:3.5.25-1.el9.x86_64                                                                                                                                                4/4 
  Installing       : postfix-2:3.5.25-1.el9.x86_64                                                                                                                                                4/4 
  Running scriptlet: postfix-2:3.5.25-1.el9.x86_64                                                                                                                                                4/4 
  Running scriptlet: dovecot-1:2.3.16-15.el9.x86_64                                                                                                                                               4/4 
  Running scriptlet: postfix-2:3.5.25-1.el9.x86_64                                                                                                                                                4/4 
  Verifying        : clucene-core-2.3.3.4-42.20130812.e8e3d20git.el9.x86_64                                                                                                                       1/4 
  Verifying        : dovecot-1:2.3.16-15.el9.x86_64                                                                                                                                               2/4 
  Verifying        : libexttextcat-3.4.5-11.el9.x86_64                                                                                                                                            3/4 
  Verifying        : postfix-2:3.5.25-1.el9.x86_64                                                                                                                                                4/4 

Installed:
  clucene-core-2.3.3.4-42.20130812.e8e3d20git.el9.x86_64            dovecot-1:2.3.16-15.el9.x86_64            libexttextcat-3.4.5-11.el9.x86_64            postfix-2:3.5.25-1.el9.x86_64           

Complete!
[opc@ocimail ~]$ 

手順5: SSL証明書関連

手順5-1: dhパラメータファイルの作成

diffie-hellman パラメータファイル を /etc/dovecot/conf.d/10-ssl.conf にあるパス /etc/dovecot/dh.pem に作成。なお、30分以上かかる。

[opc@ocimail ~]$ sudo openssl dhparam -out /etc/dovecot/dh.pem 4096
Generating DH parameters, 4096 bit long safe prime
..............................................................................................................+......................................+................................................
<略>

手順5-2: dehydratedによるLet’s Encrypt導入

Let’s EncryptによるSSL証明書導入はcertbotを使うのが一般的ではあるのだが、python環境とあわせてパッケージサイズが大きいので、コンパクトでEPELにも収録されているdehydratedを使用する。

[opc@ocimail ~]$ sudo dnf install dehydrated -y
Last metadata expiration check: 3:29:19 ago on Wed 29 Oct 2025 03:42:39 AM GMT.
Dependencies resolved.
======================================================================================================================================================================================================
 Package                                       Architecture                              Version                                          Repository                                             Size
======================================================================================================================================================================================================
Installing:
 dehydrated                                    noarch                                    0.7.1-6.el9                                      ol9_developer_EPEL                                    154 k
Installing dependencies:
 s-nail                                        x86_64                                    14.9.22-6.el9                                    ol9_appstream                                         626 k

Transaction Summary
======================================================================================================================================================================================================
Install  2 Packages

Total download size: 780 k
Installed size: 1.4 M
<略>
Installed:
  dehydrated-0.7.1-6.el9.noarch                                                                      s-nail-14.9.22-6.el9.x86_64                                                                     

Complete!
[opc@ocimail ~]$

dehydratedによるSSL証明書取得処理にはhttp port80アクセスと /var/www/dehydrated が使用されるためhttpdのインストールとディレクトリを作成します。

[opc@ocimail ~]$ sudo dnf install httpd -y
Last metadata expiration check: 3:31:07 ago on Wed 29 Oct 2025 03:42:39 AM GMT.
Dependencies resolved.
======================================================================================================================================================================================================
 Package                                           Architecture                          Version                                               Repository                                        Size
======================================================================================================================================================================================================
Installing:
 httpd                                             x86_64                                2.4.62-4.0.1.el9_6.4                                  ol9_appstream                                     64 k
Installing dependencies:
 apr                                               x86_64                                1.7.0-12.el9_3                                        ol9_appstream                                    131 k
 apr-util                                          x86_64                                1.6.1-23.el9                                          ol9_appstream                                     99 k
 apr-util-bdb                                      x86_64                                1.6.1-23.el9                                          ol9_appstream                                     12 k
 httpd-core                                        x86_64                                2.4.62-4.0.1.el9_6.4                                  ol9_appstream                                    1.8 M
 httpd-filesystem                                  noarch                                2.4.62-4.0.1.el9_6.4                                  ol9_appstream                                     11 k
 httpd-tools                                       x86_64                                2.4.62-4.0.1.el9_6.4                                  ol9_appstream                                     93 k
 oracle-logos-httpd                                noarch                                90.4-1.0.1.el9                                        ol9_baseos_latest                                 37 k
Installing weak dependencies:
 apr-util-openssl                                  x86_64                                1.6.1-23.el9                                          ol9_appstream                                     14 k
 mod_http2                                         x86_64                                2.0.26-4.el9_6.1                                      ol9_appstream                                    171 k
 mod_lua                                           x86_64                                2.4.62-4.0.1.el9_6.4                                  ol9_appstream                                     58 k

Transaction Summary
======================================================================================================================================================================================================
Install  11 Packages

Total download size: 2.5 M
Installed size: 6.1 M
Downloading Packages:
<略>
Installed:
  apr-1.7.0-12.el9_3.x86_64                  apr-util-1.6.1-23.el9.x86_64                    apr-util-bdb-1.6.1-23.el9.x86_64                      apr-util-openssl-1.6.1-23.el9.x86_64            
  httpd-2.4.62-4.0.1.el9_6.4.x86_64          httpd-core-2.4.62-4.0.1.el9_6.4.x86_64          httpd-filesystem-2.4.62-4.0.1.el9_6.4.noarch          httpd-tools-2.4.62-4.0.1.el9_6.4.x86_64         
  mod_http2-2.0.26-4.el9_6.1.x86_64          mod_lua-2.4.62-4.0.1.el9_6.4.x86_64             oracle-logos-httpd-90.4-1.0.1.el9.noarch             

Complete!
[opc@ocimail ~]$ sudo mkdir /var/www/dehydrated
[opc@ocimail ~]$ 

http://~/.well-known/acme-challenge でアクセスした時に上記ディレクトリが開くようApacheの設定を /etc/httpd/conf.d/dehydrated.conf として作成します。(sudo vi /etc/httpd/conf.d/dehydrated.conf )

[opc@ocimail ~]$ sudo vi /etc/httpd/conf.d/dehydrated.conf 
[opc@ocimail ~]$ cat /etc/httpd/conf.d/dehydrated.conf 
Alias /.well-known/acme-challenge /var/www/dehydrated
<Directory /var/www/dehydrated/>
</Directory>
[opc@ocimail ~]$ 

httpdを起動します

[opc@ocimail ~]$ sudo systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[opc@ocimail ~]$ 

SSL証明書を発行するホスト名を /etc/dehydrated/domains.txt に記載する。(sudo vi /etc/dehydrated/domains.txt)

$ sudo vi /etc/dehydrated/domains.txt
$ sudo cat /etc/dehydrated/domains.txt
ホスト1名.ドメイン名 ホスト2名.ドメイン名
$

登録操作を開始します。

[opc@ocimail ~]$ sudo dehydrated --register
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/local.sh

To use dehydrated with this certificate authority you have to agree to their terms of service which you can find here: https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf

To accept these terms of service run "/bin/dehydrated --register --accept-terms".
[opc@ocimail ~]$ sudo dehydrated --register --accept-terms
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
+ Generating account key...
+ Registering account key with ACME server...
+ Fetching account URL...
+ Done!
[opc@ocimail ~]$ 

初回のSSL証明書発行処理を実行します。

[opc@ocimail ~]$ sudo dehydrated --cron
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/local.sh
Processing ocimail.websa.jp
 + Signing domains...
 + Generating private key...
 + Generating signing request...
 + Requesting new certificate order from CA...
 + Received 1 authorizations URLs from the CA
 + Handling authorization for ホスト名
 + 1 pending challenge(s)
 + Deploying challenge tokens...
 + Responding to challenge for ocimail.websa.jp authorization...
 + Challenge is valid!
 + Cleaning challenge tokens...
 + Requesting certificate...
Warning: Will read cert request from stdin since no -in option is given
 + Checking certificate...
 + Done!
 + Creating fullchain.pem...
 + Done!
 + Running automatic cleanup
Moving unused file to archive directory: ホスト名/cert-1761722366.csr
Moving unused file to archive directory: ホスト名/cert-1761722366.pem
Moving unused file to archive directory: ホスト名/privkey-1761722366.pem
[opc@ocimail ~]$ 

これで/etc/dehydrated/certs/ホスト名/ にSSL証明書が作成される

[opc@ocimail ~]$ sudo ls -l /etc/dehydrated/certs/ホスト名/
total 20
-rw-------. 1 root root 1655 Oct 29 07:26 cert-1761722787.csr
-rw-------. 1 root root 2134 Oct 29 07:26 cert-1761722787.pem
lrwxrwxrwx. 1 root root   19 Oct 29 07:26 cert.csr -> cert-1761722787.csr
lrwxrwxrwx. 1 root root   19 Oct 29 07:26 cert.pem -> cert-1761722787.pem
-rw-------. 1 root root 1802 Oct 29 07:26 chain-1761722787.pem
lrwxrwxrwx. 1 root root   20 Oct 29 07:26 chain.pem -> chain-1761722787.pem
-rw-------. 1 root root 3936 Oct 29 07:26 fullchain-1761722787.pem
lrwxrwxrwx. 1 root root   24 Oct 29 07:26 fullchain.pem -> fullchain-1761722787.pem
-rw-------. 1 root root 3272 Oct 29 07:26 privkey-1761722787.pem
lrwxrwxrwx. 1 root root   22 Oct 29 07:26 privkey.pem -> privkey-1761722787.pem
[opc@ocimail ~]$ 

dovecot設定

dovecot ssl設定

/etc/dovecot/conf.d/10-ssl.conf にて

「ssl = required」を「ssl = yes」に変更

# SSL/TLS support: yes, no, required. &lt;doc/wiki/SSL.txt>
# disable plain pop3 and imap, allowed are only pop3+TLS, pop3s, imap+TLS and imaps
# plain imap and pop3 are still allowed for local connections
ssl = yes

ssl_certとssl_keyをdehydratedが出力したファイルに置き換え

# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
# dropping root privileges, so keep the key file unreadable by anyone but
# root. Included doc/mkcert.sh can be used to easily generate self-signed
# certificate, just make sure to update the domains in dovecot-openssl.cnf
ssl_cert = &lt;/etc/dehydrated/certs/ホスト名/fullchain.pem
ssl_key = &lt;/etc/dehydrated/certs/ホスト名/privkey.pem

dhパラメータのコメントを取る

# SSL DH parameters
# Generate new params with `openssl dhparam -out /etc/dovecot/dh.pem 4096`
# Or migrate from old ssl-parameters.dat file with the command dovecot
# gives on startup when ssl_dh is unset.
ssl_dh = &lt;/etc/dovecot/dh.pem

dovecotのメイン設定ファイル

/etc/dovecot/dovecot.conf に以下の変更

標準だと「imap pop3 lmtp submission」となっているものから、imapとsubmissionとする

# Protocols we want to be serving.
#protocols = imap pop3 lmtp submission
protocols = imap submission

dovecotのメール保存に関するファイル

/etc/dovecot/conf.d/10-mail.conf に以下の変更

maildir形式で各ユーザのホームディレクトリに保存する設定

#   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
#
# &lt;doc/wiki/MailLocation.txt>
#
mail_location = maildir:~/Maildir

quotaを有効化するため、mail_plugins に「$mail_plugins quota」を追加

# Space separated list of plugins to load for all services. Plugins specific to
# IMAP, LDA, etc. are added to this list in their own .conf files.
mail_plugins = $mail_plugins quota

mailboxのindexを有効にする設定「mailbox_list_index = yes」を入れる

##
## Mailbox handling optimizations
##

# Mailbox list indexes can be used to optimize IMAP STATUS commands. They are
# also required for IMAP NOTIFY extension to be enabled.
mailbox_list_index = yes

IMAPログイン時のパスワード取り扱い設定

IMAPログイン時のパスワードを暗号化して送信する、というのが現代の設定となる。

古い仕様のメールクラインとがいたとすると、平文パスワードを許可する設定を /etc/dovecot/conf.d/10-auth.conf に追加する必要がある。

その場合は下記を「disable_plaintext_auth = no」に変更する

# Disable LOGIN command and all other plaintext authentications unless
# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
# matches the local IP (ie. you're connecting from the same computer), the
# connection is considered secure and plaintext authentication is allowed.
# See also ssl=required setting.
#disable_plaintext_auth = yes

また、下記を「auth_mechanism = plain login」に変更する

# Space separated list of wanted authentication mechanisms:
#   plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp
#   gss-spnego
# NOTE: See also disable_plaintext_auth setting.
auth_mechanisms = plain

dovecotのSMTP-auth動作時の設定

/etc/dovecot/conf.d/10-master.conf でコメントアウトされている smtp-authに関する設定を少し修正して設定する

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

dovecotのIMAP設定

/etc/dovecot/conf.d/20-imap.conf にて mail_plugin として「imap_quota」を追加

protocol imap {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins imap_quota

  # Maximum number of IMAP connections allowed for a user from each IP address.
  # NOTE: The username is compared case-sensitively.
  #mail_max_userip_connections = 10
}

dovecotのメールボックス取り扱い設定

/etc/dovecot/conf.d/15-mailboxes.conf を修正することで、メールソフトによってフォルダ名に微妙な違いがあるのをある程度吸収できる。

##
## Mailbox definitions
##

# Each mailbox is specified in a separate mailbox section. The section name
# specifies the mailbox name. If it has spaces, you can put the name
# "in quotes". These sections can contain the following mailbox settings:
#
# auto:
#   Indicates whether the mailbox with this name is automatically created
#   implicitly when it is first accessed. The user can also be automatically
#   subscribed to the mailbox after creation. The following values are
#   defined for this setting:
# 
#     no        - Never created automatically.
#     create    - Automatically created, but no automatic subscription.
#     subscribe - Automatically created and subscribed.
#  
# special_use:
#   A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the
#   mailbox. There are no validity checks, so you could specify anything
#   you want in here, but it's not a good idea to use flags other than the
#   standard ones specified in the RFC:
#
#     \All       - This (virtual) mailbox presents all messages in the
#                  user's message store.
#     \Archive   - This mailbox is used to archive messages.
#     \Drafts    - This mailbox is used to hold draft messages.
#     \Flagged   - This (virtual) mailbox presents all messages in the
#                  user's message store marked with the IMAP \Flagged flag.
#     \Important - This (virtual) mailbox presents all messages in the
#                  user's message store deemed important to user.
#     \Junk      - This mailbox is where messages deemed to be junk mail
#                  are held.
#     \Sent      - This mailbox is used to hold copies of messages that
#                  have been sent.
#     \Trash     - This mailbox is used to hold messages that have been
#                  deleted.
#
# comment:
#   Defines a default comment or note associated with the mailbox. This
#   value is accessible through the IMAP METADATA mailbox entries
#   "/shared/comment" and "/private/comment". Users with sufficient
#   privileges can override the default value for entries with a custom
#   value.

# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox "下書き" {
    special_use = \Drafts
  }
  mailbox INBOX.Drafts {
    special_use = \Drafts
  }

  mailbox Junk {
    special_use = \Junk
  }
  mailbox "迷惑メール" {
    special_use = \Junk
  }
  mailbox "Junk Email" {
    special_use = \Junk
  }
  mailbox "INBOX.Junk Email" {
    special_use = \Junk
  }

  mailbox Trash {
    special_use = \Trash
  }
  mailbox "削除済みアイテム" {
    special_use = \Trash
  }
  mailbox "Deleted Items" {
    special_use = \Trash
  }
  mailbox "INBOX.Deleted Items" {
    special_use = \Trash
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  mailbox "送信済みアイテム" {
    special_use = \Sent
  }
  mailbox "Sent Items" {
    special_use = \Sent
  }
  mailbox "INBOX.Sent Items" {
    special_use = \Sent
  }

  # If you have a virtual "All messages" mailbox:
  #mailbox virtual/All {
  #  special_use = \All
  #  comment = All my messages
  #}

  # If you have a virtual "Flagged" mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged
  #  comment = All my flagged messages
  #}

  # If you have a virtual "Important" mailbox:
  #mailbox virtual/Important {
  #  special_use = \Important
  #  comment = All my important messages
  #}
}

dovecotのquota設定

既存の /etc/dovecot/conf.d/90-quota.conf の最後に下記を追加する

これは100MBで制限する例

mailbox_list_index = yes

# Avoid spending excessive time waiting for the quota calculation to finish
# when mails' vsizes aren't already cached. If this many mails are opened,
# finish the quota calculation on background in indexer-worker process. Mail
# deliveries will be assumed to succeed, and explicit quota lookups will
# return internal error. (v2.2.28+)
protocol !indexer-worker {
  mail_vsize_bg_after_count = 100
}

plugin {
  quota = count:User quota
  quota_rule = *:storage=100M
  #quota_rule2 = Trash:storage=+100M

  # This is required - it uses "virtual sizes" rather than "physical sizes"
  # for quota counting:
  quota_vsizes = yes
}

dovecotのsmtp submission設定

/etc/dovecot/conf.d/20-submission.conf にて設定する

dovecot自体ではメール配送を行わないので、postfix側に引き渡すのだが、同じホスト上にあったとしてもlocalhost指定ではなく、外部から見えるホスト名で指定する。

# Relay server configuration:
#
# The Dovecot SMTP submission service directly proxies the mail transaction
# to the SMTP relay configured here.

# Host name for the relay server (required)
submission_relay_host = ホスト名.ドメン名

postfix側設定

postfix側は /etc/postfix/main.cf へ設定を行う

Oracle Cloud上だとホスト名が内部のみの ホスト名.subnet<数字>.vcn<数字>.oraclevcn.comといったものとなっているので、DNS上のホスト名をmyhostnameで設定する

# INTERNET HOST AND DOMAIN NAMES
# 
# The myhostname parameter specifies the internet hostname of this
# mail system. The default is to use the fully-qualified domain name
# from gethostname(). $myhostname is used as a default value for many
# other configuration parameters.
#
#myhostname = host.domain.tld
#myhostname = virtual.domain.tld
myhostname = ホスト名.ドメイン名

続いてmydomain も 外部で認識させたいドメイン名を入れる

# The mydomain parameter specifies the local internet domain name.
# The default is to use $myhostname minus the first component.
# $mydomain is used as a default value for many other configuration
# parameters.
#
#mydomain = domain.tld
mydomain = ドメイン名

外部に送信するメールの@以降の部分はドメイン名としたいので「myorigin = $mydomain」の方を有効にします。

# SENDING MAIL
# 
# The myorigin parameter specifies the domain that locally-posted
# mail appears to come from. The default is to append $myhostname,
# which is fine for small sites.  If you run a domain with multiple
# machines, you should (1) change this to $mydomain and (2) set up
# a domain-wide alias database that aliases each user to
# user@that.users.mailhost.
#
# For the sake of consistency between sender and recipient addresses,
# myorigin also specifies the default domain name that is appended
# to recipient addresses that have no @domain part.
#
#myorigin = $myhostname
myorigin = $mydomain

外部からpostfixにアクセスする必要があるので「inet_interfaces = all」を有効にします

# The inet_interfaces parameter specifies the network interface
# addresses that this mail system receives mail on.  By default,
# the software claims all active interfaces on the machine. The
# parameter also controls delivery of mail to user@[ip.address].
#
# See also the proxy_interfaces parameter, for network addresses that
# are forwarded to us via a proxy or network address translator.
#
# Note: you need to stop/start Postfix when this parameter changes.
#
inet_interfaces = all
#inet_interfaces = $myhostname
#inet_interfaces = $myhostname, localhost
#inet_interfaces = localhost

# Enable IPv4, and IPv6 if supported
inet_protocols = all

自サーバで受信するメールドメインの設定は2番目のドメイン宛ても受け取るやつにします

# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
#
#mydestination = $myhostname, localhost.$mydomain, localhost
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
#       mail.$mydomain, www.$mydomain, ftp.$mydomain

ローカルユーザとしてメールを受け取りたいので、local_recipient_mapsを明示的に有効にします。

# The right-hand side of the lookup tables is conveniently ignored.
# In the left-hand side, specify a bare username, an @domain.tld
# wild-card, or specify a user@domain.tld address.
# 
local_recipient_maps = unix:passwd.byname $alias_maps
#local_recipient_maps = proxy:unix:passwd.byname $alias_maps
#local_recipient_maps =

postfixでメールを送信できるようにする設定

メール送信を許可するネットワークを mynetworks で行う

#mynetworks = 168.100.189.0/28, 127.0.0.0/8
#mynetworks = $config_directory/mynetworks
#mynetworks = hash:/etc/postfix/network_table

また、以下を追加

# With Postfix version before 2.10, use smtpd_recipient_restrictions
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

postfixのssl証明書設定

/etc/postfix/main.cf の最後の方にSSL関連の設定がある

# The full pathname of a file with the Postfix SMTP server RSA certificate
# in PEM format. Intermediate certificates should be included in general,
# the server certificate first, then the issuing CA(s) (bottom-up order).
#
smtpd_tls_cert_file = /etc/dehydrated/certs/ocimail.websa.jp/fullchain.pem
# The full pathname of a file with the Postfix SMTP server RSA private key
# in PEM format. The private key must be accessible without a pass-phrase,
# i.e. it must not be encrypted.
#
smtpd_tls_key_file = /etc/dehydrated/certs/ocimail.websa.jp/privkey.pem

postfix側からdovecotを起動する設定

/etc/postfix/master.cf の最終行に以下を追加

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/dovecot-lda -f ${sender} -d ${recipient}

postfixからSASLを使ってdovecot連携する手法は使わない

今回はsmtp submissionはdovecot側で行うので、SASLを使ってdovecotと連携するための下記設定は行わない。

smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
# dovecot sasl configuration
smtpd_sasl_type = dovecot
# Can be an absolute path, or relative to $queue_directory
# Debian/Ubuntu users: Postfix is setup by default to run chrooted, so it is best to leave it as-is below
smtpd_sasl_path = private/auth
# and the common settings to enable SASL:
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous 

トラブル対応

gmail宛てがgmail側で受け取り拒否

gmailに送ったところ、メールがなかなか届かないので/var/log/maillogを確認

Oct 30 10:15:28 ocimail postfix/smtp[5898]: AA57A309E87E: to=&lt;アドレス@gmail.com>, relay=gmail-smtp-in.l.google.com[2404:6800:4008:c15::1b]:25, delay=2.6, delays=0.29/0.19/1.2/0.9, dsn=5.7.1, status=bounced (host gmail-
smtp-in.l.google.com[2404:6800:4008:c15::1b] said: 550-5.7.1 [2603:c023:f:9000:0:7a41:2e84:f27f] Gmail has detected that this 550-5.7.1 message does not meet IPv6 sending guidelines regarding PTR records 550-5.7.1 and auth
entication. For more information, go to 550 5.7.1  https://support.google.com/mail/?p=IPv6AuthError 41be03b00d2f7-b71f4ba78c7si7488417a12.1056 - gsmtp (in reply to end of DATA command))

「Gmail has detected that this 550-5.7.1 message does not meet IPv6 sending guidelines regarding PTR records 550-5.7.1 and authentication. For more information, go to 550 5.7.1 https://support.google.com/mail/?p=IPv6AuthError」という形で拒否されていた。

リンク先はGoogleの「メール送信者のガイドライン」の最後のあたりで下記の様に書かれている

IPv6 認証エラーを修正する
送信元サーバーの PTR レコードで IPv6 が使用されていない場合、IPv6 認証エラーが返される場合があります。メールサービス プロバイダを利用している場合は、プロバイダが IPv6 の PTR レコードを使用していることを確認してください。

IPv6 認証エラーの例を次に示します。
550-5.7.1: Message does not meet IPv6 sending guidelines regarding PTR records and authentication.(メールが PTR レコードと認証に関する IPv6 の送信ガイドラインに準拠していません。)

あと、最初の方に書かれているIPアドレスに対する要件も関係している

インフラストラクチャ設定の要件とガイドライン
IP アドレス
重要: 送信元 IP アドレスは、ポインタ(PTR)レコードで指定されたホスト名の IP アドレスと一致している必要があります。

送信元 SMTP サーバーのパブリック IP アドレスには、対応するホスト名を参照する PTR レコードが必要です。これは、リバース DNS ルックアップと呼ばれます。このホスト名には、送信元サーバーと同じパブリック IP アドレスを参照する A レコード(IPv4 の場合)または AAAA レコード(IPv6 の場合)も必要です。これは、フォワード DNS ルックアップと呼ばれます。
送信元サーバーの IP アドレスとドメインを対応付ける有効なリバース DNS レコードを設定します。Google 管理者ツールボックスの Dig ツールを使用して PTR レコードを確認します。
重要: 送信元 IP アドレスは、ポインタ(PTR)レコードで指定されたホスト名の IP アドレスと一致している必要があります。

つまり、IPv6アドレスのPTRレコードに対してちゃんとホスト名を設定する必要があるようだ。

じゃあ、Oracle Cloudの場合、それを設定できるのか?を確認

Oracle Cloud Infrastructureドキュメント:逆引きDNS (PTR)

クラウドIPアドレスに対してPTRレコードを確立するようにリクエストできます:
1. リクエストをオープンする前の完全修飾ドメイン名をIPに示したA (IPv4)またはAAAA (IPv6)フォワード・レコードを作成します。レコードは、Oracle Cloud Infrastructure DNSサービスまたはサードパーティDNSプロバイダを使用して作成できます。
2. サービス・リクエストをオープンして、次の情報を含めます:
a. PTRに必要なIPアドレスおよび完全修飾ドメイン名(FQDN)。
b. ステップ1で作成したフォワード・レコードのFQDN。

サービス・リクエストの受信後、フォワード(AまたはAAAA)レコード情報は、正常に解決できることが検証され、OracleによってPTRレコードが作成されます。

Web UIでは設定できないのでサービスリクエストから申請する必要がある、とのこと。

サービスリクエストのリンクを飛ぶと「サポート・リクエスト」になったが、読むと・・・

サポート・リクエストは有料アカウントでのみ利用可能です。Always Freeリソースのみを使用する顧客およびFree Tierアカウントを使用する顧客はOracle Supportの対象ではありません。サポートが必要な場合は、サポート・チャットおよびCloud Customer Connectを使用します。

とある、サポートチャットで、対応してもらえるんだろうか?

OCI CLIコマンドのdnsオプションで操作できないのか?

パッケージ oci-utils ではなく、パッケージ python39-oci-cli の方だった

[root@ocimail ~]# dnf install python39-oci-cli
Last metadata expiration check: 2:19:30 ago on Thu 30 Oct 2025 08:47:09 AM JST.
Dependencies resolved.
==============================================================================================================================================================================================================================
 Package                                                        Architecture                               Version                                               Repository                                              Size
==============================================================================================================================================================================================================================
Installing:
 python39-oci-cli                                               noarch                                     3.69.0-1.el9                                          ol9_oci_included                                        46 M
Upgrading:
 python39-oci-sdk                                               x86_64                                     2.162.0-1.el9                                         ol9_oci_included                                        91 M
Installing dependencies:
 python3-arrow                                                  noarch                                     1.2.3-5.el9                                           ol9_developer_EPEL                                     166 k
 python3-importlib-metadata                                     noarch                                     4.12.0-2.el9                                          ol9_oci_included                                        75 k
 python3-jmespath                                               noarch                                     0.10.0-4.el9                                          ol9_oci_included                                        78 k
 python3-prompt-toolkit                                         noarch                                     3.0.38-4.el9                                          ol9_oci_included                                       1.0 M
 python3-terminaltables                                         noarch                                     3.1.10-8.0.1.el9                                      ol9_oci_included                                        60 k
 python3-wcwidth                                                noarch                                     0.2.5-8.el9                                           ol9_appstream                                           65 k
 python3-zipp                                                   noarch                                     3.20.1-2.el9                                          ol9_oci_included                                        48 k

Transaction Summary
==============================================================================================================================================================================================================================
Install  8 Packages
Upgrade  1 Package

Total download size: 138 M
Is this ok [y/N]: y
<略>
Upgraded:
  python39-oci-sdk-2.162.0-1.el9.x86_64                                                                                                                                                                                       
Installed:
  python3-arrow-1.2.3-5.el9.noarch     python3-importlib-metadata-4.12.0-2.el9.noarch   python3-jmespath-0.10.0-4.el9.noarch   python3-prompt-toolkit-3.0.38-4.el9.noarch   python3-terminaltables-3.1.10-8.0.1.el9.noarch  
  python3-wcwidth-0.2.5-8.el9.noarch   python3-zipp-3.20.1-2.el9.noarch                 python39-oci-cli-3.69.0-1.el9.noarch  

Complete!
[root@ocimail ~]# 

いれたものの、DNSの逆引き設定ができそうな感じはなかった・・・

とりあえず、IPv6を使わないようにすればごまかせる、という話が「How I Fixed Gmail Rejecting Emails by Disabling IPv6 in Postfix」にあったので /etc/postfix/main.cfの「inet_protocols = all」を「inet_protocols = ipv4」に変更

# Enable IPv4, and IPv6 if supported
inet_protocols = ipv4

ただ、これをやったところ、dovecot submissionで受け取ったメールがpostfixに引き渡されてくれないという問題が発生・・・

how to set smtp-client -> submission_relay_host for IPv4 only?」で似たような感じで、IPv4だけでつなげたい場合設定はあるのか?という話があるが、/etc/hosts に書くぐらいの対処方法しかないようだ

で・・・さらに原因を調査してみて判明したこと

どうやら、Oracle Cloud内部の仮想マシン上から外部のIPv4アドレスに対してのポート25アクセスができない模様

IPv6アドレスであればいける

[root@ocimail ~]# telnet 外部メールサーバ 25
Trying <IPv6アドレス>...
Connected to 外部メールサーバ.
Escape character is '^]'.
220 外部メールサーバ ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.
[root@ocimail ~]# telnet -4 外部メールサーバ 25
Trying <IPv4アドレス>...
^C
[root@ocimail ~]# 

ポート80だったらIPv4でも問題無いので、IPv4 ポート25に関してだけ規制されている模様

[root@ocimail ~]# telnet -4 外部メールサーバ 80
Trying <IPv4アドレス>...
Connected to 外部メールサーバ.
Escape character is '^]'.
GET / HTTP/1.0

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 30 Oct 2025 06:02:36 GMT
Content-Type: text/html
Content-Length: 162
Connection: close
Location: https://_/
X-Frame-Options: sameorigin
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Content-Security-Policy: default-src https: data: 'unsafe-inline' 'unsafe-eval'
Referrer-Policy: strict-origin

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
Connection closed by foreign host.
[root@ocimail ~]# 

試しにOCIのセキュリティリストのセキュリティルールにて、エグレスルールとして、ポート25を追加してみたものの状況は変わりませんでした。(ステートフルのチェックを入れた場合も変化無し)

・・・Oracle Cloudドキュメントにポート25はブロックしてると記載されていました。

アウトバウンドSMTPがブロックされます

OutlookとIMAPのフォルダ事情

OutlookでIMAPメールサーバを登録した時に表示されるフォルダがいまいちなことがある

その原因についていろんな調べてみた

まだアクセスしたことないけどメールが届いているユーザのメールボックス状態とそのときのディレクトリ

# doveadm mailbox list -u testuser3
INBOX
# ls -aF /var/vmail/testuser3/Maildir/
./    dovecot-uidlist               dovecot.index.log       tmp/
../   dovecot-uidvalidity           dovecot.list.index.log
cur/  dovecot-uidvalidity.68eef53b  new/
#

このときのINBOXフォルダの実態はどこかになるかを確認すると下記の様になっており、各ユーザのメールボックスのroot がINBOXとなっている、ということがわかる。

# doveadm mailbox path -u testuser3 INBOX
/var/vmail/testuser3/Maildir
#

次に、OutlookにIMAPサーバ設定を追加してログインしてみる

上記のようなメールボックスが表示される

doveadmコマンドで確認すると日本語名のメールボックスが確認できる

# doveadm mailbox list -u testuser3
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
#

実際に作られているディレクトリを確認すると、日本語文字列ではない修正UTF-7と呼ばれるものになっている。(UTF-8ベースではなくUTF-7ベースなのかは2000年以前のsendmailでは8bit目を取り扱えないシステムも存在していたため7bitで表現できる範囲に収める必要があった。これを引き継いで7bit範囲内に収まるUTF-7を採用したと思われる)

# ls -aF /var/vmail/testuser3/Maildir/
 ./                            dovecot-uidvalidity.68eef53f
'.&Tgtm+DBN-'/                 dovecot.index.cache
'.&UkqWZG4IMH8wojCkMMYw4A-'/   dovecot.index.log
'.&j,dg0TDhMPww6w-'/           dovecot.list.index.log
'.&kAFP4W4IMH8wojCkMMYw4A-'/   dovecot.mailbox.log
 ../                           new/
 cur/                          subscriptions
 dovecot-uidlist               tmp/
 dovecot-uidvalidity
#

この修正UTF-7が何を表しているかというのは、doveadmコマンドに-7,-8オプションを付与することで確認できる

# doveadm mailbox list -u testuser3 -7
&j,dg0TDhMPww6w-
&Tgtm+DBN-
&UkqWZG4IMH8wojCkMMYw4A-
&kAFP4W4IMH8wojCkMMYw4A-
INBOX
# doveadm mailbox list -u testuser3 -8
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
#

それぞれのメールボックスがどう変換されるのかを具体的に確認するのであれば、下記の様に「doveadm mailbox mutf7 -7 “文字列”」「doveadm mailbox mutf7 -8 “文字列”」と実行する

# doveadm mailbox mutf7 -7 "&j,dg0TDhMPww6w-"
迷惑メール
# doveadm mailbox mutf7 -8 "迷惑メール"
&j,dg0TDhMPww6w-
#

というわけで、Outlookで最初にIMAPメールを取りに行くと日本語でメールフォルダを作成する、ということがわかった。

Outlook形式メールボックスをThunderbirdメールで使う方法

同じユーザアカウントをThunderbirdメールで取得してみると、下記の様に表示される

じゃあ、下書き/削除済みアイテム/送信済みアイテムがOutlookと相互同期がとれているのかというと、そうはなっていなかった。

Thunderbirdの[アカウント設定]-[送信控えと特別なフォルダー]を見てみると、下記に様に、送信済みは「ローカルフォルダー」、下書きも「ローカルフォルダー」となっている。

これをどちらも各ユーザを指定する

かと思ったのですが、上記を設定しても、実際にメール送信や下書き保存してから設定を確認すると「ローカルフォルダー」に戻ります。

ただしい設定は「その他のフォルダーを指定する」を選んで、手動でフォルダを指定することでした

これで解決かと思ったのですが、「ゴミ箱」と「迷惑メール」についての設定がありません。

ゴミ箱は[サーバー設定]-[サーバー設定]にある「メッセージを削除する時」でゴミ箱を指定

迷惑メールは[迷惑メール]-[移動先と保存期間]で設定します。

で・・・ここまでの設定を行った段階でdoveadmコマンドでメールボックスを確認してみたところ、設定中にThunderbirdが「Junk」と「Trash」を別に作ってしまったようです。

# doveadm mailbox list -u testuser3
Junk
Trash
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
#

Thunderbirdメール上のメールボックス表示も「迷惑メール」が2種類、「ゴミ箱」と「削除済みアイテム」が両方ある、という状態に

Outlook側も「ゴミ箱」と「削除済みアイテム」が両方ある、という状態

これの解消についてはThunderbirdであればアカウント名の右クリックメニューから「購読」

表示される一覧の「Junk」と「Trash」のチェックを外します

下記の様に表示されます。

IMAPの購読設定はOutlook側で行うこともできます。受信トレイの右クリックメニューから「IMAPフォルダ」を選び、[クエリ]をクリックすると、下記の様にフォルダが表示されます。

「Junk」と「Trash」をそれぞれ「購読取り消し」を選んで適用します

Outlook側の表示も下記の様になります。(フォルダが残ったままの場合は一度Outlookを起動し直す)

日本語版Outlookと英語版Outlookは共存できるのか?

Outlookで自動的に作成されるのは日本語名のフォルダになっている。

じゃあ、英語環境ではどうなのか?と英語版Outlook環境を作成して、日本語版Outlook/Thunderbirdでアクセス済みのアカウントを設定してみた。

英語名のフォルダが別に作成されてしまうという事態に

# doveadm mailbox list -u testuser3
Drafts
Sent Items
Junk
Trash
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
#

英語Outlookでメール送信/下書きをすると、英語名フォルダに保存され、日本語環境のモノと同期がとれず、それぞれ別に保存されていることを確認

日本語Outlookでフォルダを確認すると下記の状態

OutlookのIMAPフォルダーでの購読状況は下記の様にどちらも共通(INBOX/受信ボックスはどちらも共通)

で・・・Thunderbirdメールの場合、とてもややこしい状態になっています

じゃあ、日本語Outlookと英語Outlookでメールボックス名を共通化することができるのか?

下書きの保存については「Change where sent email messages are saved」に記載があった

[ファイル]-[オプション]の「メール」にある「メッセージの保存」で下書きの保存場所を設定できる・・・のかと思ったら

選択できるものが、それぞれ英語/日本語でOutlookが作成したものだけとなっており、それ以外の場所が設定できないようだ。

Thunderbirdログイン後に日本語Outlookからアクセス

初回ログインはThunderbirdから行って、次に日本語Outlookからアクセスした場合の状態について確認

まずはサーバ上の初期状態を確認

# doveadm mailbox list -u testuser2
INBOX
# ls -aF testuser2/Maildir/
./  ../  cur/  dovecot.list.index.log  new/  tmp/
#

Thunderbirdに設定を入れた直後は「受信トレイ」と「ゴミ箱」のみ

# doveadm mailbox list -u testuser2
Trash
INBOX
# ls -aF testuser2/Maildir/
./       dovecot-keywords              dovecot.index.cache     new/
../      dovecot-uidlist               dovecot.index.log       subscriptions
.Trash/  dovecot-uidvalidity           dovecot.list.index.log  tmp/
cur/     dovecot-uidvalidity.68ef30a8  dovecot.mailbox.log
#

このときのThunderbird設定を確認すると[サーバー設定]-[サーバ設定]の「メッセージを削除する時」はIMAPのフォルダーになっている

それに対して[送信控えと特別なフォルダー]は、ローカルフォルダーになっている。

これを下記の設定にしても、しばらくするとローカルフォルダ設定に戻る。

動作を確認すると、ゴミ箱については、確かにTrashフォルダにメールが移動されていることを確認できた。

この状態で、OutlookでIMAP設定を行うと下記の様になった。

# doveadm mailbox list -u testuser2
迷惑メール
下書き
送信済みアイテム
Trash
INBOX
# ls -aF testuser2/Maildir/
 ./                            dovecot-uidvalidity
'.&Tgtm+DBN-'/                 dovecot-uidvalidity.68ef30ab
'.&j,dg0TDhMPww6w-'/           dovecot.index.cache
'.&kAFP4W4IMH8wojCkMMYw4A-'/   dovecot.index.log
 ../                           dovecot.list.index.log
 .Trash/                       dovecot.mailbox.log
 cur/                          new/
 dovecot-keywords              subscriptions
 dovecot-uidlist               tmp/
#

Thunderbirdで作成されたUI上は「ごみ箱」となっていた「Trash」フォルダは、Outlook側では「Trash」と表示され、Outlook側でメールを削除すると「Trash」フォルダにメールが移動する、ということが確認できた。

つまり、「受信トレイ」と「ゴミ箱」については、ThunderbirdとOutlookとで共通利用が可能なようだ

Outlook側で作成したフォルダが追加されたあとのThunderbird側は下記の表示となった。

このときに、Outlook側と動作を揃えるためにアカウント設定では以下の様に「その他のフォルダーを指定する」の方を選んで設定する。

下記の様にフォルダーに色がついたりする

英語版Outlookで初回ログインした場合

英語版Outlookで初回ログインした場合

# doveadm mailbox list -u testuser4
Junk Email
Drafts
Deleted Items
Sent Items
INBOX
# ls -aF testuser4/Maildir/
 ./                 cur/                           dovecot.list.index.log
 ../                dovecot-uidlist                dovecot.mailbox.log
'.Deleted Items'/   dovecot-uidvalidity            new/
 .Drafts/           dovecot-uidvalidity.68ef371e   subscriptions
'.Junk Email'/      dovecot.index.cache            tmp/
'.Sent Items'/      dovecot.index.log
#

この状態ではThunderbirdメールから見ると以下の状態となっていた

# doveadm mailbox list -u testuser4
Trash
Junk Email
Drafts
Deleted Items
Sent Items
INBOX
#

このとき、thunderbirdの設定は下記となっており、下書きについては、自動的に「その他のフォルダー」の方で設定されている。

しかし、Thunderbirdでメールの送信と下書き保存を行ってみると送信済みは

この状態では、英語outlookとThunderbirdではゴミ箱と送信済みの同期がとれていない状態となっていた。

英語版Outlook「Deleted Items」とThunderbird「Trash」がIMAP上の別フォルダ。
英語版Outlook「Sent Items」はIMAP上だが、Thunderbirdの「送信済みトレイ/送信済みアイテム」はローカル

続いて日本語Outlookで設定をすると下記となり、この場合はフォルダ名が英語表示ではあるものの内容は英語版Outlookと同期がとれている。

dovecotの設定調整で共有化できるのか?

ここまでのところで判明した問題点

・OutlookはIMAPアクセスした時に規定のフォルダがないと新規作成する
・英語版Outlookで作ったフォルダは日本語版Outlookでも共通で使えるが、逆は別物となる
・ThunderbirdでIMAPアクセスした時は、ゴミ箱(Trash)しか作成しない

dovecotの設定で /etc/dovecot/conf.d/15-mailboxes.conf内で下記ような設定がある

namespace inbox {
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox Trash {
    special_use = \Trash
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }

special_use というのは RFC6154「IMAP LIST Extension for Special-Use Mailboxes」で定義されている特殊な役割をもつものとなっていて「\Drafts(下書き)」「\Junk(迷惑メール)」「\Trash(ゴミ箱)」「\Sent(送信済みアイテム)」の設定となっている。

すでに行われている設定をみると、「Sent」と「Sent Messages」は同じ「\Sent」を指す、という設定になっているように見える

この設定をこれまでに出てきたものに対して適用することで解決できるのでは?ということで並べると・・・

\Drafts 候補
下書き
Drafts

\Junk 候補
迷惑メール
Junk
Junk Email

\Trash 候補
削除済みアイテム
Trash
Deleted Items

\Sent 候補
送信済みアイテム
Sent Items

これを /etc/dovecot/conf.d/15-mailboxes.conf に設定してdovecot再起動

##
## Mailbox definitions
##

# Each mailbox is specified in a separate mailbox section. The section name
# specifies the mailbox name. If it has spaces, you can put the name
# "in quotes". These sections can contain the following mailbox settings:
#
# auto:
#   Indicates whether the mailbox with this name is automatically created
#   implicitly when it is first accessed. The user can also be automatically
#   subscribed to the mailbox after creation. The following values are
#   defined for this setting:
#
#     no        - Never created automatically.
#     create    - Automatically created, but no automatic subscription.
#     subscribe - Automatically created and subscribed.
#
# special_use:
#   A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the
#   mailbox. There are no validity checks, so you could specify anything
#   you want in here, but it's not a good idea to use flags other than the
#   standard ones specified in the RFC:
#
#     \All       - This (virtual) mailbox presents all messages in the
#                  user's message store.
#     \Archive   - This mailbox is used to archive messages.
#     \Drafts    - This mailbox is used to hold draft messages.
#     \Flagged   - This (virtual) mailbox presents all messages in the
#                  user's message store marked with the IMAP \Flagged flag.
#     \Important - This (virtual) mailbox presents all messages in the
#                  user's message store deemed important to user.
#     \Junk      - This mailbox is where messages deemed to be junk mail
#                  are held.
#     \Sent      - This mailbox is used to hold copies of messages that
#                  have been sent.
#     \Trash     - This mailbox is used to hold messages that have been
#                  deleted.
#
# comment:
#   Defines a default comment or note associated with the mailbox. This
#   value is accessible through the IMAP METADATA mailbox entries
#   "/shared/comment" and "/private/comment". Users with sufficient
#   privileges can override the default value for entries with a custom
#   value.

# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {
  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
  }
  mailbox "下書き" {
    special_use = \Drafts
  }
  mailbox Junk {
    special_use = \Junk
  }
  mailbox "迷惑メール" {
    special_use = \Junk
  }
  mailbox "Junk Email" {
    special_use = \Junk
  }
  mailbox Trash {
    special_use = \Trash
  }
  mailbox "削除済みアイテム" {
    special_use = \Trash
  }
  mailbox "Deleted Items" {
    special_use = \Trash
  }

  # For \Sent mailboxes there are two widely used names. We'll mark both of
  # them as \Sent. User typically deletes one of them if duplicates are created.
  mailbox Sent {
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
  mailbox "送信済みアイテム" {
    special_use = \Sent
  }
  mailbox "Sent Items" {
    special_use = \Sent
  }

  # If you have a virtual "All messages" mailbox:
  #mailbox virtual/All {
  #  special_use = \All
  #  comment = All my messages
  #}

  # If you have a virtual "Flagged" mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged
  #  comment = All my flagged messages
  #}

  # If you have a virtual "Important" mailbox:
  #mailbox virtual/Important {
  #  special_use = \Important
  #  comment = All my important messages
  #}
}

初期状態

# doveadm mailbox list -u testuser5
INBOX
# ls -aF testuser5/Maildir/
./  ../  cur/  new/  tmp/
#

日本語Outlookで最初に作成した場合

日本語Outlookでログイン

# doveadm mailbox list -u testuser5
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
# ls -aF testuser5/Maildir/
 ./                            dovecot-uidvalidity.68ef4b2b
'.&Tgtm+DBN-'/                 dovecot.index.cache
'.&UkqWZG4IMH8wojCkMMYw4A-'/   dovecot.index.log
'.&j,dg0TDhMPww6w-'/           dovecot.list.index.log
'.&kAFP4W4IMH8wojCkMMYw4A-'/   dovecot.mailbox.log
 ../                           new/
 cur/                          subscriptions
 dovecot-uidlist               tmp/
 dovecot-uidvalidity
#

続いて英語Outlookでログインした場合

# doveadm mailbox list -u testuser5
迷惑メール
下書き
削除済みアイテム
送信済みアイテム
INBOX
# ls -aF testuser5/Maildir/
 ./                            dovecot-uidvalidity.68ef4b2b
'.&Tgtm+DBN-'/                 dovecot.index.cache
'.&UkqWZG4IMH8wojCkMMYw4A-'/   dovecot.index.log
'.&j,dg0TDhMPww6w-'/           dovecot.list.index.log
'.&kAFP4W4IMH8wojCkMMYw4A-'/   dovecot.mailbox.log
 ../                           new/
 cur/                          subscriptions
 dovecot-uidlist               tmp/
 dovecot-uidvalidity
#

英語版Outlookであっても、日本語文字列でのフォルダが見えており、ゴミ箱/下書き/送信済みアイテムの内容が日本語版Outlookと同期がとれていることを確認できた。

Thunderbirdで設定すると以下の状態で見れる

Thunderbirdの[サーバー設定]の「メールを削除するとき」の初期値は下記となっていて、ちゃんと選択されてるのか?という感じでしたが、メールを削除すると、IMAP上のTrashに移動してることを確認しました

[送信控えと特別なフォルダー]は下記

日本語版Outlook、英語版Outlook、Thunderbirdメールのそれぞれで同期がとれたように見える。

英語Outlookで最初に作成した場合

英語Outlookで最初にアクセスした場合に作成されるもの

# doveadm mailbox list -u testuser5
Junk Email
Drafts
Deleted Items
Sent Items
INBOX
# ls -aF testuser5/Maildir/
 ./                 cur/                           dovecot.list.index.log
 ../                dovecot-uidlist                dovecot.mailbox.log
'.Deleted Items'/   dovecot-uidvalidity            new/
 .Drafts/           dovecot-uidvalidity.68ef4f73   subscriptions
'.Junk Email'/      dovecot.index.cache            tmp/
'.Sent Items'/      dovecot.index.log
#

続いて日本語Outlookでログイン

実際に作成されているメールボックスは英語のまま

# doveadm mailbox list -u testuser5
Junk Email
Drafts
Deleted Items
Sent Items
INBOX
# ls -aF testuser5/Maildir/
 ./                 cur/                           dovecot.list.index.log
 ../                dovecot-uidlist                dovecot.mailbox.log
'.Deleted Items'/   dovecot-uidvalidity            new/
 .Drafts/           dovecot-uidvalidity.68ef4f73   subscriptions
'.Junk Email'/      dovecot.index.cache            tmp/
'.Sent Items'/      dovecot.index.log
#

最後にThunderbirdは下記状態で、特に問題は無い状態となっていた。

日本語Outlookで作成された「削除済みアイテム」の選択表示がおかしかったが、英語文字列の場合は特に問題ないようだ。

Thunderbirdで最初にアクセスした場合

Thuderbirdで最初にアクセスした場合は下記の様になった

# doveadm mailbox list -u testuser5
Trash
INBOX
# ls -aF testuser5/Maildir/
./       dovecot-keywords              dovecot.index.cache     new/
../      dovecot-uidlist               dovecot.index.log       subscriptions
.Trash/  dovecot-uidvalidity           dovecot.list.index.log  tmp/
cur/     dovecot-uidvalidity.68ef52a1  dovecot.mailbox.log
#

このとき、設定は、ゴミ箱はIMAP上を使用するが、「送信済みアイテム」と「下書き」についてはローカルに保存する設定になっていた。

この状態で、日本語Outlookからアクセスすると、日本語名で作成される

# doveadm mailbox list -u testuser5
迷惑メール
下書き
送信済みアイテム
Trash
# ls -aF testuser5/Maildir/
 ./                            dovecot-uidvalidity
'.&Tgtm+DBN-'/                 dovecot-uidvalidity.68ef52a4
'.&j,dg0TDhMPww6w-'/           dovecot.index.cache
'.&kAFP4W4IMH8wojCkMMYw4A-'/   dovecot.index.log
 ../                           dovecot.list.index.log
 .Trash/                       dovecot.mailbox.log
 cur/                          new/
 dovecot-keywords              subscriptions
 dovecot-uidlist               tmp/
#

改めてthunderbird側で確認すると、下記の状態に変更されているが下書きと送信済みアイテムの同期が出来ていない

設定を確認すると、アイコンの絵がそれっぽく表示されているだけで、設定自体は手動で変更する必要があった。

これを下記に変更したところ同期が行われるようになった

設定追加

RFC6154を読むと、special useとして定義さえている文字列には「\Archive」「\Flagged」とゴミ箱/迷惑メールを含めて全メールを表示する「\All」がある模様

「\Archive」は、Outlookの各メールの右クリックメニューにある「Archive/アーカイブ」で保存される先として使用される。

# doveadm mailbox list -u testuser4
Archive
Junk
Trash
Junk Email
Drafts
Deleted Items
Sent Items
INBOX
# ls -aF testuser4/Maildir/
 ./                 .Trash/                        dovecot.list.index
 ../                cur/                           dovecot.list.index.log
 .Archive/          dovecot-keywords               dovecot.list.index.log.2
'.Deleted Items'/   dovecot-uidlist                dovecot.mailbox.log
 .Drafts/           dovecot-uidvalidity            new/
 .Junk/             dovecot-uidvalidity.68ef3721   subscriptions
'.Junk Email'/      dovecot.index.cache            tmp/
'.Sent Items'/      dovecot.index.log
#

上記のように「Archive」フォルダが作成される。このフォルダについては日本語Outlook環境でも英語表記Archiveでアーカイブ動作をした。

次に、最初に日本語Outlook環境で「アーカイブ」した場合は、日本語で作成される

# doveadm mailbox list -u testuser5
アーカイブ
迷惑メール
下書き
送信済みアイテム
Trash
INBOX
#

英語Outlookでアーカイブを行おうとすると、日本語アーカイブフォルダは認めてくれていない

/etc/dovecot/conf.d/15-mailboxes.confに下記設定を追加してdovecot再起動

  mailbox Archive {
    special_use = \Archive
  }
  mailbox "アーカイブ" {
    special_use = \Archive
  }

これで問題無くなるかと思ったのですが、引き続き”Archive”を新規作成するダイアログが表示される状態に・・・

アーカイブの動作が謎だ・・・

パソコン変更時のThunderbirdの移行手法メモ

Thuderbirdでメールを受信している環境で、パソコンを新しくした。

その際に、メールアカウントが複数あるのでパスワードの再入力したくないなぁ、と思ってたのですが、ThunderbirdのGUI操作でやるとパスワード入力が発生したのでメモとして残しておく

移行元パソコンでの操作として、Thuderbirdの[ツール]-[設定とデータのエクスポート]を開く

そうすると下記のような画面が開く

「プロファイルフォルダーを開く」を選択するとエクスプローラーで Thuderbirdのメールデータが入っている場所が開く

上記では C:\Users\ユーザ名\AppData\Roaming\Thunderbird\Profiles\s0k7246v.default というフォルダになっているが、最後の部分は環境によって異なる。(なお、どのユーザでも共通して使えるやりかたとしては、エクスプローラのアドレスのところに「%AppData%\Thunderbird\Profiles」と入力するというのがある。)

で、この表示されたプロファイルフォルダーのところだけを新しいパソコンにもっていって、[ツール]-[設定とデータのインポート]から読み込ませたところ、パスワードを聞いてきました。

で・・・エクスプローラで開いたパスを C:\Users\ユーザ名\AppData\Roaming\Thunderbird (一般名「%AppData%\Thunderbird」)に変更すると、下記のようにいろいろ設定ファイルがあることがわかる。

profiles.ini とinstalls.ini の中身を確認するとどちらも相対的なパス指定となっているので、新旧パソコンでユーザ名が異なっていても問題なさそう。

[Install8216C80C92C4E828]
Default=Profiles/s0k7246v.default

[InstallD78BF5DD33499EC2]
Default=Profiles/s0k7246v.default

[Profile0]
Name=default
IsRelative=1
Path=Profiles/s0k7246v.default
Default=1

[General]
StartWithLastProfile=1
Version=2

ということで、「%AppData%\Thunderbird」を丸ごとコピーすれば、メールデータ、メールサーバ設定情報+パスワードもそのまま移行できることを確認しました。

dovecot / postfix と Active Directory連携時の動作調査手法

dovecot / postfix と Active Directoryを連携させようと設定してみたところ、最初はうまく動かなかった。

この動かない原因をどうやって調べていくか、というのを解説してるものがなく、非常に難儀したのでメモ書きとして残す

dovecot, postfixの現在の設定を確認

RHEL9の場合、 /etc/dovecot および /etc/postfix に設定ファイル群があるが、コメントやサブディレクトリにあるファイルとの結合により、最終的な設定が何になっているのかわかりにくい

「doveconf」および「postconf」を実行することで最終的な設定を確認することができる

また、デフォルト値と異なる部分は何かを「doveconf -n」「postconf -n」を実行することで確認できる。

なお、doveconfの場合、ssh_keyなど一部のパラメータについては「doveconf -P」と-Pオプションをつけないと実際の値が表示されない

dovecotのログ出力を増やす

ログ出力を増やすための設定がいろいろあった(Dovecot Logging)ため、 /etc/dovecot/conf.d/99-debug.conf と1つのファイルにまとめて必要ない場合は /etc/dovecot/conf.d/99-debug._conf と.conf という名前じゃなくすることで無効化できるようにした

[root@mail dovecot]# cat /etc/dovecot/conf.d/99-debug.conf
auth_debug=yes
auth_debug_passwords=yes
auth_verbose=yes
auth_verbose_passwords=yes
verbose_proctitle=yes
verbose_ssl=yes

[root@mail dovecot]#

設定後は「systemctl restart dovecot」で設定を有効にする

なお「doveadm log find」を実行するとdovecotのログがどのファイルに出力されているかを確認することができる

[root@mail dovecot]# doveadm log find
Looking for log files from /var/log
Debug: /var/log/maillog
Info: /var/log/maillog
Warning: /var/log/maillog
Error: /var/log/maillog
Fatal: /var/log/maillog
[root@mail dovecot]#

LDAP検索のログを増やす

dovecotの場合は dovecot本体への auth_verbose=yes 設定だけでLDAPでどういったqueryを投げているかも確認できる

ただ、もっと詳細を確認したい、という場合 /etc/dovecot/dovecot-ldap.conf.ext などのLDAP接続情報を書いたファイルに「debug_level」を追加することでログを増やすこともできる。

dovecot Common LDAP Settings for both auth and sieve
iredmail Turn on debug mode in Dovecot

dovecot標準値は「debug_level=0」。ログを増やす場合は「debug_level=1」、最大量に増やす場合は「debug_level=-1」とする

postfixの場合も同様に LDAP接続情報を書いたファイル /etc/postfix/ldap-mailbox.cf などに「debuglevel」を追加することでログを増やすことができる。

postfix ldap_table – Postfix LDAP client configuration

postfix標準値は「debuglevel=0」。増やす場合は「debuglevel=1」から最大量は「debuglevel=10」とする

postfixのログ出力を増やす

Postfix Debugging Howto に記載があるが正直めんどい

/etc/postfix/master.cf の smtpd起動に関して「-v」オプションか「-D」オプションをつける、という形となる。

とはいえ、postfix/dovecotを組み合わせた場合、ActiveDirectory/LDAP側の処理をdovecot側で行うということもあるので、まずはdovecot側の動作がちゃんとするのを先に確認したほうがよい。

dovecotでの認証確認

dovecotで認証動作を確認する場合、まずは「doveadm auth login ユーザ名」を実行する

[root@mail ~]# doveadm auth login testuser1@adsample.local
Password: <パスワード入力>
passdb: testuser1@adsample.local auth succeeded
extra fields:
  user=testuser1@adsample.local
  uid=1000
  gid=1000
userdb extra fields:
  testuser1@adsample.local
  uid=1000
  gid=1000
  auth_mech=PLAIN
[root@mail ~]#

なお、「doveadm auth login testuser1@adsample.local パスワード」とパスワードをつけて実行すると入力しないで済むので検証時は便利(ログに残るので一時なパスワードにすること)

ただし、このdoveadm auth loginコマンドは模擬的に確認しているだけで、実際にログイン処理は行っていないようで、テストしたユーザのディレクトリがない場合でもディレクトリが作成されない。(ちゃんとログインした場合は自動的に作成される)

ldapsearchコマンドを使った検証

doveadm auth loginコマンドでうまく認証が実行できない場合、 ldapsearchコマンドを使って原因を調査していったりする。

その場合、 /etc/dovecot/conf.d/99-debug.conf の設定を有効にしてから行う。

期待通りに動作していない場合、ログにある下記のような「ldap」「base=~」「filter=~」という記述に注目する

May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): Server accepted connection (fd=14)
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): Sending version handshake
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: Handling LIST request
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap(): Performing userdb lookup
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap: iterate: base=cn=Users,dc=adsample,dc=local scope=subtree filter=(objectClass=posixAccount) fields=uid
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap(): Finished userdb lookup
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: Finished

上記の場合注目するのは以下の部分

base=cn=Users,dc=adsample,dc=local scope=subtree filter=(objectClass=posixAccount) fields=uid

これをldapsearchコマンドに与える

-bオプションの後ろにbase=の後ろにある「cn=Users,dc=adsample,dc=local」
-sオプションの後ろにscope=の「subtree」
そしてfilterの「objectClass=posixAccount」

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree objectClass=posixAccount

この出力結果を確認し、fields=で指定した「uid」という項目があるかを確認します

なければfilterで指定した条件が不適切、ということとなる

fieldsで適切かなぁ、というものが出るまでfilterの条件式の調整と、fieldsで選ぶ項目の調整を行う

各ユーザで取得できるLDAPの情報が何かを調べる場合は下記のようにuserPrincipalName、もしくはsAMAccountName で検索して確認する

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree userPrincipalName=testuser2@adsample.local

ldapsearchが1000件表示ぐらいで止まってしまう

openldapでの仕様で1000件で出力を止めるため。

「-E pr=1000/noprompt」オプションを付けると無視できる

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree sAMAccountName -E pr=1000/noprompt

なお-Eオプションの意味は下記

   -E [!]ext[=extparam]

          Specify general extensions with -e and search extensions with -E.  ´!´ indicates
          criticality.

          General extensions:
            [!]assert=&lt;filter>    (an RFC 4515 Filter)
            !authzid=&lt;authzid>    ("dn:&lt;dn>" or "u:&lt;user>")
            [!]bauthzid           (RFC 3829 authzid control)
            [!]chaining[=&lt;resolve>[/&lt;cont>]]
            [!]manageDSAit
            [!]noop
            ppolicy
            [!]postread[=&lt;attrs>] (a comma-separated attribute list)
            [!]preread[=&lt;attrs>]  (a comma-separated attribute list)
            [!]relax
            sessiontracking[=&lt;username>]
            abandon,cancel,ignore (SIGINT sends abandon/cancel,
            or ignores response; if critical, doesn't wait for SIGINT.
            not really controls)

          Search extensions:
            !dontUseCopy
            [!]domainScope                       (domain scope)
            [!]mv=&lt;filter>                       (matched values filter)
            [!]pr=&lt;size>[/prompt|noprompt]       (paged results/prompt)
            [!]sss=[-]&lt;attr[:OID]>[/[-]&lt;attr[:OID]>...]  (server side sorting)
            [!]subentries[=true|false]           (subentries)
            [!]sync=ro[/&lt;cookie>]                (LDAP Sync refreshOnly)
                    rp[/&lt;cookie>][/&lt;slimit>]     (LDAP Sync refreshAndPersist)
            [!]vlv=&lt;before>/&lt;after>(/&lt;offset>/&lt;count>|:&lt;value>)  (virtual list view)
            [!]deref=derefAttr:attr[,attr[...]][;derefAttr:attr[,attr[...]]]
            [!]&lt;oid>[=:&lt;value>|::&lt;b64value>]

ldapsearchで特定に値があるエントリのみ出力

LDAPでmailアトリビュートが設定されているアカウント名とメールアドレスだけを出力させたい場合

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree mail=* sAMAccountName mail

-s substreeの後の語句がfilterで検索条件。「mail=*」はmailに値がなんでもいいのであれば良い、ということ

続く「sAMAccountName mail」が出力させたいattiribute名。いくつでも列挙可

mail=*の部分の条件を複雑化させることもできる

doveadmでメールボックスの状態確認

dovecotで認識しているメールボックスの状態を確認する「doveadm mailbox status」コマンド

全ユーザについてとりあえず全ステータスをとる場合はfieldをallにすればいい、というので「doveadm mailbox status -A all ‘*’」を実行してみる

[root@mail ~]# doveadm mailbox status -A all '*'
testuser1@adsample.local Trash messages=0 recent=0 uidnext=2 uidvalidity=1745978754 unseen=0 highestmodseq=5 vsize=0 guid=40b0b82833051c68570600003a0de1d0 firstsaved=never
testuser1@adsample.local INBOX messages=16 recent=0 uidnext=18 uidvalidity=1745978753 unseen=0 highestmodseq=22 vsize=613873 guid=3fa5f40281851168ee0500003a0de1d0 firstsaved=1746666817
testuser2@adsample.local Drafts messages=4 recent=0 uidnext=5 uidvalidity=1745978410 unseen=0 highestmodseq=9 vsize=2313 guid=fe4beb08b4d91268980500003a0de1d0 firstsaved=1746066862
testuser2@adsample.local Sent messages=28 recent=0 uidnext=35 uidvalidity=1745978409 unseen=0 highestmodseq=37 vsize=10545 guid=a28a5e0b7c201268cb0600003a0de1d0 firstsaved=1746018428
testuser2@adsample.local Trash messages=0 recent=0 uidnext=12 uidvalidity=1745978408 unseen=0 highestmodseq=11 vsize=0 guid=ab2c081a361e1268260600003a0de1d0 firstsaved=never
testuser2@adsample.local INBOX messages=9 recent=0 uidnext=15 uidvalidity=1745978407 unseen=0 highestmodseq=33 vsize=10810 guid=7e51333727841168d30500003a0de1d0 firstsaved=1746084330
testuser3@adsample.local INBOX messages=2 recent=2 uidnext=3 uidvalidity=1746166331 unseen=2 highestmodseq=3 vsize=1330 guid=7d83dc163b621468950800003a0de1d0 firstsaved=1746166331
[root@mail ~]#

ん?? vsizeは表示されていない?…マニュアルを再度確認すると -tオプションで messages, recent, unseen, vsizeだけを表示できるとのこと

[root@mail ~]# doveadm mailbox status -A all '*' -t
testuser1@adsample.local messages=16 recent=0 unseen=0 vsize=613873
testuser2@adsample.local messages=41 recent=0 unseen=0 vsize=23668
testuser3@adsample.local messages=2 recent=2 unseen=2 vsize=1330
testuser4@adsample.local messages=0 recent=0 unseen=0 vsize=0
vmail@adsample.local messages=0 recent=0 unseen=0 vsize=0
[root@mail ~]#

messages: メール総数
recent: Recentフラグがついてるメール数(新着メール=まだメールソフトに取り込んでない)
unseen: 未読メール数
vsize: メールの総容量(バイト)

dovecotの起動プロセス数確認

メールソフトからpop3/imapで接続すると、dovecot/pop3やdovecot/imapプロセスが起動する

例えば雑にpsコマンドの結果をとってみるとこんな感じ

[root@mail ~]# ps -ef|grep imap
vmail       2096    2088  0 17:36 ?        00:00:00 dovecot/imap [testuser2@adsample.local 192.168.122.1 IDLE]
vmail       2097    2088  0 17:36 ?        00:00:00 dovecot/imap [testuser2@adsample.local 192.168.122.1]
dovenull    2099    2088  0 17:37 ?        00:00:00 dovecot/imap-login [192.168.122.1 TLS proxy]
vmail       2101    2088  0 17:37 ?        00:00:00 dovecot/imap [testuser1@adsample.local 192.168.122.1 IDLE]
root        2118    1441  0 17:45 pts/0    00:00:00 grep --color=auto imap
[root@mail ~]#

これをdovecot側のコマンドで状態取得する場合は「doveadm service status サービス名」で取得する

[root@mail ~]# doveadm service status imap
name: imap
process_count: 3
process_avail: 0
process_limit: 1024
client_limit: 1
throttle_secs: 0
exit_failure_last: 0
exit_failures_in_sec: 0
last_drop_warning: 0
listen_pending: n
listening: y
doveadm_stop: n
process_total: 4
[root@mail ~]# doveadm service status imap-login
name: imap-login
process_count: 1
process_avail: 0
process_limit: 100
client_limit: 1
throttle_secs: 0
exit_failure_last: 0
exit_failures_in_sec: 0
last_drop_warning: 0
listen_pending: n
listening: y
doveadm_stop: n
process_total: 4
[root@mail ~]#

IMAPの場合、メールクライアントの実装によっては接続が維持されるのでprocess_limitの値に抵触しないかを注意する必要がある

Service Limits

Then client_limit needs to be set high enough to be able to serve all the needed connections (max connections=process_limit * client_limit).

acvite directory連携のdovecotでdoveadm quota get -Aが動かない

dovecot 2.2.19以降で登場した各ユーザのメールフォルダ内にあるindexファイルを使ったquotaを設定しようとした際に発見した出来事です。

doveadm quota get -Aの動作

doveadm quotaのマニュアルを見ると「doveadm quota get -A」を実行すると全ユーザの結果が表示されそうな気がするので実行してみたがされない

[root@mail dovecot]# doveadm quota get -A
Username Quota name Type Value Limit                                                   %
[root@mail dovecot]#

dovecotにdebug系ログ出力を有効にした状態での /var/log/maillog には下記のログ

May  2 11:18:59 mail dovecot[959]: auth: Debug: Loading modules from directory: /usr/lib64/dovecot/auth
May  2 11:18:59 mail dovecot[959]: auth: Debug: Module loaded: /usr/lib64/dovecot/auth/lib20_auth_var_expand_crypt.so
May  2 11:18:59 mail dovecot[959]: auth: Debug: Module loaded: /usr/lib64/dovecot/auth/libdriver_sqlite.so
May  2 11:18:59 mail dovecot[959]: auth: Debug: Loading modules from directory: /usr/lib64/dovecot/auth
May  2 11:18:59 mail dovecot[959]: auth: Debug: Module loaded: /usr/lib64/dovecot/auth/libauthdb_ldap.so
May  2 11:18:59 mail dovecot[959]: auth: Debug: Read auth token secret from /run/dovecot/auth-token-secret.dat
May  2 11:18:59 mail dovecot[959]: auth: Debug: ldap(/etc/dovecot/dovecot-ldap.conf.ext): LDAP initialization took 22 msecs
May  2 11:18:59 mail dovecot[959]: auth: Debug: master in: LIST#0111
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: Loading modules from directory: /usr/lib64/dovecot/auth
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: Module loaded: /usr/lib64/dovecot/auth/lib20_auth_var_expand_crypt.so
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: Module loaded: /usr/lib64/dovecot/auth/libdriver_sqlite.so
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: Loading modules from directory: /usr/lib64/dovecot/auth
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: Module loaded: /usr/lib64/dovecot/auth/libauthdb_ldap.so
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: ldap(/etc/dovecot/dovecot-ldap.conf.ext): LDAP initialization took 14 msecs
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): Server accepted connection (fd=14)
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): Sending version handshake
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: Handling LIST request
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap(): Performing userdb lookup
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap: iterate: base=cn=Users,dc=adsample,dc=local scope=subtree filter=(objectClass=posixAccount) fields=uid
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: ldap(): Finished userdb lookup
May  2 11:18:59 mail dovecot[959]: auth-worker(1542): Debug: conn unix:auth-worker (pid=1541,uid=97): auth-worker&lt;1>: Finished

「objectClass=posixAccount」でフィルターをかけているが、Active DirectoryベースのLDAPサーバ標準では posixAccountは存在していないため、フィルター文字列を変える必要がある、という話である

確認のためldapsearchコマンドで出力がないことを確認

[root@mail dovecot]# ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree objectClass=posixAccount
# extended LDIF
#
# LDAPv3
# base &lt;dc=adsample,dc=local> with scope subtree
# filter: objectClass=posixAccount
# requesting: ALL
#

# search reference
ref: ldaps://ForestDnsZones.adsample.local/DC=ForestDnsZones,DC=adsample,DC=lo
 cal

# search reference
ref: ldaps://DomainDnsZones.adsample.local/DC=DomainDnsZones,DC=adsample,DC=lo
 cal

# search reference
ref: ldaps://adsample.local/CN=Configuration,DC=adsample,DC=local

# search result
search: 2
result: 0 Success

# numResponses: 4
# numReferences: 3
[root@mail dovecot]#

どこの設定を変えればいいのか調べていくと userdb_ldap_iterate_fieldsuserdb_ldap_iterate_filter で行っているので /etc/dovecot/dovecot-ldap.conf.ext に iterate_filter と iterate_attrs の設定を行う、ということがわかる

うまいことユーザ一覧っぽいのを取得するにはどうすればいいかな、とldapsearchコマンドをこねくり回して「ldapsearch -x -H ldaps://192.168.122.10 -D “cn=vmail,cn=Users,dc=adsample,dc=local” -w “パスワード” -b “dc=adsample,dc=local” -s subtree objectClass=user userPrincipalName」とすればいいかな、というのがわかった。

この結果をもとに、/etc/dovecot/dovecot-ldap.conf.ext に以下を追加してみたところおおむね期待通りの動作となった

iterate_filter=objectClass=user
iterate_attrs=userPrincipalName=user

これは、”objectClass=user”に該当するオブジェクトを表示させたあと、 userPrincipalName の値を dovecot上の user として認識させる、という意味合いの設定となる。

doveadm quota get -Aの実行結果

[root@mail dovecot]# doveadm quota get -A
Username                 Quota name Type    Value Limit                                          %
testuser1@adsample.local User quota STORAGE     9 10240                                          0
testuser1@adsample.local User quota MESSAGE    13     -                                          0
testuser2@adsample.local User quota STORAGE    14 10240                                          0
testuser2@adsample.local User quota MESSAGE    31     -                                          0
testuser3@adsample.local User quota STORAGE     0 10240                                          0
testuser3@adsample.local User quota MESSAGE     0     -                                          0
testuser4@adsample.local User quota STORAGE     0 10240                                          0
testuser4@adsample.local User quota MESSAGE     0     -                                          0
vmail@adsample.local     User quota STORAGE     0 10240                                          0
vmail@adsample.local     User quota MESSAGE     0     -                                          0
[root@mail dovecot]#

/etc/dovecot/conf.d/90-quota.conf を編集し、容量制限を1MBに変更

<略>
plugin {
  # 10MB quota limit
  quota = count:User quota
  quota_rule = *:storage=1M

  # This is required - it uses "virtual sizes" rather than "physical sizes"
  # for quota counting:
  quota_vsizes = yes
}

この状態でメールを送って容量を増やして確認・・・

[root@mail dovecot]# doveadm quota get -A
Username                 Quota name Type    Value Limit                                          %
testuser1@adsample.local User quota STORAGE   895  1024                                         87
testuser1@adsample.local User quota MESSAGE    16     -                                          0
testuser2@adsample.local User quota STORAGE   907  1024                                         88
testuser2@adsample.local User quota MESSAGE    38     -                                          0
testuser3@adsample.local User quota STORAGE     0  1024                                          0
testuser3@adsample.local User quota MESSAGE     0     -                                          0
testuser4@adsample.local User quota STORAGE     0  1024                                          0
testuser4@adsample.local User quota MESSAGE     0     -                                          0
vmail@adsample.local     User quota STORAGE     0  1024                                          0
vmail@adsample.local     User quota MESSAGE     0     -                                          0
[root@mail dovecot]#

2025/08/21 追記

動作試験のため、Active DirectoryにPowerShellのNew-Aduserコマンドを使って6万アカウントを作成した。

for($I=0;$I -lt 60000; $I++){
    $count="{0:000000}" -f $I
    $username="h"+$count
    New-Aduser -emailaddress $username"@adsample.local" -SamAccountName $username -Name $username -DisplayName $username -GivenName $username -UserPrincipalName $username"@adsample.local"
}

そして、doveadm quota get -Aを実行したところ約1000件表示したところでエラー発生

# doveadm quota get -A|head -20
Username  Quota name Type    Value Limit                    %
h000000   User quota STORAGE     0  5120                    0
h000000   User quota MESSAGE     0     -                    0
h000001   User quota STORAGE     0  5120                    0
h000001   User quota MESSAGE     0     -                    0
h000002   User quota STORAGE     0  5120                    0
h000002   User quota MESSAGE     0     -                    0
<略>
h000999   User quota STORAGE     0  5120                    0
h000999   User quota MESSAGE     0     -                    0
doveadm(2465): Error: auth-master: userdb list: User listing returned failure
doveadm: Error: Failed to iterate through some users
#

この時、ログには以下が出力されていた

Aug 21 17:38:30 rhel9 dovecot[1135]: auth-worker(2463): Error: conn unix:auth-worker (pid=2462,uid=97): auth-worker<2>: ldap(): ldap_search(base=cn=Users,dc=adsample,dc=local filter=objectClass=user) failed: Size limit exceeded

これはopenldapの仕様で1000件までしか表示してくれないため、という制限だった。

dovecotのソースファイルを確認してみたけど、 ldap検索時のsizelimitについて解除できるような設定が見当たらなかった。

で、doveadmコマンドのqoutaについてdocを確認すると-Fオプションで確認したいユーザを列挙したファイルを与えて取得ができることがわかった

-F file
Execute the command for all the users in the file.  This is similar to the -A option, but instead of getting the list of users from the userdb, they are read from the given file.  The file contains one username per line.

ldapsearchコマンドによるユーザ名一覧作成についても1000件制限がかかるが、「-E pr=1000/noprompt」オプションを付けると解除されるため、全ユーザ一覧の取得ができる。

元の一覧作成で以下を使っていた場合

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree objectClass=user userPrincipalName

下記の様に実行すると userPrincipalName だけを取得できる

ldapsearch -x -H ldaps://192.168.122.10 -D "cn=vmail,cn=Users,dc=adsample,dc=local" -w "パスワード" -b "dc=adsample,dc=local" -s subtree objectClass=user userPrincipalName  -E "pr=1000/noprompt" |grep "userPrincipalName:" | awk '{ print $2 }'

これをファイルに保存して「doveadm quota get -F ファイル名」を実行することで対応可能となる。

で、これをスクリプト化したいわけですが、スクリプトに直接パスワードを書くのではなく、 /etc/dovecot/dovecot-ldap.conf.ext に書いたヤツを流用してくれるとうれしいわけです。

概ねこんな感じでしょうか?(注:これを使う場合、例えば「dn=」のあとにスペースがあるとエラーになります)

#/bin/bash
# dovecotのLDAP設定が書いてあるファイル
ldapconf=/etc/dovecot/dovecot-ldap.conf.ext

### 一時ファイル関連の処理
# 一時ファイルを作る
tmpfile=$(mktemp)
# 生成した一時ファイルを削除する
function rm_tmpfile {
  [[ -f "$tmpfile" ]] && rm -f "$tmpfile"
}
# 正常終了したとき
trap rm_tmpfile EXIT
# 異常終了したとき
trap 'trap - EXIT; rm_tmpfile; exit -1' INT PIPE TERM

### 実際の処理
# 設定ファイルから値を読み込み
tmpuris=`grep "^uris=" $ldapconf|awk -Fis= '{ print $2 }'`
tmpdn=`grep "^dn=" $ldapconf|awk -Fdn= '{ print $2 }'`
tmpdnpass=`grep "^dnpass=" $ldapconf|awk -Fss= '{ print $2 }'`
tmpbase=`grep "^base=" $ldapconf|awk -Fse= '{ print $2 }'`
tmpfilter=`grep "^iterate_filter=" $ldapconf|awk -Fer= '{ print $2 }'`

ldapsearch -x -H "$tmpuris" -D "$tmpdn" -w "$tmpdnpass" -b "$tmpbase" -s subtree $tmpfilter userPrincipalName  -E "pr=1000/noprompt" |grep "userPrincipalName:" | awk '{ print $2 }' > $tmpfile
doveadm quota get -F $tmpfile

一時ファイルを作成するあたりの処理は晴耕雨読Bashで一時ファイルを作る方法」のものを使用しました。