z-pushでIMAPメールをプッシュ通知する

IMAPに対応したメールサーバーで、iPhoneなどのスマートフォンなどに、プッシュ通知を行うツール「z-push」。Zimbraの一部として提供されていた機能がオープンソースとして提供されています。
2022/11/4にオープンソース版の終了が公開されました。
https://forum.kopano.io/topic/4069/statement-regarding-the-closure-of-the-kopano-community-forum-and-the-end-of-the-community-edition
しかし、2023/4/15に新しいメンテナーが現れたことで現在もオープンソースとしてメンテナンスされています。（メンテナーの方に感謝）
https://kopano.com/blog/z-push-has-a-new-home-and-a-new-maintainer/

本記事は、PHP8.4環境で、PHPとPHP-IMAPインストール環境において、z-pushによるプッシュ通知環境を構築する方法を紹介します。

## 0.準備作業
メールサーバー（IMAP）の準備
Apache及びPHP 8.4環境の用意
PHP-IMAP(PHP 8.4から別モジュールでビルドが必要）


## 1.インストール
```
cd /usr/local/src
wget https://github.com/Z-Hub/Z-Push/archive/refs/tags/2.7.5.tar.gz
tar xvzf 2.7.5.tar.gz
cd Z-Push-2.7.5
cp -rf src /docs/xxx.example.com  #Apahceのドキュメントディレクトリ
chown daemon:daemon -R /docs/xyz.example.com
```

## 2.Apacheに設定を入れる

```
vi /usr/local/apache2/conf/extra/httpd-ssl.conf

<VirtualHost _default_:443>
    DocumentRoot    /docs/xyz.example.com

    #Z-push Added 
    <IfModule mod_alias.c>
        Alias /Microsoft-Server-ActiveSync /docs/xyz.exampel.com/index.php
    </IfModule>

    <IfModule mod_alias.c>
        Alias /AutoDiscover/AutoDiscover.xml "/docs/xyz.example.com/autodiscover/autodiscover.php"
        Alias /Autodiscover/Autodiscover.xml "/docs/xyz.example.com/autodiscover/autodiscover.php"
        Alias /autodiscover/autodiscover.xml "/docs/xyz.example.com/autodiscover/autodiscover.php"
    </IfModule>


    <Directory /usr/share/z-push>
        # Don't list a directory index, follow symlinks (maybe state dir is somewhere linked)
        DirectoryIndex index.php
        Options -Indexes +FollowSymLinks

        # Security
        # Don't allow .htaccess Overrides, disallow access to files
        AllowOverride none
        <IfModule !mod_authz_core.c>
            Order allow,deny
            allow from all
        </IfModule>
        <IfModule mod_authz_core.c>
            Require all granted
        </IfModule>

        <Files "config.php">
            <IfModule !mod_authz_core.c>
                Deny from All
            </IfModule>
            <IfModule mod_authz_core.c>
                Require all denied
            </IfModule>
        </Files>
    </Directory>  
    #Z-push ---end---

    ServerName       xyz.example.com:443
    ServerAdmin      system@xyz.exaple.com
    ErrorLog         /usr/local/apache2/logs/xyz.example.com-error_log
    TransferLog      /usr/local/apache2/logs/xyz.example.com-access_log

    #SSL Engine Switch:
    SSLEngine on
    SSLCertificateFile       /etc/letsencrypt/live/xyz.example.com/cert.pem
    SSLCertificateKeyFile    /etc/letsencrypt/live/xyz.example.com/privkey.pem
    SSLCertificateChainFile  /etc/letsencrypt/live/xyz.example.com/chain.pem

    #SSL Engine Options:
    #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory "/usr/local/apache2/cgi-bin">
        SSLOptions +StdEnvVars
    </Directory>

    #SSL Protocol Adjustments:
    #"force-response-1.0" for this.
    BrowserMatch "MSIE [2-5]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0

    #   Per-Server Logging:
    #   compact non-error SSL logfile on a virtual host basis.
    CustomLog "/usr/local/apache2/logs/ssl_request_log" \
              "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

</VirtualHost>
```

## 3.Z-pushに設定を入れる

```
vi /docs/xyz.example.com/config.php
```
```
#以下を変更
define('TIMEZONE', 'Asia/Tokyo');
define('STATE_DIR', '/docs/xyz.example.com/');
define('LOGFILEDIR', '/var/log/z-push/');
define('BACKEND_PROVIDER', 'BackendIMAP');

#以下を追加
define('IMAP_SERVER', 'localhost');

// connecting to default port (143)
define('IMAP_PORT', 143);

// best cross-platform compatibility (see http://php.net/imap_open for options)
define('IMAP_OPTIONS', '/notls/norsh');
#define('IMAP_OPTIONS', '/ssl/validate-cert');

// Since I know you won't configure this, I will raise an error unless you do.
// When configured set this to true to remove the error
define('IMAP_FOLDER_CONFIGURED', true);

//'@mydomain.com' - the username is used and the given string will be appended
define('IMAP_DEFAULTFROM', '@example.com');

// smtp => direct connection against SMTP
define('IMAP_SMTP_METHOD', 'smtp');

define('IMAP_FOLDER_PREFIX', '');
define('IMAP_FOLDER_PREFIX_IN_INBOX', false);
define('IMAP_FOLDER_INBOX', 'INBOX');
define('IMAP_FOLDER_SENT', 'INBOX.Sent');
define('IMAP_FOLDER_DRAFT', 'INBOX.Drafts');
define('IMAP_FOLDER_TRASH', 'INBOX.Trash');
define('IMAP_FOLDER_SPAM', 'INBOX.Spam');
define('IMAP_FOLDER_ARCHIVE', '');              
```

### 諸設定を入れる
```
mkdir -p /var/log/z-push/
chown daemon:daemon -R /docs/notif.example.com/
chown daemon:daemon -R /var/log/z-push/
```

### ログロテーと設定
```
cat > /etc/logrotate.d/z-push << EOF
/var/log/z-push/*.log
{
    missingok
    sharedscripts
    postrotate
        systemctl restart httpd
    endscript
}
EOF
```