さくらのレンタルサーバはメール送信ドメイン認証技術の DKIM に対応してませんが、特定の条件下で送信されるメールのみ DKIM に対応できたので手順を公開します。(※RainLoop は適当にインストールしてください)
・仕組み
php.ini の sendmail_path を変更し、 php のmail関数で送信されるメールを自作のスクリプト経由で送信されるように変更する。スクリプトは、 “opendkimの起動→sendmailでメール送信→opendkimの停止”をする。さくらのレンタルサーバでは常駐プロセスの起動は禁止されているので、メール送信ごとに opendkimの起動/停止をするようにしている。
・条件
- 該当ドメインの TXT レコードに DKIM の公開鍵を登録できること
- メールクライアントは Webメールの RainLoop を さくらのレンタルサーバにインストールし、使用すること。
- RainLoop から送信するメールの Bcc は未対応。
1. OSと sendmail のバージョンの確認
#-- OSの確認
uname -a
FreeBSD www439.sakura.ne.jp 11.2-RELEASE-p9 FreeBSD 11.2-RELEASE-p9 #0: Tue Feb 5 15:30:36 UTC 2019 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64
#-- sendmail のバージョンの確認
sendmail -bt -d0.1 | grep Version
Version 8.15.2
2. opendkim の インストール
#-- opendkim のインストール
mkdir -p ~/mail/source
cd ~/mail/source
#-- opendkim-2.10.3.tar.gz をダウンロードし ~/mail/source/opendkim-2.10.3.tar.gz に 用意
tar xvzf opendkim-2.10.3.tar.gz
cd opendkim-2.10.3
./configure --prefix=${HOME}/mail/opendkim
make
make install
mkdir -p ~/mail/opendkim/{etc/key,run}
#-- 設定ファイルの用意
cd ~/mail/opendkim/etc/
DOMAIN=examle.com
SELECTOR=default
cat <<_EOF_> opendkim.conf
Mode s
UserID ${USER}:users
Socket unix:/home/${USER}/mail/opendkim/run/opendkim.socket
Umask 002
SoftwareHeader no
Canonicalization relaxed/simple
Domain ${DOMAIN}
Selector ${SELECTOR}
MinimumKeyBits 1024
KeyFile /home/${USER}/mail/opendkim/etc/key/${SELECTOR}.private
PidFile /home/${USER}/mail/opendkim/run/opendkim.pid
_EOF_
#-- 秘密鍵、公開鍵の作成
~/mail/opendkim/sbin/opendkim-genkey -D ~/mail/opendkim/etc/key -d ${DOMAIN} -s ${SELECTOR}
#-- default.txt の内容を DNSに登録する
cat key/default.txt
default._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC82amdPQIlaS2HWexxjqNcTURhGtPWUIbWG1G+IpZySPSdO6vuDJtLiZx3fAAMt2pF7FXk6rN91YobbD9PU0TOWhe5ovFiJEggRWj3OGZlScSOBn7fHpd6Cbh1OuqwSVbQlDf6dGgMXIPloYlwGry8W3NLxVI4NBw5xQ9VNT3GLwIDAQAB" ) ; ----- DKIM key default for examle.com
3. submit.cf の作成
#-- opendkim を使用してメールを送信する為の設定ファイル(submit.cf)を作成
cd ~/mail
mkdir mqueue tmp log
cp -pr /usr/share/sendmail/cf .
cd cf/cf
#-- submit_tmp.mc を editor で作成
vi submit_tmp.mc
#-- ここから
divert(0)dnl
VERSIONID(`$Id: submit.mc,v 8.15 2019-06-22 13:12:46 ca Exp $')
define(`confCF_VERSION', `Submit')dnl
define(`__OSTYPE__',`')dnl dirty hack to keep proto.m4 from complaining
define(`_USE_DECNET_SYNTAX_', `1')dnl support DECnet
define(`confTIME_ZONE', `USE_TZ')dnl
define(`confDONT_INIT_GROUPS', `True')dnl
define(`confRUN_AS_USER', `_USER_')dnl
define(`confTRUSTED_USER',`_USER_')dnl
define(`confTRUSTED_USERS',`_USER_')dnl
define(`MSP_QUEUE_DIR',`/home/_USER_/mail/mqueue')dnl
define(`STATUS_FILE', `/home/_USER_/mail/sm-client.st')dnl
define(`confPID_FILE',`/home/_USER_/mail/sm-client.pid')dnl
define(`confRECEIVED_HEADER', `$?sfrom $s $.$?_
$.$?{auth_type}(authenticated$?{auth_ssf} (${auth_ssf} bits)$.)
$.by $j $?r with $r$. id $i$?{tls_version}
(using ${tls_version} with cipher ${cipher} (${cipher_bits} bits) verified ${verify})$.$?u
for $u; $|;
$.$b')dnl
INPUT_MAIL_FILTER(`opendkim',`S=unix:/home/_USER_/mail/opendkim/run/opendkim.socket')dnl
FEATURE(`msp', `[127.0.0.1]')dnl
#-- ここまで
#-- submit.cf を作成
sed "s/_USER_/${USER}/" submit_tmp.mc > submit.mc
make submit.cf
cp -p submit.cf ~/mail/
4. sendmail.sh を作成
cd ~/mail
vi sendmail_tmp.sh
#-- ここから
#!/bin/sh
DIR=/home/_USER_/mail
DEBUG=${DIR}/log/debug.log
(
OPENDKIM_PID=${DIR}/opendkim/run/opendkim.pid
OPENDKIM_BIN=${DIR}/opendkim/sbin/opendkim
#-- remove old mail data
find ${DIR}/tmp -mtime +7 -type f -exec rm {} \;
#-- check opendkim already working
while :
do
if [ -f "${OPENDKIM_PID}" ]
then
if [ $(stat -f %m ${OPENDKIM_PID}) -ge $(($(date +%s)+10)) ]
then
break
else
sleep 5
fi
else
break
fi
done
#-- save mail data
UNIXTIME=$(date +%s)
TMP=${DIR}/tmp/T${UNIXTIME}-$$.txt
cat - >> ${TMP}
#-- start opendkim
${OPENDKIM_BIN}
#-- create mail queue
QUEUE=${DIR}/tmp/Q${UNIXTIME}-$$.txt
printf "HELO $(hostname)\r\n" > ${QUEUE}
FROM=$(awk '/^From: /{print $2}' ${TMP} | head -1 )
printf "MAIL FROM: ${FROM}\r\n" >> ${QUEUE}
cat ${TMP} | perl -ne 'BEGIN{$read=0;}{if(/^To:|^Cc:/){ $read=1; } elsif (/^\w|^$/){ $read=0;}
if ($read==1) { s/(^\w+:|\s)//g; push @address,(split /,/);}END{foreach (@address) { print "RCPT TO: $_\r\n"} print "DATA\r\n";}}' >> ${QUEUE}
cat ${TMP} >> ${QUEUE}
printf ".\r\n" >> ${QUEUE}
#-- send email
cat ${QUEUE} | /usr/sbin/sendmail -C${DIR}/submit.cf -v -i -t -bs
sleep 3
#-- stop opendkim
kill $(cat ${OPENDKIM_PID}) && rm -f ${OPENDKIM_PID}
) > ${DEBUG} 2>&1
#-- ここまで
sed "s/_USER_/${USER}/" sendmail_tmp.sh > sendmail.sh
chmod 755 sendmail.sh
rm -f sendmail_tmp.sh
5. php.ini の設定変更
cat <<"_EOF_"> /home/${USER}/www/php.ini
sendmail_path = /home/${USER}/mail/sendmail.sh
_EOF_
6. RainLoop の SMTP 設定変更
RainLoop の ドメイン設定にて “PHP mail() 関数を使用する (beta)” を有効にする
これで RainLoop から送信するメール(To,Cc) が DKIM署名される。