目次
qmail-remote に SMTP-AUTH対応させる(SMTPクライアントになりきってもらう)
2008年07月22日 23時32分22秒
これは何?
これは、qmailの構成プログラムである qmail-remote にSMTP-AUTH対応させた際のメモ。 OSは FreeBSD/amd64 7.0RELEASE 、qmailはportsで導入した qmail-1.03_7 です。
ISPがSMTPを潰しました
まぁ、去年・一昨年くらいから「停止するるよぅ」っていってましたから。 一応メールを出して確認したのですがヘルプデスクの回答は、「SMTP-AUTH対応のサーバに切り替えてくれ」しか書いてない。 こちらの質問に全く答えてないし。 この回答は予想通りではあるけど、もうちっときちんとした回答できないかなぁ。
やるべき事
こちらは、室内にqmailを使ったメールサーバがあり、室内から出すメールはこのメールサーバがISPのSMTPサーバへメールを転送していました。 このISPのSMTPサーバが使用不能となり、新たな SMTP-AUTH対応の SMTPサーバを利用する必要があります。
しかし、室内のqmailは素のqmailなので、SMTP-AUTH に対応していません。
qmail-remoteへのパッチ
今回やりたいことは、お部屋のqmailにSMTP-AUTHをおしゃべりさせてISPのメールサーバに接続できる様にする事です。 お部屋のqmailがメール送信の際にユーザに対してアカウントを要求する、という話とは全く違うのでご注意を。 グーグル先生にお伺いを立てたところ、 http://search.luky.org/linux-users.a/msg02384.html を通して http://tomclegg.net/qmail/#qmail-smtpd-auth が見つかりました。 グーグル様さまです。
http://tomclegg.net/qmail/#qmail-smtpd-auth の説明どおりにオペレーションを行うと、残念ですがパッチはあたりません。 このパッチは素のqmailに対してのものなので、portsで展開された他のパッチが当たったソースには適用できません。 ただ、内容を見た限りだとそれほど大量なパッチではないので、手作業で修正してみました。
ソース qmail-remote.c は以下の様になります。
chopin# pwd /usr/ports/mail/qmail/work/qmail-1.03 chopin# chopin# diff -c qmail-remote.c.orig qmail-remote.c *** qmail-remote.c.orig 2008-07-22 21:55:44.000000000 +0900 --- qmail-remote.c 2008-07-22 22:34:02.000000000 +0900 *************** *** 45,50 **** --- 45,52 ---- struct constmap maproutes; stralloc host = {0}; stralloc sender = {0}; + stralloc auth_smtp_user = {0}; + stralloc auth_smtp_pass = {0}; saa reciplist = {0}; *************** *** 225,246 **** unsigned long code; int flagbother; int i; code = smtpcode(); if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed"); if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */ if (code != 220) quit("ZConnected to "," but greeting failed"); ! substdio_puts(&smtpto,"HELO "); substdio_put(&smtpto,helohost.s,helohost.len); substdio_puts(&smtpto,"\r\n"); substdio_flush(&smtpto); ! if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); ! ! substdio_puts(&smtpto,"MAIL FROM:<"); ! substdio_put(&smtpto,sender.s,sender.len); ! substdio_puts(&smtpto,">\r\n"); ! substdio_flush(&smtpto); code = smtpcode(); if (code >= 500) quit("DConnected to "," but sender was rejected"); if (code >= 400) quit("ZConnected to "," but sender was rejected"); --- 227,284 ---- unsigned long code; int flagbother; int i; + stralloc slop = {0}; code = smtpcode(); if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed"); if (code >= 400 && code < 500) return; /* try next MX, see RFC-2821 */ if (code != 220) quit("ZConnected to "," but greeting failed"); ! substdio_puts(&smtpto,"EHLO "); substdio_put(&smtpto,helohost.s,helohost.len); substdio_puts(&smtpto,"\r\n"); substdio_flush(&smtpto); ! if (smtpcode() != 250) { ! substdio_puts(&smtpto,"HELO "); ! substdio_put(&smtpto,helohost.s,helohost.len); ! substdio_puts(&smtpto,"\r\n"); ! substdio_flush(&smtpto); ! if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); ! } ! i = 0; ! while((i += str_chr(smtptext.s+i,'\n') + 1) && (i+14 < smtptext.len) && ! str_diffn(smtptext.s+i+4,"AUTH LOGIN\n",11) && ! str_diffn(smtptext.s+i+4,"AUTH LOGIN ",11) && ! str_diffn(smtptext.s+i+4,"AUTH PLAIN LOGIN\n",17) && ! str_diffn(smtptext.s+i+4,"AUTH PLAIN LOGIN ",17) && ! str_diffn(smtptext.s+i+4,"AUTH=LOGIN\n",11) && ! str_diffn(smtptext.s+i+4,"AUTH=LOGIN ",11)); ! if ((i+14 < smtptext.len) && auth_smtp_user.len && auth_smtp_pass.len) { ! substdio_puts(&smtpto,"AUTH LOGIN\r\n"); ! substdio_flush(&smtpto); ! if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)"); ! if (b64encode(&auth_smtp_user,&slop) < 0) temp_nomem(); ! substdio_put(&smtpto,slop.s,slop.len); ! substdio_puts(&smtpto,"\r\n"); ! substdio_flush(&smtpto); ! if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username)"); ! if (b64encode(&auth_smtp_pass,&slop) < 0) temp_nomem(); ! substdio_put(&smtpto,slop.s,slop.len); ! substdio_puts(&smtpto,"\r\n"); ! substdio_flush(&smtpto); ! if (smtpcode() != 235) quit("ZConnected to "," but authentication was rejected (password)"); ! substdio_puts(&smtpto,"MAIL FROM:<"); ! substdio_put(&smtpto,sender.s,sender.len); ! substdio_puts(&smtpto,"> AUTH=<"); ! substdio_put(&smtpto,sender.s,sender.len); ! substdio_puts(&smtpto,">\r\n"); ! substdio_flush(&smtpto); ! } else { ! substdio_puts(&smtpto,"MAIL FROM:<"); ! substdio_put(&smtpto,sender.s,sender.len); ! substdio_puts(&smtpto,">\r\n"); ! substdio_flush(&smtpto); ! } code = smtpcode(); if (code >= 500) quit("DConnected to "," but sender was rejected"); if (code >= 400) quit("ZConnected to "," but sender was rejected"); *************** *** 445,451 **** char **argv; { static ipalloc ip = {0}; ! int i; unsigned long random; char **recips; unsigned long prefme; --- 483,489 ---- char **argv; { static ipalloc ip = {0}; ! int i,j; unsigned long random; char **recips; unsigned long prefme; *************** *** 461,466 **** --- 499,507 ---- if (!stralloc_copys(&host,argv[1])) temp_nomem(); + if (!stralloc_copys(&auth_smtp_user,"")) temp_nomem(); + if (!stralloc_copys(&auth_smtp_pass,"")) temp_nomem(); + relayhost = 0; for (i = 0;i <= host.len;++i) if ((i == 0) || (i == host.len) || (host.s[i] == '.')) *************** *** 469,474 **** --- 510,525 ---- if (relayhost && !*relayhost) relayhost = 0; if (relayhost) { + i = str_chr(relayhost,' '); + if (relayhost[i]) { + j = str_chr(relayhost + i + 1,' '); + if (relayhost[j]) { + relayhost[i] = 0; + relayhost[i + j + 1] = 0; + if (!stralloc_copys(&auth_smtp_user,relayhost + i + 1)) temp_nomem(); + if (!stralloc_copys(&auth_smtp_pass,relayhost + i + j + 2)) temp_nomem(); + } + } i = str_chr(relayhost,':'); if (relayhost[i]) { scan_ulong(relayhost + i + 1,&smtp_port);
Makefileはこんな感じ。
chopin# pwd /usr/ports/mail/qmail/work/qmail-1.03 chopin# chopin# diff -c Makefile.orig Makefile *** Makefile.orig 2008-07-22 21:55:44.000000000 +0900 --- Makefile 2008-07-22 22:07:22.000000000 +0900 *************** *** 1502,1513 **** load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \ timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o strsalloc.o ipme.o quote.o \ ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \ ! substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib ./load qmail-remote control.o constmap.o timeoutread.o \ timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \ ipalloc.o strsalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ ! str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` qmail-remote.0: \ qmail-remote.8 --- 1502,1513 ---- load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \ timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o strsalloc.o ipme.o quote.o \ ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \ ! substdio.a error.a str.a fs.a auto_qmail.o base64.o dns.lib socket.lib ./load qmail-remote control.o constmap.o timeoutread.o \ timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \ ipalloc.o strsalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ ! str.a fs.a auto_qmail.o base64.o `cat dns.lib` `cat socket.lib` qmail-remote.0: \ qmail-remote.8
smtproutesへの記述
パッチを当てた事で、ファイル smtproutes の記述形式がちょっぴり変わります。 例えば、
:smtp.hogehoge.jp
の smtp.hogehoge.jp が廃止され、asmtp.hogehoge.jp となり、ポート 784 を指定する必要が出た場合、
:asmtp.hogehoge.jp:784
ユーザID,パスワードも必要な場合は、
:asmtp.hogehoge.jp:784 userid password
となります。