さくらのレンタルサーバでDKIM対応

さくらのレンタルサーバはメール送信ドメイン認証技術DKIM に対応してませんが、特定の条件下で送信されるメールのみ DKIM に対応できたので手順を公開します。(※RainLoop は適当にインストールしてください)

・仕組み

php.ini の sendmail_path を変更し、 php のmail関数で送信されるメールを自作のスクリプト経由で送信されるように変更する。スクリプトは、 “opendkimの起動→sendmailでメール送信→opendkimの停止”をする。さくらのレンタルサーバでは常駐プロセスの起動は禁止されているので、メール送信ごとに opendkimの起動/停止をするようにしている。

・条件

  1. 該当ドメインの TXT レコードに DKIM の公開鍵を登録できること
  2. メールクライアントは Webメールの RainLoop を さくらのレンタルサーバにインストールし、使用すること。
  3. 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署名される。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)